expo-native-track-player 0.1.1

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 (53) hide show
  1. package/ExpoNativeTrackPlayer.podspec +21 -0
  2. package/LICENSE +20 -0
  3. package/README.md +267 -0
  4. package/android/build.gradle +71 -0
  5. package/android/src/main/AndroidManifest.xml +12 -0
  6. package/android/src/main/java/com/exponativetrackplayer/ExpoNativeTrackPlayerModule.kt +528 -0
  7. package/android/src/main/java/com/exponativetrackplayer/ExpoNativeTrackPlayerPackage.kt +34 -0
  8. package/android/src/main/java/com/exponativetrackplayer/ExpoNativeTrackPlayerService.kt +118 -0
  9. package/ios/ExpoNativeTrackPlayer.h +6 -0
  10. package/ios/ExpoNativeTrackPlayer.mm +475 -0
  11. package/lib/module/NativeExpoNativeTrackPlayer.js +5 -0
  12. package/lib/module/NativeExpoNativeTrackPlayer.js.map +1 -0
  13. package/lib/module/constants.js +31 -0
  14. package/lib/module/constants.js.map +1 -0
  15. package/lib/module/events.js +56 -0
  16. package/lib/module/events.js.map +1 -0
  17. package/lib/module/hooks.js +105 -0
  18. package/lib/module/hooks.js.map +1 -0
  19. package/lib/module/index.js +150 -0
  20. package/lib/module/index.js.map +1 -0
  21. package/lib/module/package.json +1 -0
  22. package/lib/module/types/ResourceObject.js +2 -0
  23. package/lib/module/types/ResourceObject.js.map +1 -0
  24. package/lib/module/types/Track.js +4 -0
  25. package/lib/module/types/Track.js.map +1 -0
  26. package/lib/module/types/TrackMetadataBase.js +2 -0
  27. package/lib/module/types/TrackMetadataBase.js.map +1 -0
  28. package/lib/typescript/package.json +1 -0
  29. package/lib/typescript/src/NativeExpoNativeTrackPlayer.d.ts +57 -0
  30. package/lib/typescript/src/NativeExpoNativeTrackPlayer.d.ts.map +1 -0
  31. package/lib/typescript/src/constants.d.ts +23 -0
  32. package/lib/typescript/src/constants.d.ts.map +1 -0
  33. package/lib/typescript/src/events.d.ts +163 -0
  34. package/lib/typescript/src/events.d.ts.map +1 -0
  35. package/lib/typescript/src/hooks.d.ts +12 -0
  36. package/lib/typescript/src/hooks.d.ts.map +1 -0
  37. package/lib/typescript/src/index.d.ts +65 -0
  38. package/lib/typescript/src/index.d.ts.map +1 -0
  39. package/lib/typescript/src/types/ResourceObject.d.ts +5 -0
  40. package/lib/typescript/src/types/ResourceObject.d.ts.map +1 -0
  41. package/lib/typescript/src/types/Track.d.ts +22 -0
  42. package/lib/typescript/src/types/Track.d.ts.map +1 -0
  43. package/lib/typescript/src/types/TrackMetadataBase.d.ts +18 -0
  44. package/lib/typescript/src/types/TrackMetadataBase.d.ts.map +1 -0
  45. package/package.json +172 -0
  46. package/src/NativeExpoNativeTrackPlayer.ts +70 -0
  47. package/src/constants.ts +40 -0
  48. package/src/events.ts +136 -0
  49. package/src/hooks.ts +149 -0
  50. package/src/index.tsx +250 -0
  51. package/src/types/ResourceObject.ts +4 -0
  52. package/src/types/Track.ts +23 -0
  53. package/src/types/TrackMetadataBase.ts +17 -0
