Updated packages, rewrote player = gapless playback, faster loading
This commit is contained in:
parent
6f250df004
commit
d4299f736f
92 changed files with 10270 additions and 1450 deletions
37
just_audio/macos/.gitignore
vendored
Normal file
37
just_audio/macos/.gitignore
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
.idea/
|
||||
.vagrant/
|
||||
.sconsign.dblite
|
||||
.svn/
|
||||
|
||||
.DS_Store
|
||||
*.swp
|
||||
profile
|
||||
|
||||
DerivedData/
|
||||
build/
|
||||
GeneratedPluginRegistrant.h
|
||||
GeneratedPluginRegistrant.m
|
||||
|
||||
.generated/
|
||||
|
||||
*.pbxuser
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspectivev3
|
||||
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
xcuserdata
|
||||
|
||||
*.moved-aside
|
||||
|
||||
*.pyc
|
||||
*sync/
|
||||
Icon?
|
||||
.tags*
|
||||
|
||||
/Flutter/Generated.xcconfig
|
||||
/Flutter/flutter_export_environment.sh
|
0
just_audio/macos/Assets/.gitkeep
Normal file
0
just_audio/macos/Assets/.gitkeep
Normal file
21
just_audio/macos/Classes/AudioPlayer.h
Normal file
21
just_audio/macos/Classes/AudioPlayer.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface AudioPlayer : NSObject<FlutterStreamHandler>
|
||||
|
||||
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar playerId:(NSString*)idParam configuredSession:(BOOL)configuredSession;
|
||||
|
||||
@end
|
||||
|
||||
enum ProcessingState {
|
||||
none,
|
||||
loading,
|
||||
buffering,
|
||||
ready,
|
||||
completed
|
||||
};
|
||||
|
||||
enum LoopMode {
|
||||
loopOff,
|
||||
loopOne,
|
||||
loopAll
|
||||
};
|
1138
just_audio/macos/Classes/AudioPlayer.m
Normal file
1138
just_audio/macos/Classes/AudioPlayer.m
Normal file
File diff suppressed because it is too large
Load diff
13
just_audio/macos/Classes/AudioSource.h
Normal file
13
just_audio/macos/Classes/AudioSource.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface AudioSource : NSObject
|
||||
|
||||
@property (readonly, nonatomic) NSString* sourceId;
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid;
|
||||
- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex;
|
||||
- (void)findById:(NSString *)sourceId matches:(NSMutableArray<AudioSource *> *)matches;
|
||||
- (NSArray *)getShuffleOrder;
|
||||
- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex;
|
||||
|
||||
@end
|
37
just_audio/macos/Classes/AudioSource.m
Normal file
37
just_audio/macos/Classes/AudioSource.m
Normal file
|
@ -0,0 +1,37 @@
|
|||
#import "AudioSource.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation AudioSource {
|
||||
NSString *_sourceId;
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid {
|
||||
self = [super init];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_sourceId = sid;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)sourceId {
|
||||
return _sourceId;
|
||||
}
|
||||
|
||||
- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex {
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)findById:(NSString *)sourceId matches:(NSMutableArray<AudioSource *> *)matches {
|
||||
if ([_sourceId isEqualToString:sourceId]) {
|
||||
[matches addObject:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)getShuffleOrder {
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
11
just_audio/macos/Classes/ClippingAudioSource.h
Normal file
11
just_audio/macos/Classes/ClippingAudioSource.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#import "AudioSource.h"
|
||||
#import "UriAudioSource.h"
|
||||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface ClippingAudioSource : IndexedAudioSource
|
||||
|
||||
@property (readonly, nonatomic) UriAudioSource* audioSource;
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end;
|
||||
|
||||
@end
|
79
just_audio/macos/Classes/ClippingAudioSource.m
Normal file
79
just_audio/macos/Classes/ClippingAudioSource.m
Normal file
|
@ -0,0 +1,79 @@
|
|||
#import "AudioSource.h"
|
||||
#import "ClippingAudioSource.h"
|
||||
#import "IndexedPlayerItem.h"
|
||||
#import "UriAudioSource.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation ClippingAudioSource {
|
||||
UriAudioSource *_audioSource;
|
||||
CMTime _start;
|
||||
CMTime _end;
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid audioSource:(UriAudioSource *)audioSource start:(NSNumber *)start end:(NSNumber *)end {
|
||||
self = [super initWithId:sid];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_audioSource = audioSource;
|
||||
_start = start == [NSNull null] ? kCMTimeZero : CMTimeMake([start intValue], 1000);
|
||||
_end = end == [NSNull null] ? kCMTimeInvalid : CMTimeMake([end intValue], 1000);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UriAudioSource *)audioSource {
|
||||
return _audioSource;
|
||||
}
|
||||
|
||||
- (void)findById:(NSString *)sourceId matches:(NSMutableArray<AudioSource *> *)matches {
|
||||
[super findById:sourceId matches:matches];
|
||||
[_audioSource findById:sourceId matches:matches];
|
||||
}
|
||||
|
||||
- (void)attach:(AVQueuePlayer *)player {
|
||||
[super attach:player];
|
||||
_audioSource.playerItem.forwardPlaybackEndTime = _end;
|
||||
// XXX: Not needed since currentItem observer handles it?
|
||||
[self seek:kCMTimeZero];
|
||||
}
|
||||
|
||||
- (IndexedPlayerItem *)playerItem {
|
||||
return _audioSource.playerItem;
|
||||
}
|
||||
|
||||
- (NSArray *)getShuffleOrder {
|
||||
return @[@(0)];
|
||||
}
|
||||
|
||||
- (void)play:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)pause:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)stop:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler {
|
||||
if (!completionHandler || (self.playerItem.status == AVPlayerItemStatusReadyToPlay)) {
|
||||
CMTime absPosition = CMTimeAdd(_start, position);
|
||||
[_audioSource.playerItem seekToTime:absPosition toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler];
|
||||
}
|
||||
}
|
||||
|
||||
- (CMTime)duration {
|
||||
return CMTimeSubtract(CMTIME_IS_INVALID(_end) ? self.playerItem.duration : _end, _start);
|
||||
}
|
||||
|
||||
- (void)setDuration:(CMTime)duration {
|
||||
}
|
||||
|
||||
- (CMTime)position {
|
||||
return CMTimeSubtract(self.playerItem.currentTime, _start);
|
||||
}
|
||||
|
||||
- (CMTime)bufferedPosition {
|
||||
CMTime pos = CMTimeSubtract(_audioSource.bufferedPosition, _start);
|
||||
CMTime dur = [self duration];
|
||||
return CMTimeCompare(pos, dur) >= 0 ? dur : pos;
|
||||
}
|
||||
|
||||
@end
|
13
just_audio/macos/Classes/ConcatenatingAudioSource.h
Normal file
13
just_audio/macos/Classes/ConcatenatingAudioSource.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#import "AudioSource.h"
|
||||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface ConcatenatingAudioSource : AudioSource
|
||||
|
||||
@property (readonly, nonatomic) int count;
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray<AudioSource *> *)audioSources;
|
||||
- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index;
|
||||
- (void)removeSourcesFromIndex:(int)start toIndex:(int)end;
|
||||
- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex;
|
||||
|
||||
@end
|
109
just_audio/macos/Classes/ConcatenatingAudioSource.m
Normal file
109
just_audio/macos/Classes/ConcatenatingAudioSource.m
Normal file
|
@ -0,0 +1,109 @@
|
|||
#import "AudioSource.h"
|
||||
#import "ConcatenatingAudioSource.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
@implementation ConcatenatingAudioSource {
|
||||
NSMutableArray<AudioSource *> *_audioSources;
|
||||
NSMutableArray<NSNumber *> *_shuffleOrder;
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid audioSources:(NSMutableArray<AudioSource *> *)audioSources {
|
||||
self = [super initWithId:sid];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_audioSources = audioSources;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int)count {
|
||||
return _audioSources.count;
|
||||
}
|
||||
|
||||
- (void)insertSource:(AudioSource *)audioSource atIndex:(int)index {
|
||||
[_audioSources insertObject:audioSource atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeSourcesFromIndex:(int)start toIndex:(int)end {
|
||||
if (end == -1) end = _audioSources.count;
|
||||
for (int i = start; i < end; i++) {
|
||||
[_audioSources removeObjectAtIndex:start];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)moveSourceFromIndex:(int)currentIndex toIndex:(int)newIndex {
|
||||
AudioSource *source = _audioSources[currentIndex];
|
||||
[_audioSources removeObjectAtIndex:currentIndex];
|
||||
[_audioSources insertObject:source atIndex:newIndex];
|
||||
}
|
||||
|
||||
- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex {
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex];
|
||||
}
|
||||
return treeIndex;
|
||||
}
|
||||
|
||||
- (void)findById:(NSString *)sourceId matches:(NSMutableArray<AudioSource *> *)matches {
|
||||
[super findById:sourceId matches:matches];
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
[_audioSources[i] findById:sourceId matches:matches];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)getShuffleOrder {
|
||||
NSMutableArray *order = [NSMutableArray new];
|
||||
int offset = [order count];
|
||||
NSMutableArray *childOrders = [NSMutableArray new]; // array of array of ints
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
AudioSource *audioSource = _audioSources[i];
|
||||
NSArray *childShuffleOrder = [audioSource getShuffleOrder];
|
||||
NSMutableArray *offsetChildShuffleOrder = [NSMutableArray new];
|
||||
for (int j = 0; j < [childShuffleOrder count]; j++) {
|
||||
[offsetChildShuffleOrder addObject:@([childShuffleOrder[j] integerValue] + offset)];
|
||||
}
|
||||
[childOrders addObject:offsetChildShuffleOrder];
|
||||
offset += [childShuffleOrder count];
|
||||
}
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
[order addObjectsFromArray:childOrders[[_shuffleOrder[i] integerValue]]];
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex {
|
||||
int currentChildIndex = -1;
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
int indexBefore = treeIndex;
|
||||
AudioSource *child = _audioSources[i];
|
||||
treeIndex = [child shuffle:treeIndex currentIndex:currentIndex];
|
||||
if (currentIndex >= indexBefore && currentIndex < treeIndex) {
|
||||
currentChildIndex = i;
|
||||
} else {}
|
||||
}
|
||||
// Shuffle so that the current child is first in the shuffle order
|
||||
_shuffleOrder = [NSMutableArray arrayWithCapacity:[_audioSources count]];
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
[_shuffleOrder addObject:@(0)];
|
||||
}
|
||||
NSLog(@"shuffle: audioSources.count=%d and shuffleOrder.count=%d", [_audioSources count], [_shuffleOrder count]);
|
||||
// First generate a random shuffle
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
int j = arc4random_uniform(i + 1);
|
||||
_shuffleOrder[i] = _shuffleOrder[j];
|
||||
_shuffleOrder[j] = @(i);
|
||||
}
|
||||
// Then bring currentIndex to the front
|
||||
if (currentChildIndex != -1) {
|
||||
for (int i = 1; i < [_audioSources count]; i++) {
|
||||
if ([_shuffleOrder[i] integerValue] == currentChildIndex) {
|
||||
NSNumber *v = _shuffleOrder[0];
|
||||
_shuffleOrder[0] = _shuffleOrder[i];
|
||||
_shuffleOrder[i] = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return treeIndex;
|
||||
}
|
||||
|
||||
@end
|
21
just_audio/macos/Classes/IndexedAudioSource.h
Normal file
21
just_audio/macos/Classes/IndexedAudioSource.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#import "AudioSource.h"
|
||||
#import "IndexedPlayerItem.h"
|
||||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@interface IndexedAudioSource : AudioSource
|
||||
|
||||
@property (readonly, nonatomic) IndexedPlayerItem *playerItem;
|
||||
@property (readwrite, nonatomic) CMTime duration;
|
||||
@property (readonly, nonatomic) CMTime position;
|
||||
@property (readonly, nonatomic) CMTime bufferedPosition;
|
||||
@property (readonly, nonatomic) BOOL isAttached;
|
||||
|
||||
- (void)attach:(AVQueuePlayer *)player;
|
||||
- (void)play:(AVQueuePlayer *)player;
|
||||
- (void)pause:(AVQueuePlayer *)player;
|
||||
- (void)stop:(AVQueuePlayer *)player;
|
||||
- (void)seek:(CMTime)position;
|
||||
- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler;
|
||||
|
||||
@end
|
68
just_audio/macos/Classes/IndexedAudioSource.m
Normal file
68
just_audio/macos/Classes/IndexedAudioSource.m
Normal file
|
@ -0,0 +1,68 @@
|
|||
#import "IndexedAudioSource.h"
|
||||
#import "IndexedPlayerItem.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation IndexedAudioSource {
|
||||
BOOL _isAttached;
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid {
|
||||
self = [super init];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_isAttached = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (IndexedPlayerItem *)playerItem {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isAttached {
|
||||
return _isAttached;
|
||||
}
|
||||
|
||||
- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex {
|
||||
[sequence addObject:self];
|
||||
return treeIndex + 1;
|
||||
}
|
||||
|
||||
- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex {
|
||||
return treeIndex + 1;
|
||||
}
|
||||
|
||||
- (void)attach:(AVQueuePlayer *)player {
|
||||
_isAttached = YES;
|
||||
}
|
||||
|
||||
- (void)play:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)pause:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)stop:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)seek:(CMTime)position {
|
||||
[self seek:position completionHandler:nil];
|
||||
}
|
||||
|
||||
- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler {
|
||||
}
|
||||
|
||||
- (CMTime)duration {
|
||||
return kCMTimeInvalid;
|
||||
}
|
||||
|
||||
- (void)setDuration:(CMTime)duration {
|
||||
}
|
||||
|
||||
- (CMTime)position {
|
||||
return kCMTimeInvalid;
|
||||
}
|
||||
|
||||
- (CMTime)bufferedPosition {
|
||||
return kCMTimeInvalid;
|
||||
}
|
||||
|
||||
@end
|
9
just_audio/macos/Classes/IndexedPlayerItem.h
Normal file
9
just_audio/macos/Classes/IndexedPlayerItem.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@class IndexedAudioSource;
|
||||
|
||||
@interface IndexedPlayerItem : AVPlayerItem
|
||||
|
||||
@property (readwrite, nonatomic) IndexedAudioSource *audioSource;
|
||||
|
||||
@end
|
16
just_audio/macos/Classes/IndexedPlayerItem.m
Normal file
16
just_audio/macos/Classes/IndexedPlayerItem.m
Normal file
|
@ -0,0 +1,16 @@
|
|||
#import "IndexedPlayerItem.h"
|
||||
#import "IndexedAudioSource.h"
|
||||
|
||||
@implementation IndexedPlayerItem {
|
||||
IndexedAudioSource *_audioSource;
|
||||
}
|
||||
|
||||
-(void)setAudioSource:(IndexedAudioSource *)audioSource {
|
||||
_audioSource = audioSource;
|
||||
}
|
||||
|
||||
-(IndexedAudioSource *)audioSource {
|
||||
return _audioSource;
|
||||
}
|
||||
|
||||
@end
|
4
just_audio/macos/Classes/JustAudioPlugin.h
Normal file
4
just_audio/macos/Classes/JustAudioPlugin.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface JustAudioPlugin : NSObject<FlutterPlugin>
|
||||
@end
|
55
just_audio/macos/Classes/JustAudioPlugin.m
Normal file
55
just_audio/macos/Classes/JustAudioPlugin.m
Normal file
|
@ -0,0 +1,55 @@
|
|||
#import "JustAudioPlugin.h"
|
||||
#import "AudioPlayer.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
@implementation JustAudioPlugin {
|
||||
NSObject<FlutterPluginRegistrar>* _registrar;
|
||||
BOOL _configuredSession;
|
||||
}
|
||||
|
||||
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||
FlutterMethodChannel* channel = [FlutterMethodChannel
|
||||
methodChannelWithName:@"com.ryanheise.just_audio.methods"
|
||||
binaryMessenger:[registrar messenger]];
|
||||
JustAudioPlugin* instance = [[JustAudioPlugin alloc] initWithRegistrar:registrar];
|
||||
[registrar addMethodCallDelegate:instance channel:channel];
|
||||
}
|
||||
|
||||
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
|
||||
self = [super init];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_registrar = registrar;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
|
||||
if ([@"init" isEqualToString:call.method]) {
|
||||
NSArray* args = (NSArray*)call.arguments;
|
||||
NSString* playerId = args[0];
|
||||
/*AudioPlayer* player =*/ [[AudioPlayer alloc] initWithRegistrar:_registrar playerId:playerId configuredSession:_configuredSession];
|
||||
result(nil);
|
||||
} else if ([@"setIosCategory" isEqualToString:call.method]) {
|
||||
#if TARGET_OS_IPHONE
|
||||
NSNumber* categoryIndex = (NSNumber*)call.arguments;
|
||||
AVAudioSessionCategory category = nil;
|
||||
switch (categoryIndex.integerValue) {
|
||||
case 0: category = AVAudioSessionCategoryAmbient; break;
|
||||
case 1: category = AVAudioSessionCategorySoloAmbient; break;
|
||||
case 2: category = AVAudioSessionCategoryPlayback; break;
|
||||
case 3: category = AVAudioSessionCategoryRecord; break;
|
||||
case 4: category = AVAudioSessionCategoryPlayAndRecord; break;
|
||||
case 5: category = AVAudioSessionCategoryMultiRoute; break;
|
||||
}
|
||||
if (category) {
|
||||
_configuredSession = YES;
|
||||
}
|
||||
[[AVAudioSession sharedInstance] setCategory:category error:nil];
|
||||
#endif
|
||||
result(nil);
|
||||
} else {
|
||||
result(FlutterMethodNotImplemented);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
8
just_audio/macos/Classes/LoopingAudioSource.h
Normal file
8
just_audio/macos/Classes/LoopingAudioSource.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#import "AudioSource.h"
|
||||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface LoopingAudioSource : AudioSource
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray<AudioSource *> *)audioSources;
|
||||
|
||||
@end
|
53
just_audio/macos/Classes/LoopingAudioSource.m
Normal file
53
just_audio/macos/Classes/LoopingAudioSource.m
Normal file
|
@ -0,0 +1,53 @@
|
|||
#import "AudioSource.h"
|
||||
#import "LoopingAudioSource.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation LoopingAudioSource {
|
||||
// An array of duplicates
|
||||
NSArray<AudioSource *> *_audioSources; // <AudioSource *>
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid audioSources:(NSArray<AudioSource *> *)audioSources {
|
||||
self = [super initWithId:sid];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_audioSources = audioSources;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int)buildSequence:(NSMutableArray *)sequence treeIndex:(int)treeIndex {
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
treeIndex = [_audioSources[i] buildSequence:sequence treeIndex:treeIndex];
|
||||
}
|
||||
return treeIndex;
|
||||
}
|
||||
|
||||
- (void)findById:(NSString *)sourceId matches:(NSMutableArray<AudioSource *> *)matches {
|
||||
[super findById:sourceId matches:matches];
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
[_audioSources[i] findById:sourceId matches:matches];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)getShuffleOrder {
|
||||
NSMutableArray *order = [NSMutableArray new];
|
||||
int offset = (int)[order count];
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
AudioSource *audioSource = _audioSources[i];
|
||||
NSArray *childShuffleOrder = [audioSource getShuffleOrder];
|
||||
for (int j = 0; j < [childShuffleOrder count]; j++) {
|
||||
[order addObject:@([childShuffleOrder[j] integerValue] + offset)];
|
||||
}
|
||||
offset += [childShuffleOrder count];
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
- (int)shuffle:(int)treeIndex currentIndex:(int)currentIndex {
|
||||
// TODO: This should probably shuffle the same way on all duplicates.
|
||||
for (int i = 0; i < [_audioSources count]; i++) {
|
||||
treeIndex = [_audioSources[i] shuffle:treeIndex currentIndex:currentIndex];
|
||||
}
|
||||
return treeIndex;
|
||||
}
|
||||
|
||||
@end
|
8
just_audio/macos/Classes/UriAudioSource.h
Normal file
8
just_audio/macos/Classes/UriAudioSource.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#import "IndexedAudioSource.h"
|
||||
#import <FlutterMacOS/FlutterMacOS.h>
|
||||
|
||||
@interface UriAudioSource : IndexedAudioSource
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri;
|
||||
|
||||
@end
|
79
just_audio/macos/Classes/UriAudioSource.m
Normal file
79
just_audio/macos/Classes/UriAudioSource.m
Normal file
|
@ -0,0 +1,79 @@
|
|||
#import "UriAudioSource.h"
|
||||
#import "IndexedAudioSource.h"
|
||||
#import "IndexedPlayerItem.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation UriAudioSource {
|
||||
NSString *_uri;
|
||||
IndexedPlayerItem *_playerItem;
|
||||
/* CMTime _duration; */
|
||||
}
|
||||
|
||||
- (instancetype)initWithId:(NSString *)sid uri:(NSString *)uri {
|
||||
self = [super initWithId:sid];
|
||||
NSAssert(self, @"super init cannot be nil");
|
||||
_uri = uri;
|
||||
if ([_uri hasPrefix:@"file://"]) {
|
||||
_playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL fileURLWithPath:[_uri substringFromIndex:7]]];
|
||||
} else {
|
||||
_playerItem = [[IndexedPlayerItem alloc] initWithURL:[NSURL URLWithString:_uri]];
|
||||
}
|
||||
if (@available(macOS 10.13, iOS 11.0, *)) {
|
||||
// This does the best at reducing distortion on voice with speeds below 1.0
|
||||
_playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmTimeDomain;
|
||||
}
|
||||
/* NSKeyValueObservingOptions options = */
|
||||
/* NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew; */
|
||||
/* [_playerItem addObserver:self */
|
||||
/* forKeyPath:@"duration" */
|
||||
/* options:options */
|
||||
/* context:nil]; */
|
||||
return self;
|
||||
}
|
||||
|
||||
- (IndexedPlayerItem *)playerItem {
|
||||
return _playerItem;
|
||||
}
|
||||
|
||||
- (NSArray *)getShuffleOrder {
|
||||
return @[@(0)];
|
||||
}
|
||||
|
||||
- (void)play:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)pause:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)stop:(AVQueuePlayer *)player {
|
||||
}
|
||||
|
||||
- (void)seek:(CMTime)position completionHandler:(void (^)(BOOL))completionHandler {
|
||||
if (!completionHandler || (_playerItem.status == AVPlayerItemStatusReadyToPlay)) {
|
||||
[_playerItem seekToTime:position toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:completionHandler];
|
||||
}
|
||||
}
|
||||
|
||||
- (CMTime)duration {
|
||||
return _playerItem.duration;
|
||||
}
|
||||
|
||||
- (void)setDuration:(CMTime)duration {
|
||||
}
|
||||
|
||||
- (CMTime)position {
|
||||
return _playerItem.currentTime;
|
||||
}
|
||||
|
||||
- (CMTime)bufferedPosition {
|
||||
NSValue *last = _playerItem.loadedTimeRanges.lastObject;
|
||||
if (last) {
|
||||
CMTimeRange timeRange = [last CMTimeRangeValue];
|
||||
return CMTimeAdd(timeRange.start, timeRange.duration);
|
||||
} else {
|
||||
return _playerItem.currentTime;
|
||||
}
|
||||
return kCMTimeInvalid;
|
||||
}
|
||||
|
||||
@end
|
21
just_audio/macos/just_audio.podspec
Normal file
21
just_audio/macos/just_audio.podspec
Normal file
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'just_audio'
|
||||
s.version = '0.0.1'
|
||||
s.summary = 'A new flutter plugin project.'
|
||||
s.description = <<-DESC
|
||||
A new flutter plugin project.
|
||||
DESC
|
||||
s.homepage = 'http://example.com'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'Your Company' => 'email@example.com' }
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
s.public_header_files = 'Classes/**/*.h'
|
||||
s.dependency 'FlutterMacOS'
|
||||
s.platform = :osx, '10.11'
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
||||
end
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue