react-native-media-notification 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/LICENSE +20 -0
  2. package/MediaControls.podspec +30 -0
  3. package/README.md +237 -0
  4. package/android/build.gradle +89 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +29 -0
  7. package/android/src/main/java/com/mediacontrols/AudioFocusListener.kt +79 -0
  8. package/android/src/main/java/com/mediacontrols/Controls.kt +22 -0
  9. package/android/src/main/java/com/mediacontrols/CustomCommandButton.kt +72 -0
  10. package/android/src/main/java/com/mediacontrols/MediaControlsModule.kt +188 -0
  11. package/android/src/main/java/com/mediacontrols/MediaControlsPackage.kt +36 -0
  12. package/android/src/main/java/com/mediacontrols/MediaControlsPlayer.kt +321 -0
  13. package/android/src/main/java/com/mediacontrols/MediaControlsService.kt +233 -0
  14. package/android/src/main/java/com/mediacontrols/MediaNotificationProvider.kt +74 -0
  15. package/ios/MediaControls.h +5 -0
  16. package/ios/MediaControls.mm +300 -0
  17. package/lib/module/NativeMediaControls.js +7 -0
  18. package/lib/module/NativeMediaControls.js.map +1 -0
  19. package/lib/module/index.js +75 -0
  20. package/lib/module/index.js.map +1 -0
  21. package/lib/module/package.json +1 -0
  22. package/lib/typescript/package.json +1 -0
  23. package/lib/typescript/src/NativeMediaControls.d.ts +31 -0
  24. package/lib/typescript/src/NativeMediaControls.d.ts.map +1 -0
  25. package/lib/typescript/src/index.d.ts +34 -0
  26. package/lib/typescript/src/index.d.ts.map +1 -0
  27. package/package.json +169 -0
  28. package/src/NativeMediaControls.ts +54 -0
  29. package/src/index.tsx +87 -0