@@ -0,0 +1,475 @@
1
+ #import "ExpoNativeTrackPlayer.h"
2
+ #import <AVFoundation/AVFoundation.h>
3
+ #import <React/RCTBridge.h>
4
+
5
+ @interface ExpoNativeTrackPlayer ()
6
+
7
+ @property (nonatomic, strong) AVPlayer *player;
8
+ @property (nonatomic, strong) NSMutableArray<NSDictionary *> *queue;
9
+ @property (nonatomic, assign) NSInteger currentIndex;
10
+ @property (nonatomic, copy) NSString *repeatMode;
11
+ @property (nonatomic, strong, nullable) NSNumber *loopStartMs;
12
+ @property (nonatomic, strong, nullable) NSNumber *loopEndMs;
13
+ @property (nonatomic, copy) NSString *playbackState;
14
+ @property (nonatomic, assign) float playbackRate;
15
+ @property (nonatomic, strong, nullable) id timeObserver;
16
+ @property (nonatomic, strong, nullable) id endObserver;
17
+
18
+ @end
19
+
20
+ @implementation ExpoNativeTrackPlayer
21
+
22
+ RCT_EXPORT_MODULE();
23
+ @synthesize bridge = _bridge;
24
+
25
+ static NSString *const ExpoNativeTrackPlayerEventPlaybackState = @"playback-state";
26
+ static NSString *const ExpoNativeTrackPlayerEventPlaybackProgress = @"playback-progress-updated";
27
+ static NSString *const ExpoNativeTrackPlayerEventPlaybackActiveTrackChanged =
28
+ @"playback-active-track-changed";
29
+ static NSString *const ExpoNativeTrackPlayerEventPlaybackQueueEnded =
30
+ @"playback-queue-ended";
31
+ static NSString *const ExpoNativeTrackPlayerEventQueueUpdated = @"queue-updated";
32
+
33
+ - (instancetype)init
34
+ {
35
+ if (self = [super init]) {
36
+ _player = [[AVPlayer alloc] init];
37
+ _queue = [NSMutableArray array];
38
+ _currentIndex = -1;
39
+ _repeatMode = @"off";
40
+ _playbackState = @"stopped";
41
+ _playbackRate = 1.0f;
42
+ [self configureAudioSession];
43
+ [self startLoopWatcher];
44
+ }
45
+ return self;
46
+ }
47
+
48
+ - (void)dealloc
49
+ {
50
+ if (_timeObserver != nil) {
51
+ [_player removeTimeObserver:_timeObserver];
52
+ _timeObserver = nil;
53
+ }
54
+ if (_endObserver != nil) {
55
+ [[NSNotificationCenter defaultCenter] removeObserver:_endObserver];
56
+ _endObserver = nil;
57
+ }
58
+ }
59
+
60
+ - (NSDictionary *)dictionaryFromTrack:(JS::NativeExpoNativeTrackPlayer::TrackMetadata &)track
61
+ {
62
+ NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
63
+ dictionary[@"id"] = track.id_();
64
+ dictionary[@"url"] = track.url();
65
+
66
+ if (track.title().length > 0) dictionary[@"title"] = track.title();
67
+ if (track.artist().length > 0) dictionary[@"artist"] = track.artist();
68
+ if (track.albumName().length > 0) dictionary[@"albumName"] = track.albumName();
69
+ if (track.artworkUri().length > 0) dictionary[@"artworkUri"] = track.artworkUri();
70
+ if (track.type().length > 0) dictionary[@"type"] = track.type();
71
+ if (track.userAgent().length > 0) dictionary[@"userAgent"] = track.userAgent();
72
+ if (track.contentType().length > 0) dictionary[@"contentType"] = track.contentType();
73
+ if (track.pitchAlgorithm().length > 0) dictionary[@"pitchAlgorithm"] = track.pitchAlgorithm();
74
+ if (track.composer().length > 0) dictionary[@"composer"] = track.composer();
75
+ if (track.conductor().length > 0) dictionary[@"conductor"] = track.conductor();
76
+ if (track.genre().length > 0) dictionary[@"genre"] = track.genre();
77
+ if (track.compilation().length > 0) dictionary[@"compilation"] = track.compilation();
78
+ if (track.subtitle().length > 0) dictionary[@"subtitle"] = track.subtitle();
79
+ if (track.description().length > 0) dictionary[@"description"] = track.description();
80
+ if (track.station().length > 0) dictionary[@"station"] = track.station();
81
+ if (track.trackNumber().has_value()) {
82
+ dictionary[@"trackNumber"] = @(track.trackNumber().value());
83
+ }
84
+ if (track.duration().has_value()) {
85
+ dictionary[@"duration"] = @(track.duration().value());
86
+ }
87
+ if (track.mediaType().has_value()) {
88
+ dictionary[@"mediaType"] = @(track.mediaType().value());
89
+ }
90
+
91
+ return dictionary;
92
+ }
93
+
94
+ - (NSNumber * _Nullable)nullableNumberFrom:(NSNumber *)value
95
+ {
96
+ if (value == (id)kCFNull) return nil;
97
+ return value;
98
+ }
99
+
100
+ - (void)addListener:(NSString *)eventName
101
+ {
102
+ }
103
+
104
+ - (void)removeListeners:(double)count
105
+ {
106
+ }
107
+
108
+ - (void)emitEvent:(NSString *)name body:(NSDictionary *)body
109
+ {
110
+ if (self.bridge == nil || name.length == 0) return;
111
+ NSArray *args = body != nil ? @[name, body] : @[name, [NSNull null]];
112
+ [self.bridge enqueueJSCall:@"RCTDeviceEventEmitter" method:@"emit" args:args completion:NULL];
113
+ }
114
+
115
+ - (void)emitPlaybackState
116
+ {
117
+ [self emitEvent:ExpoNativeTrackPlayerEventPlaybackState body:@{
118
+ @"state": self.playbackState ?: @"stopped"
119
+ }];
120
+ }
121
+
122
+ - (void)emitQueueUpdated
123
+ {
124
+ NSDictionary *payload = @{
125
+ @"count": @(self.queue.count),
126
+ @"trackIndex": @(self.currentIndex),
127
+ @"queue": [self.queue copy]
128
+ };
129
+ [self emitEvent:ExpoNativeTrackPlayerEventQueueUpdated body:payload];
130
+ }
131
+
132
+ - (void)emitTrackChanged
133
+ {
134
+ NSDictionary *track = nil;
135
+ if (self.currentIndex >= 0 && self.currentIndex < (NSInteger)self.queue.count) {
136
+ track = self.queue[(NSUInteger)self.currentIndex];
137
+ }
138
+ NSDictionary *payload = @{
139
+ @"trackIndex": @(self.currentIndex),
140
+ @"track": track ?: (id)kCFNull
141
+ };
142
+ [self emitEvent:ExpoNativeTrackPlayerEventPlaybackActiveTrackChanged body:payload];
143
+ }
144
+
145
+ - (void)emitPlaybackPositionWithPosition:(double)position
146
+ duration:(double)duration
147
+ trackIndex:(NSInteger)trackIndex
148
+ {
149
+ NSDictionary *payload = @{
150
+ @"position": @(position),
151
+ @"duration": @(duration),
152
+ @"trackIndex": @(trackIndex)
153
+ };
154
+ [self emitEvent:ExpoNativeTrackPlayerEventPlaybackProgress body:payload];
155
+ }
156
+
157
+ - (void)emitPlaybackQueueEnded
158
+ {
159
+ NSDictionary *payload = @{
160
+ @"trackIndex": @(self.currentIndex),
161
+ @"position": @([self getPosition].doubleValue)
162
+ };
163
+ [self emitEvent:ExpoNativeTrackPlayerEventPlaybackQueueEnded body:payload];
164
+ }
165
+
166
+ - (void)addToQueue:(JS::NativeExpoNativeTrackPlayer::TrackMetadata &)track
167
+ {
168
+ NSDictionary *dictionary = [self dictionaryFromTrack:track];
169
+ [self.queue addObject:dictionary];
170
+ [self emitQueueUpdated];
171
+ }
172
+
173
+ - (void)addQueue:(NSArray *)tracks
174
+ {
175
+ if (tracks == nil) return;
176
+ for (NSDictionary *track in tracks) {
177
+ if (![track isKindOfClass:[NSDictionary class]]) continue;
178
+ [self.queue addObject:track];
179
+ }
180
+ [self emitQueueUpdated];
181
+ }
182
+
183
+ - (NSArray<NSDictionary *> *)getQueue
184
+ {
185
+ return [self.queue copy];
186
+ }
187
+
188
+ - (void)removeFromQueue:(NSString *)trackId
189
+ {
190
+ if (trackId.length == 0) return;
191
+ __block NSInteger indexToRemove = NSNotFound;
192
+ [self.queue enumerateObjectsUsingBlock:^(NSDictionary *track, NSUInteger idx, BOOL *stop) {
193
+ if ([[track objectForKey:@"id"] isEqualToString:trackId]) {
194
+ indexToRemove = (NSInteger)idx;
195
+ *stop = YES;
196
+ }
197
+ }];
198
+ if (indexToRemove == NSNotFound) return;
199
+
200
+ [self.queue removeObjectAtIndex:indexToRemove];
201
+ if (indexToRemove == self.currentIndex) {
202
+ [self stopInternal];
203
+ self.currentIndex = -1;
204
+ [self emitTrackChanged];
205
+ } else if (indexToRemove < self.currentIndex) {
206
+ self.currentIndex -= 1;
207
+ [self emitTrackChanged];
208
+ }
209
+ [self emitQueueUpdated];
210
+ }
211
+
212
+ - (void)clearQueue
213
+ {
214
+ [self.queue removeAllObjects];
215
+ [self stopInternal];
216
+ self.currentIndex = -1;
217
+ [self emitQueueUpdated];
218
+ [self emitTrackChanged];
219
+ }
220
+
221
+ - (void)play:(NSNumber *)index
222
+ {
223
+ [self playInternal:[self nullableNumberFrom:index]];
224
+ }
225
+
226
+ - (void)pause
227
+ {
228
+ [self.player pause];
229
+ [self setPlaybackState:@"paused"];
230
+ }
231
+
232
+ - (void)stop
233
+ {
234
+ [self stopInternal];
235
+ }
236
+
237
+ - (void)skipToNext
238
+ {
239
+ [self playInternal:@(self.currentIndex + 1)];
240
+ }
241
+
242
+ - (void)skipToPrevious
243
+ {
244
+ [self playInternal:@(self.currentIndex - 1)];
245
+ }
246
+
247
+ - (void)skipToIndex:(double)index
248
+ {
249
+ [self playInternal:@((NSInteger)index)];
250
+ }
251
+
252
+ - (void)seekTo:(double)positionMs
253
+ {
254
+ CMTime position = CMTimeMakeWithSeconds(positionMs / 1000.0, 600);
255
+ [self.player seekToTime:position];
256
+ }
257
+
258
+ - (void)reset
259
+ {
260
+ [self.queue removeAllObjects];
261
+ [self stopInternal];
262
+ self.currentIndex = -1;
263
+ [self emitQueueUpdated];
264
+ [self emitTrackChanged];
265
+ }
266
+
267
+ - (void)setRepeatMode:(NSString *)mode startMs:(NSNumber *)startMs endMs:(NSNumber *)endMs
268
+ {
269
+ self.repeatMode = mode ?: @"off";
270
+ self.loopStartMs = [self nullableNumberFrom:startMs];
271
+ self.loopEndMs = [self nullableNumberFrom:endMs];
272
+ }
273
+
274
+ - (NSString *)getRepeatMode
275
+ {
276
+ return self.repeatMode;
277
+ }
278
+
279
+ - (NSDictionary * _Nullable)getCurrentTrack
280
+ {
281
+ if (self.currentIndex < 0 || self.currentIndex >= (NSInteger)self.queue.count) return nil;
282
+ return self.queue[self.currentIndex];
283
+ }
284
+
285
+ - (NSNumber *)getCurrentTrackIndex
286
+ {
287
+ return @(self.currentIndex);
288
+ }
289
+
290
+ - (NSNumber *)getPosition
291
+ {
292
+ return @(CMTimeGetSeconds([self.player currentTime]) * 1000.0);
293
+ }
294
+
295
+ - (NSNumber *)getDuration
296
+ {
297
+ double duration = CMTimeGetSeconds(self.player.currentItem.duration);
298
+ return @(isfinite(duration) ? duration * 1000.0 : 0.0);
299
+ }
300
+
301
+ - (NSString *)getPlaybackState
302
+ {
303
+ return self.playbackState;
304
+ }
305
+
306
+ - (void)setVolume:(double)volume
307
+ {
308
+ self.player.volume = (float)volume;
309
+ }
310
+
311
+ - (NSNumber *)getVolume
312
+ {
313
+ return @(self.player.volume);
314
+ }
315
+
316
+ - (void)setRate:(double)rate
317
+ {
318
+ self.playbackRate = (float)rate;
319
+ if ([self.playbackState isEqualToString:@"playing"]) {
320
+ [self.player playImmediatelyAtRate:self.playbackRate];
321
+ }
322
+ }
323
+
324
+ - (NSNumber *)getRate
325
+ {
326
+ return @(self.playbackRate);
327
+ }
328
+
329
+ - (void)playInternal:(NSNumber * _Nullable)index
330
+ {
331
+ if (self.queue.count == 0) return;
332
+ if (index != nil) {
333
+ NSInteger target = [index integerValue];
334
+ if (target < 0 || target >= (NSInteger)self.queue.count) return;
335
+ [self loadTrackAtIndex:target];
336
+ } else if (self.currentIndex < 0) {
337
+ [self loadTrackAtIndex:0];
338
+ }
339
+ [self.player playImmediatelyAtRate:self.playbackRate];
340
+ [self setPlaybackState:@"playing"];
341
+ }
342
+
343
+ - (void)loadTrackAtIndex:(NSInteger)index
344
+ {
345
+ NSDictionary *track = self.queue[index];
346
+ NSString *urlString = [track objectForKey:@"url"];
347
+ if (urlString.length == 0) return;
348
+ NSURL *url = [NSURL URLWithString:urlString];
349
+ if (!url) return;
350
+
351
+ AVPlayerItem *item = [AVPlayerItem playerItemWithURL:url];
352
+ [self.player replaceCurrentItemWithPlayerItem:item];
353
+ self.currentIndex = index;
354
+ [self observeItemEnd:item];
355
+ [self emitTrackChanged];
356
+ }
357
+
358
+ - (void)observeItemEnd:(AVPlayerItem *)item
359
+ {
360
+ if (self.endObserver != nil) {
361
+ [[NSNotificationCenter defaultCenter] removeObserver:self.endObserver];
362
+ }
363
+ __weak ExpoNativeTrackPlayer *weakSelf = self;
364
+ self.endObserver = [[NSNotificationCenter defaultCenter]
365
+ addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
366
+ object:item
367
+ queue:[NSOperationQueue mainQueue]
368
+ usingBlock:^(NSNotification *note) {
369
+ [weakSelf handleTrackEnded];
370
+ }];
371
+ }
372
+
373
+ - (void)handleTrackEnded
374
+ {
375
+ if ([self.repeatMode isEqualToString:@"track"]) {
376
+ [self.player seekToTime:kCMTimeZero];
377
+ [self.player playImmediatelyAtRate:self.playbackRate];
378
+ return;
379
+ }
380
+ if ([self.repeatMode isEqualToString:@"queue"]) {
381
+ NSInteger nextIndex = self.currentIndex + 1;
382
+ if (nextIndex >= (NSInteger)self.queue.count) {
383
+ [self loadTrackAtIndex:0];
384
+ } else {
385
+ [self loadTrackAtIndex:nextIndex];
386
+ }
387
+ [self.player playImmediatelyAtRate:self.playbackRate];
388
+ return;
389
+ }
390
+ if ([self.repeatMode isEqualToString:@"loop_portion"]) {
391
+ [self seekToLoopStart];
392
+ [self.player playImmediatelyAtRate:self.playbackRate];
393
+ return;
394
+ }
395
+ NSInteger nextIndex = self.currentIndex + 1;
396
+ if (nextIndex < (NSInteger)self.queue.count) {
397
+ [self loadTrackAtIndex:nextIndex];
398
+ [self.player playImmediatelyAtRate:self.playbackRate];
399
+ } else {
400
+ [self setPlaybackState:@"ended"];
401
+ [self emitPlaybackQueueEnded];
402
+ }
403
+ }
404
+
405
+ - (void)startLoopWatcher
406
+ {
407
+ __weak ExpoNativeTrackPlayer *weakSelf = self;
408
+ CMTime interval = CMTimeMakeWithSeconds(0.1, 600);
409
+ self.timeObserver = [self.player addPeriodicTimeObserverForInterval:interval
410
+ queue:dispatch_get_main_queue()
411
+ usingBlock:^(CMTime time) {
412
+ double positionMs = CMTimeGetSeconds(time) * 1000.0;
413
+ [weakSelf handleLoopPortionIfNeeded:positionMs];
414
+ double durationMs = 0.0;
415
+ AVPlayerItem *item = weakSelf.player.currentItem;
416
+ if (item != nil) {
417
+ durationMs = CMTimeGetSeconds(item.duration) * 1000.0;
418
+ if (isnan(durationMs) || isinf(durationMs)) {
419
+ durationMs = 0.0;
420
+ }
421
+ }
422
+ [weakSelf emitPlaybackPositionWithPosition:positionMs
423
+ duration:durationMs
424
+ trackIndex:weakSelf.currentIndex];
425
+ }];
426
+ }
427
+
428
+ - (void)handleLoopPortionIfNeeded:(double)positionMs
429
+ {
430
+ if (![self.repeatMode isEqualToString:@"loop_portion"]) return;
431
+ if (self.loopStartMs == nil || self.loopEndMs == nil) return;
432
+ double startMs = [self.loopStartMs doubleValue];
433
+ double endMs = [self.loopEndMs doubleValue];
434
+ if (endMs <= startMs) return;
435
+ if (positionMs >= endMs) {
436
+ [self seekToLoopStart];
437
+ }
438
+ }
439
+
440
+ - (void)seekToLoopStart
441
+ {
442
+ double startMs = self.loopStartMs != nil ? [self.loopStartMs doubleValue] : 0.0;
443
+ CMTime position = CMTimeMakeWithSeconds(startMs / 1000.0, 600);
444
+ [self.player seekToTime:position];
445
+ }
446
+
447
+ - (void)stopInternal
448
+ {
449
+ [self.player pause];
450
+ [self.player seekToTime:kCMTimeZero];
451
+ [self setPlaybackState:@"stopped"];
452
+ }
453
+
454
+ - (void)setPlaybackState:(NSString *)state
455
+ {
456
+ NSString *nextState = state ?: @"stopped";
457
+ _playbackState = [nextState copy];
458
+ [self emitPlaybackState];
459
+ }
460
+
461
+ - (void)configureAudioSession
462
+ {
463
+ AVAudioSession *session = [AVAudioSession sharedInstance];
464
+ NSError *error = nil;
465
+ [session setCategory:AVAudioSessionCategoryPlayback error:&error];
466
+ [session setActive:YES error:&error];
467
+ }
468
+
469
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
470
+ (const facebook::react::ObjCTurboModule::InitParams &)params
471
+ {
472
+ return std::make_shared<facebook::react::NativeExpoNativeTrackPlayerSpecJSI>(params);
473
+ }
474
+
475
+ @end
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('ExpoNativeTrackPlayer');
5
+ //# sourceMappingURL=NativeExpoNativeTrackPlayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeExpoNativeTrackPlayer.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAqEpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ export const TrackTypes = {
4
+ Default: 'default',
5
+ Dash: 'dash',
6
+ Hls: 'hls',
7
+ SmoothStreaming: 'smoothstreaming'
8
+ };
9
+ export const PitchAlgorithms = {
10
+ Linear: 'linear',
11
+ Music: 'music',
12
+ Voice: 'voice'
13
+ };
14
+ export const State = {
15
+ None: 'none',
16
+ Ready: 'ready',
17
+ Playing: 'playing',
18
+ Paused: 'paused',
19
+ Stopped: 'stopped',
20
+ Loading: 'loading',
21
+ Buffering: 'buffering',
22
+ Error: 'error',
23
+ Ended: 'ended'
24
+ };
25
+ export const RepeatModes = {
26
+ Off: 'off',
27
+ Track: 'track',
28
+ Queue: 'queue',
29
+ LoopPortion: 'loop_portion'
30
+ };
31
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TrackTypes","Default","Dash","Hls","SmoothStreaming","PitchAlgorithms","Linear","Music","Voice","State","None","Ready","Playing","Paused","Stopped","Loading","Buffering","Error","Ended","RepeatModes","Off","Track","Queue","LoopPortion"],"sourceRoot":"../../src","sources":["constants.ts"],"mappings":";;AAAA,OAAO,MAAMA,UAAU,GAAG;EACxBC,OAAO,EAAE,SAAS;EAClBC,IAAI,EAAE,MAAM;EACZC,GAAG,EAAE,KAAK;EACVC,eAAe,EAAE;AACnB,CAAU;AAIV,OAAO,MAAMC,eAAe,GAAG;EAC7BC,MAAM,EAAE,QAAQ;EAChBC,KAAK,EAAE,OAAO;EACdC,KAAK,EAAE;AACT,CAAU;AAKV,OAAO,MAAMC,KAA6B,GAAG;EAC3CC,IAAI,EAAE,MAAM;EACZC,KAAK,EAAE,OAAO;EACdC,OAAO,EAAE,SAAS;EAClBC,MAAM,EAAE,QAAQ;EAChBC,OAAO,EAAE,SAAS;EAClBC,OAAO,EAAE,SAAS;EAClBC,SAAS,EAAE,WAAW;EACtBC,KAAK,EAAE,OAAO;EACdC,KAAK,EAAE;AACT,CAAU;AAIV,OAAO,MAAMC,WAAW,GAAG;EACzBC,GAAG,EAAE,KAAK;EACVC,KAAK,EAAE,OAAO;EACdC,KAAK,EAAE,OAAO;EACdC,WAAW,EAAE;AACf,CAAU","ignoreList":[]}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ import { NativeEventEmitter } from 'react-native';
4
+ import ExpoNativeTrackPlayer from "./NativeExpoNativeTrackPlayer.js";
5
+ export const Event = {
6
+ PlayerError: 'player-error',
7
+ PlaybackState: 'playback-state',
8
+ PlaybackError: 'playback-error',
9
+ PlaybackQueueEnded: 'playback-queue-ended',
10
+ PlaybackActiveTrackChanged: 'playback-active-track-changed',
11
+ PlaybackPlayWhenReadyChanged: 'playback-play-when-ready-changed',
12
+ PlaybackProgressUpdated: 'playback-progress-updated',
13
+ PlaybackResume: 'android-playback-resume',
14
+ RemotePlay: 'remote-play',
15
+ RemotePlayPause: 'remote-play-pause',
16
+ RemotePause: 'remote-pause',
17
+ RemoteStop: 'remote-stop',
18
+ RemoteNext: 'remote-next',
19
+ RemotePrevious: 'remote-previous',
20
+ RemoteJumpForward: 'remote-jump-forward',
21
+ RemoteJumpBackward: 'remote-jump-backward',
22
+ RemoteSeek: 'remote-seek',
23
+ RemoteSetRating: 'remote-set-rating',
24
+ RemoteDuck: 'remote-duck',
25
+ RemoteLike: 'remote-like',
26
+ RemoteDislike: 'remote-dislike',
27
+ RemoteBookmark: 'remote-bookmark',
28
+ RemotePlayId: 'remote-play-id',
29
+ RemotePlaySearch: 'remote-play-search',
30
+ RemoteSkip: 'remote-skip',
31
+ MetadataChapterReceived: 'metadata-chapter-received',
32
+ MetadataTimedReceived: 'metadata-timed-received',
33
+ MetadataCommonReceived: 'metadata-common-received',
34
+ AndroidConnectorConnected: 'android-controller-connected',
35
+ AndroidConnectorDisconnected: 'android-controller-disconnected'
36
+ };
37
+ export const TrackPlayerEvents = {
38
+ ...Event,
39
+ QueueUpdated: 'queue-updated'
40
+ };
41
+ const emitter = new NativeEventEmitter(ExpoNativeTrackPlayer);
42
+ export function addEventListener(eventName, listener) {
43
+ return emitter.addListener(eventName, event => listener(event));
44
+ }
45
+ export function addTypedEventListener(eventName, listener) {
46
+ return emitter.addListener(eventName, event => listener(event));
47
+ }
48
+ export function removeAllEventListeners(eventName) {
49
+ emitter.removeAllListeners(eventName);
50
+ }
51
+ export const AudioEvents = {
52
+ addListener: addEventListener,
53
+ addTypedListener: addTypedEventListener,
54
+ removeAllListeners: removeAllEventListeners
55
+ };
56
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeEventEmitter","ExpoNativeTrackPlayer","Event","PlayerError","PlaybackState","PlaybackError","PlaybackQueueEnded","PlaybackActiveTrackChanged","PlaybackPlayWhenReadyChanged","PlaybackProgressUpdated","PlaybackResume","RemotePlay","RemotePlayPause","RemotePause","RemoteStop","RemoteNext","RemotePrevious","RemoteJumpForward","RemoteJumpBackward","RemoteSeek","RemoteSetRating","RemoteDuck","RemoteLike","RemoteDislike","RemoteBookmark","RemotePlayId","RemotePlaySearch","RemoteSkip","MetadataChapterReceived","MetadataTimedReceived","MetadataCommonReceived","AndroidConnectorConnected","AndroidConnectorDisconnected","TrackPlayerEvents","QueueUpdated","emitter","addEventListener","eventName","listener","addListener","event","addTypedEventListener","removeAllEventListeners","removeAllListeners","AudioEvents","addTypedListener"],"sourceRoot":"../../src","sources":["events.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAkC,cAAc;AAC3E,OAAOC,qBAAqB,MAGrB,kCAA+B;AAEtC,OAAO,MAAMC,KAAK,GAAG;EACnBC,WAAW,EAAE,cAAc;EAC3BC,aAAa,EAAE,gBAAgB;EAC/BC,aAAa,EAAE,gBAAgB;EAC/BC,kBAAkB,EAAE,sBAAsB;EAC1CC,0BAA0B,EAAE,+BAA+B;EAC3DC,4BAA4B,EAAE,kCAAkC;EAChEC,uBAAuB,EAAE,2BAA2B;EACpDC,cAAc,EAAE,yBAAyB;EACzCC,UAAU,EAAE,aAAa;EACzBC,eAAe,EAAE,mBAAmB;EACpCC,WAAW,EAAE,cAAc;EAC3BC,UAAU,EAAE,aAAa;EACzBC,UAAU,EAAE,aAAa;EACzBC,cAAc,EAAE,iBAAiB;EACjCC,iBAAiB,EAAE,qBAAqB;EACxCC,kBAAkB,EAAE,sBAAsB;EAC1CC,UAAU,EAAE,aAAa;EACzBC,eAAe,EAAE,mBAAmB;EACpCC,UAAU,EAAE,aAAa;EACzBC,UAAU,EAAE,aAAa;EACzBC,aAAa,EAAE,gBAAgB;EAC/BC,cAAc,EAAE,iBAAiB;EACjCC,YAAY,EAAE,gBAAgB;EAC9BC,gBAAgB,EAAE,oBAAoB;EACtCC,UAAU,EAAE,aAAa;EACzBC,uBAAuB,EAAE,2BAA2B;EACpDC,qBAAqB,EAAE,yBAAyB;EAChDC,sBAAsB,EAAE,0BAA0B;EAClDC,yBAAyB,EAAE,8BAA8B;EACzDC,4BAA4B,EAAE;AAChC,CAAU;AAIV,OAAO,MAAMC,iBAAiB,GAAG;EAC/B,GAAG/B,KAAK;EACRgC,YAAY,EAAE;AAChB,CAAU;AAiEV,MAAMC,OAAO,GAAG,IAAInC,kBAAkB,CAACC,qBAAqB,CAAC;AAE7D,OAAO,SAASmC,gBAAgBA,CAC9BC,SAA+B,EAC/BC,QAA4B,EACP;EACrB,OAAOH,OAAO,CAACI,WAAW,CAACF,SAAS,EAAGG,KAAU,IAAKF,QAAQ,CAACE,KAAU,CAAC,CAAC;AAC7E;AAEA,OAAO,SAASC,qBAAqBA,CACnCJ,SAAY,EACZC,QAA6C,EACxB;EACrB,OAAOH,OAAO,CAACI,WAAW,CAACF,SAAS,EAAGG,KAAU,IAC/CF,QAAQ,CAACE,KAA2B,CACtC,CAAC;AACH;AAEA,OAAO,SAASE,uBAAuBA,CAACL,SAA+B,EAAQ;EAC7EF,OAAO,CAACQ,kBAAkB,CAACN,SAAS,CAAC;AACvC;AAEA,OAAO,MAAMO,WAAW,GAAG;EACzBL,WAAW,EAAEH,gBAAgB;EAC7BS,gBAAgB,EAAEJ,qBAAqB;EACvCE,kBAAkB,EAAED;AACtB,CAAC","ignoreList":[]}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+
3
+ import { useEffect, useState } from 'react';
4
+ import ExpoNativeTrackPlayer from "./NativeExpoNativeTrackPlayer.js";
5
+ import { addEventListener, Event, TrackPlayerEvents } from "./events.js";
6
+ export function usePlaybackState() {
7
+ const [state, setState] = useState('none');
8
+ useEffect(() => {
9
+ const subscription = addEventListener(Event.PlaybackState, event => setState(event.state));
10
+ return () => subscription.remove();
11
+ }, []);
12
+ return state;
13
+ }
14
+ export function useProgress(intervalMs = 1000) {
15
+ const [progress, setProgress] = useState({
16
+ position: 0,
17
+ duration: 0,
18
+ trackIndex: -1
19
+ });
20
+ useEffect(() => {
21
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0) return;
22
+ let isActive = true;
23
+ const update = () => {
24
+ if (!isActive) return;
25
+ try {
26
+ const position = ExpoNativeTrackPlayer.getPosition();
27
+ const duration = ExpoNativeTrackPlayer.getDuration();
28
+ const trackIndex = ExpoNativeTrackPlayer.getCurrentTrackIndex();
29
+ setProgress({
30
+ position,
31
+ duration,
32
+ trackIndex
33
+ });
34
+ } catch (error) {
35
+ setProgress({
36
+ position: 0,
37
+ duration: 0,
38
+ trackIndex: -1
39
+ });
40
+ }
41
+ };
42
+ update();
43
+ const timer = setInterval(update, intervalMs);
44
+ return () => {
45
+ isActive = false;
46
+ clearInterval(timer);
47
+ };
48
+ }, [intervalMs]);
49
+ return progress;
50
+ }
51
+ export function useQueue() {
52
+ const [queue, setQueue] = useState([]);
53
+ useEffect(() => {
54
+ let isActive = true;
55
+ try {
56
+ const result = ExpoNativeTrackPlayer.getQueue();
57
+ if (isActive) setQueue(result);
58
+ } catch (error) {
59
+ if (isActive) setQueue([]);
60
+ }
61
+ const subscription = addEventListener(TrackPlayerEvents.QueueUpdated, event => setQueue(event.queue));
62
+ return () => {
63
+ isActive = false;
64
+ subscription.remove();
65
+ };
66
+ }, []);
67
+ return queue;
68
+ }
69
+ export function useCurrentTrack() {
70
+ const [track, setTrack] = useState(null);
71
+ useEffect(() => {
72
+ let isActive = true;
73
+ try {
74
+ const result = ExpoNativeTrackPlayer.getCurrentTrack();
75
+ if (isActive) setTrack(result);
76
+ } catch (error) {
77
+ if (isActive) setTrack(null);
78
+ }
79
+ const subscription = addEventListener(Event.PlaybackActiveTrackChanged, event => setTrack(event.track));
80
+ return () => {
81
+ isActive = false;
82
+ subscription.remove();
83
+ };
84
+ }, []);
85
+ return track;
86
+ }
87
+ export function useCurrentTrackIndex() {
88
+ const [index, setIndex] = useState(-1);
89
+ useEffect(() => {
90
+ let isActive = true;
91
+ try {
92
+ const result = ExpoNativeTrackPlayer.getCurrentTrackIndex();
93
+ if (isActive) setIndex(result);
94
+ } catch (error) {
95
+ if (isActive) setIndex(-1);
96
+ }
97
+ const subscription = addEventListener(Event.PlaybackActiveTrackChanged, event => setIndex(event.trackIndex));
98
+ return () => {
99
+ isActive = false;
100
+ subscription.remove();
101
+ };
102
+ }, []);
103
+ return index;
104
+ }
105
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","useState","ExpoNativeTrackPlayer","addEventListener","Event","TrackPlayerEvents","usePlaybackState","state","setState","subscription","PlaybackState","event","remove","useProgress","intervalMs","progress","setProgress","position","duration","trackIndex","Number","isFinite","isActive","update","getPosition","getDuration","getCurrentTrackIndex","error","timer","setInterval","clearInterval","useQueue","queue","setQueue","result","getQueue","QueueUpdated","useCurrentTrack","track","setTrack","getCurrentTrack","PlaybackActiveTrackChanged","useCurrentTrackIndex","index","setIndex"],"sourceRoot":"../../src","sources":["hooks.ts"],"mappings":"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","ignoreList":[]}