@@ -0,0 +1 @@
1
+ {"version":3,"names":["MediaControls","ALL_MEDIA_EVENTS","EventEmitter","eventEmitter","unsubscribe","setUpNativeEventListener","onEvent","event","command","seekPosition","emit","position","updateMetadata","metadata","stopMediaNotification","enableAudioInterruption","enabled","enableBackgroundMode","setControlEnabled","name","includes","Error","addEventListener","handler","addListener","removeAllListeners","forEach","e"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,aAAa,IAClBC,gBAAgB,QAGX,0BAAuB;AAE9B,SAASC,YAAY,QAA2B,WAAW;AAO3D,MAAMC,YAAY,GAAG,IAAID,YAAY,CAAC,CAAC;AACvC,IAAIE,WAA2C,GAAG,IAAI;AAEtD,MAAMC,wBAAwB,GAAGA,CAAA,KAAM;EACrC,IAAID,WAAW,EAAE;EAEjBA,WAAW,GAAGJ,aAAa,CAACM,OAAO,CAAEC,KAAK,IAAK;IAC7C,MAAM;MAAEC,OAAO;MAAEC;IAAa,CAAC,GAAGF,KAAK;IACvCJ,YAAY,CAACO,IAAI,CAACF,OAAO,EAAE;MAAEG,QAAQ,EAAEF;IAAa,CAAC,CAAC;EACxD,CAAC,CAAC;AACJ,CAAC;;AAED;AACA;AACA;AACA,OAAO,eAAeG,cAAcA,CAClCC,QAA4B,EACb;EACf,OAAOb,aAAa,CAACY,cAAc,CAACC,QAAQ,CAAC;AAC/C;;AAEA;AACA;AACA;AACA,OAAO,eAAeC,qBAAqBA,CAAA,EAAkB;EAC3D,OAAOd,aAAa,CAACc,qBAAqB,CAAC,CAAC;AAC9C;;AAEA;AACA;AACA;AACA,OAAO,eAAeC,uBAAuBA,CAACC,OAAgB,EAAiB;EAC7E,OAAOhB,aAAa,CAACe,uBAAuB,CAACC,OAAO,CAAC;AACvD;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACD,OAAgB,EAAQ;EAC3DhB,aAAa,CAACiB,oBAAoB,CAACD,OAAO,CAAC;AAC7C;AAEA,OAAO,SAASE,iBAAiBA,CAACC,IAAkB,EAAEH,OAAgB,EAAQ;EAC5E,IAAI,CAACf,gBAAgB,CAACmB,QAAQ,CAACD,IAAI,CAAC,EAAE;IACpC,MAAM,IAAIE,KAAK,CAAC,gCAAgCF,IAAI,EAAE,CAAC;EACzD;EACAnB,aAAa,CAACkB,iBAAiB,CAACC,IAAI,EAAEH,OAAO,CAAC;AAChD;;AAEA;AACA;AACA;AACA,OAAO,SAASM,gBAAgBA,CAC9Bf,KAAwB,EACxBgB,OAA+C,EAC5B;EACnBlB,wBAAwB,CAAC,CAAC;EAC1B,OAAOF,YAAY,CAACqB,WAAW,CAACjB,KAAK,EAAEgB,OAAO,CAAC;AACjD;;AAEA;AACA;AACA;AACA,OAAO,SAASE,kBAAkBA,CAAClB,KAAyB,EAAQ;EAClE,IAAIA,KAAK,EAAE;IACTJ,YAAY,CAACsB,kBAAkB,CAAClB,KAAK,CAAC;EACxC,CAAC,MAAM;IACLN,gBAAgB,CAACyB,OAAO,CAAEC,CAAC,IAAKxB,YAAY,CAACsB,kBAAkB,CAACE,CAAC,CAAC,CAAC;EACrE;AACF;;AAEA","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,31 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import type { EventEmitter } from 'react-native/Libraries/Types/CodegenTypes';
3
+ export declare const ALL_MEDIA_EVENTS: readonly ["play", "pause", "stop", "skipToNext", "skipToPrevious", "seekForward", "seekBackward", "seek", "shuffle", "repeatMode"];
4
+ export type MediaControl = (typeof ALL_MEDIA_EVENTS)[number];
5
+ export type MediaControlEvent = MediaControl | 'duck' | 'unDuck';
6
+ export interface MediaTrackMetadata {
7
+ title: string;
8
+ artist: string;
9
+ album?: string;
10
+ duration?: number;
11
+ artwork?: string;
12
+ position?: number;
13
+ isPlaying?: boolean;
14
+ repeatMode?: 'off' | 'one' | 'all';
15
+ shuffle?: boolean;
16
+ }
17
+ export interface NativeEvent {
18
+ command: string;
19
+ seekPosition?: number;
20
+ }
21
+ export interface Spec extends TurboModule {
22
+ setControlEnabled(name: string, enabled: boolean): void;
23
+ updateMetadata(metadata: MediaTrackMetadata): Promise<void>;
24
+ stopMediaNotification(): Promise<void>;
25
+ enableAudioInterruption(enabled: boolean): Promise<void>;
26
+ enableBackgroundMode(enabled: boolean): void;
27
+ readonly onEvent: EventEmitter<NativeEvent>;
28
+ }
29
+ declare const _default: Spec;
30
+ export default _default;
31
+ //# sourceMappingURL=NativeMediaControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeMediaControls.d.ts","sourceRoot":"","sources":["../../../src/NativeMediaControls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAG9E,eAAO,MAAM,gBAAgB,oIAWnB,CAAC;AACX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxD,cAAc,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAGvC,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGzD,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAG7C,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;CAC7C;;AAED,wBAAuE"}
@@ -0,0 +1,34 @@
1
+ import { type MediaControl, type MediaControlEvent } from './NativeMediaControls';
2
+ import type { MediaTrackMetadata } from './NativeMediaControls';
3
+ import { EventSubscription } from 'fbemitter';
4
+ export type MediaControlEventData = {
5
+ position?: number;
6
+ };
7
+ /**
8
+ * Updates the metadata for the current media track.
9
+ */
10
+ export declare function updateMetadata(metadata: MediaTrackMetadata): Promise<void>;
11
+ /**
12
+ * Stops the media notification and clears any ongoing playback state.
13
+ */
14
+ export declare function stopMediaNotification(): Promise<void>;
15
+ /**
16
+ * Activates or deactivates audio interruption handling.
17
+ */
18
+ export declare function enableAudioInterruption(enabled: boolean): Promise<void>;
19
+ /**
20
+ * Activates the audio session for media playback.
21
+ * Call this method before starting media playback to ensure proper Control Center integration.
22
+ */
23
+ export declare function enableBackgroundMode(enabled: boolean): void;
24
+ export declare function setControlEnabled(name: MediaControl, enabled: boolean): void;
25
+ /**
26
+ * Register an event listener for media control events.
27
+ */
28
+ export declare function addEventListener(event: MediaControlEvent, handler: (data?: MediaControlEventData) => void): EventSubscription;
29
+ /**
30
+ * Remove a specific event listener for media control events.
31
+ */
32
+ export declare function removeAllListeners(event?: MediaControlEvent): void;
33
+ export type { MediaTrackMetadata };
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAsB,EAEpB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAgB,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG5D,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAcF;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3D;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE3D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAK5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,qBAAqB,KAAK,IAAI,GAC9C,iBAAiB,CAGnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAMlE;AAGD,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,169 @@
1
+ {
2
+ "name": "react-native-media-notification",
3
+ "version": "0.2.0",
4
+ "description": "Display and manage media style notifications based on react-native-music-control",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-media-notification-example",
36
+ "test": "jest",
37
+ "typecheck": "tsc",
38
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
39
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
40
+ "prepare": "bob build",
41
+ "release": "dotenv release-it --only-version"
42
+ },
43
+ "keywords": [
44
+ "react-native",
45
+ "ios",
46
+ "android"
47
+ ],
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/mbpictures/react-native-media-notification.git"
51
+ },
52
+ "author": "Marius Butz <mbpictures13@gmail.com> (https://github.com/mbpictures)",
53
+ "license": "MIT",
54
+ "bugs": {
55
+ "url": "https://github.com/mbpictures/react-native-media-notification/issues"
56
+ },
57
+ "homepage": "https://github.com/mbpictures/react-native-media-notification#readme",
58
+ "publishConfig": {
59
+ "registry": "https://registry.npmjs.org/"
60
+ },
61
+ "dependencies": {
62
+ "fbemitter": "^3.0.0"
63
+ },
64
+ "devDependencies": {
65
+ "@commitlint/config-conventional": "^19.6.0",
66
+ "@eslint/compat": "^1.2.7",
67
+ "@eslint/eslintrc": "^3.3.0",
68
+ "@eslint/js": "^9.22.0",
69
+ "@evilmartians/lefthook": "^1.5.0",
70
+ "@react-native-community/cli": "15.0.0-alpha.2",
71
+ "@react-native/babel-preset": "0.79.2",
72
+ "@react-native/eslint-config": "^0.78.0",
73
+ "@release-it/conventional-changelog": "^9.0.2",
74
+ "@types/fbemitter": "^2.0.35",
75
+ "@types/jest": "^29.5.5",
76
+ "@types/react": "^19.0.0",
77
+ "commitlint": "^19.6.1",
78
+ "del-cli": "^5.1.0",
79
+ "dotenv-cli": "^10.0.0",
80
+ "eslint": "^9.22.0",
81
+ "eslint-config-prettier": "^10.1.1",
82
+ "eslint-plugin-prettier": "^5.2.3",
83
+ "jest": "^29.7.0",
84
+ "prettier": "^3.0.3",
85
+ "react": "19.0.0",
86
+ "react-native": "0.79.2",
87
+ "react-native-builder-bob": "^0.40.13",
88
+ "release-it": "^19.0.4",
89
+ "turbo": "^1.10.7",
90
+ "typescript": "^5.8.3"
91
+ },
92
+ "peerDependencies": {
93
+ "react": "*",
94
+ "react-native": "*"
95
+ },
96
+ "workspaces": [
97
+ "example"
98
+ ],
99
+ "packageManager": "yarn@3.6.1",
100
+ "jest": {
101
+ "preset": "react-native",
102
+ "modulePathIgnorePatterns": [
103
+ "<rootDir>/example/node_modules",
104
+ "<rootDir>/lib/"
105
+ ]
106
+ },
107
+ "commitlint": {
108
+ "extends": [
109
+ "@commitlint/config-conventional"
110
+ ]
111
+ },
112
+ "release-it": {
113
+ "git": {
114
+ "commitMessage": "chore: release ${version}",
115
+ "tagName": "v${version}"
116
+ },
117
+ "npm": {
118
+ "publish": true
119
+ },
120
+ "github": {
121
+ "release": true
122
+ },
123
+ "plugins": {
124
+ "@release-it/conventional-changelog": {
125
+ "preset": {
126
+ "name": "angular"
127
+ }
128
+ }
129
+ }
130
+ },
131
+ "prettier": {
132
+ "quoteProps": "consistent",
133
+ "singleQuote": true,
134
+ "tabWidth": 2,
135
+ "trailingComma": "es5",
136
+ "useTabs": false
137
+ },
138
+ "react-native-builder-bob": {
139
+ "source": "src",
140
+ "output": "lib",
141
+ "targets": [
142
+ [
143
+ "module",
144
+ {
145
+ "esm": true
146
+ }
147
+ ],
148
+ [
149
+ "typescript",
150
+ {
151
+ "project": "tsconfig.build.json"
152
+ }
153
+ ]
154
+ ]
155
+ },
156
+ "codegenConfig": {
157
+ "name": "MediaControlsSpec",
158
+ "type": "modules",
159
+ "jsSrcsDir": "src",
160
+ "android": {
161
+ "javaPackageName": "com.mediacontrols"
162
+ }
163
+ },
164
+ "create-react-native-library": {
165
+ "languages": "kotlin-objc",
166
+ "type": "turbo-module",
167
+ "version": "0.52.0"
168
+ }
169
+ }
@@ -0,0 +1,54 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+ import type { EventEmitter } from 'react-native/Libraries/Types/CodegenTypes';
4
+
5
+ // Event types
6
+ export const ALL_MEDIA_EVENTS = [
7
+ 'play',
8
+ 'pause',
9
+ 'stop',
10
+ 'skipToNext',
11
+ 'skipToPrevious',
12
+ 'seekForward',
13
+ 'seekBackward',
14
+ 'seek',
15
+ 'shuffle',
16
+ 'repeatMode',
17
+ ] as const;
18
+ export type MediaControl = (typeof ALL_MEDIA_EVENTS)[number];
19
+
20
+ export type MediaControlEvent = MediaControl | 'duck' | 'unDuck';
21
+
22
+ export interface MediaTrackMetadata {
23
+ title: string;
24
+ artist: string;
25
+ album?: string;
26
+ duration?: number;
27
+ artwork?: string;
28
+ position?: number;
29
+ isPlaying?: boolean;
30
+ repeatMode?: 'off' | 'one' | 'all';
31
+ shuffle?: boolean;
32
+ }
33
+
34
+ export interface NativeEvent {
35
+ command: string;
36
+ seekPosition?: number; // Position in seconds for seek events
37
+ }
38
+
39
+ export interface Spec extends TurboModule {
40
+ setControlEnabled(name: string, enabled: boolean): void;
41
+ updateMetadata(metadata: MediaTrackMetadata): Promise<void>;
42
+ stopMediaNotification(): Promise<void>;
43
+
44
+ // Audio interruption handling
45
+ enableAudioInterruption(enabled: boolean): Promise<void>;
46
+
47
+ // Audio session activation
48
+ enableBackgroundMode(enabled: boolean): void;
49
+
50
+ // Event listeners (native events will be emitted)
51
+ readonly onEvent: EventEmitter<NativeEvent>;
52
+ }
53
+
54
+ export default TurboModuleRegistry.getEnforcing<Spec>('MediaControls');
package/src/index.tsx ADDED
@@ -0,0 +1,87 @@
1
+ import MediaControls, {
2
+ ALL_MEDIA_EVENTS,
3
+ type MediaControl,
4
+ type MediaControlEvent,
5
+ } from './NativeMediaControls';
6
+ import type { MediaTrackMetadata } from './NativeMediaControls';
7
+ import { EventEmitter, EventSubscription } from 'fbemitter';
8
+ import { type EventSubscription as NativeEventSubscription } from 'react-native';
9
+
10
+ export type MediaControlEventData = {
11
+ position?: number; // für seek events
12
+ };
13
+
14
+ const eventEmitter = new EventEmitter();
15
+ let unsubscribe: NativeEventSubscription | null = null;
16
+
17
+ const setUpNativeEventListener = () => {
18
+ if (unsubscribe) return;
19
+
20
+ unsubscribe = MediaControls.onEvent((event) => {
21
+ const { command, seekPosition } = event;
22
+ eventEmitter.emit(command, { position: seekPosition });
23
+ });
24
+ };
25
+
26
+ /**
27
+ * Updates the metadata for the current media track.
28
+ */
29
+ export async function updateMetadata(
30
+ metadata: MediaTrackMetadata
31
+ ): Promise<void> {
32
+ return MediaControls.updateMetadata(metadata);
33
+ }
34
+
35
+ /**
36
+ * Stops the media notification and clears any ongoing playback state.
37
+ */
38
+ export async function stopMediaNotification(): Promise<void> {
39
+ return MediaControls.stopMediaNotification();
40
+ }
41
+
42
+ /**
43
+ * Activates or deactivates audio interruption handling.
44
+ */
45
+ export async function enableAudioInterruption(enabled: boolean): Promise<void> {
46
+ return MediaControls.enableAudioInterruption(enabled);
47
+ }
48
+
49
+ /**
50
+ * Activates the audio session for media playback.
51
+ * Call this method before starting media playback to ensure proper Control Center integration.
52
+ */
53
+ export function enableBackgroundMode(enabled: boolean): void {
54
+ MediaControls.enableBackgroundMode(enabled);
55
+ }
56
+
57
+ export function setControlEnabled(name: MediaControl, enabled: boolean): void {
58
+ if (!ALL_MEDIA_EVENTS.includes(name)) {
59
+ throw new Error(`Unknown media control event: ${name}`);
60
+ }
61
+ MediaControls.setControlEnabled(name, enabled);
62
+ }
63
+
64
+ /**
65
+ * Register an event listener for media control events.
66
+ */
67
+ export function addEventListener(
68
+ event: MediaControlEvent,
69
+ handler: (data?: MediaControlEventData) => void
70
+ ): EventSubscription {
71
+ setUpNativeEventListener();
72
+ return eventEmitter.addListener(event, handler);
73
+ }
74
+
75
+ /**
76
+ * Remove a specific event listener for media control events.
77
+ */
78
+ export function removeAllListeners(event?: MediaControlEvent): void {
79
+ if (event) {
80
+ eventEmitter.removeAllListeners(event);
81
+ } else {
82
+ ALL_MEDIA_EVENTS.forEach((e) => eventEmitter.removeAllListeners(e));
83
+ }
84
+ }
85
+
86
+ // Export types
87
+ export type { MediaTrackMetadata };