1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 09:27:55 +01:00
Telegram/Telegraph/TGDownloadAudioSignal.m
2016-02-25 01:03:51 +01:00

211 lines
8.1 KiB
Objective-C

#import "TGDownloadAudioSignal.h"
#import "ActionStage.h"
#import "TGDownloadManager.h"
#import "TGBridgeSignalManager.h"
#import "TGMessage.h"
#import "TGPreparedLocalDocumentMessage.h"
@interface TGDownloadMediaAdapter : NSObject <ASWatcher>
{
TGMediaAttachment *_attachment;
TGMediaId *_mediaId;
CGFloat _progress;
}
@property (nonatomic, strong) ASHandle *actionHandle;
@property (nonatomic, copy) void(^completionBlock)(NSString *path);
@property (nonatomic, copy) void(^progressBlock)(CGFloat progress);
@end
@implementation TGDownloadMediaAdapter
- (instancetype)initWithAttachment:(TGMediaAttachment *)attachment conversationId:(int64_t)cid messageId:(int32_t)mid
{
self = [super init];
if (self != nil)
{
self.actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:false];
[ActionStageInstance() watchForPaths:@
[
@"downloadManagerStateChanged"
] watcher:self];
if ([attachment isKindOfClass:[TGDocumentMediaAttachment class]])
{
TGDocumentMediaAttachment *documentAttachment = (TGDocumentMediaAttachment *)attachment;
if (documentAttachment.documentId != 0 || documentAttachment.documentUri.length != 0)
{
_mediaId = [[TGMediaId alloc] initWithType:3 itemId:documentAttachment.documentId != 0 ? documentAttachment.documentId : documentAttachment.localDocumentId];
[[TGDownloadManager instance] requestItem:[NSString stringWithFormat:@"/tg/media/document/(%d:%" PRId64 ":%@)", documentAttachment.datacenterId, documentAttachment.documentId, documentAttachment.documentUri.length != 0 ? documentAttachment.documentUri : @""] options:[[NSDictionary alloc] initWithObjectsAndKeys:documentAttachment, @"documentAttachment", nil] changePriority:true messageId:mid itemId:_mediaId groupId:cid itemClass:TGDownloadItemClassDocument];
_attachment = attachment;
}
else
{
return nil;
}
}
else if ([attachment isKindOfClass:[TGAudioMediaAttachment class]])
{
TGAudioMediaAttachment *audioAttachment = (TGAudioMediaAttachment *)attachment;
if (audioAttachment.audioId != 0 || audioAttachment.audioUri.length != 0)
{
_mediaId = [[TGMediaId alloc] initWithType:4 itemId:audioAttachment.audioId != 0 ? audioAttachment.audioId : audioAttachment.localAudioId];
[[TGDownloadManager instance] requestItem:[NSString stringWithFormat:@"/tg/media/audio/(%" PRId32 ":%" PRId64 ":%@)", audioAttachment.datacenterId, audioAttachment.audioId, audioAttachment.audioUri.length != 0 ? audioAttachment.audioUri : @""] options:[[NSDictionary alloc] initWithObjectsAndKeys:audioAttachment, @"audioAttachment", nil] changePriority:true messageId:mid itemId:_mediaId groupId:cid itemClass:TGDownloadItemClassAudio];
_attachment = attachment;
}
else
{
return nil;
}
}
}
return self;
}
- (void)dealloc
{
[_actionHandle reset];
[ActionStageInstance() removeWatcher:self];
[[TGDownloadManager instance] cancelItem:_mediaId];
}
- (void)startWithCompletion:(void (^)(NSString *))completion progress:(void (^)(CGFloat))progress
{
self.completionBlock = completion;
self.progressBlock = progress;
}
- (void)actionStageResourceDispatched:(NSString *)path resource:(id)resource arguments:(id)arguments
{
if ([path isEqualToString:@"downloadManagerStateChanged"])
{
NSDictionary *mediaList = resource;
NSMutableDictionary *messageDownloadProgress = [[NSMutableDictionary alloc] init];
if (mediaList == nil || mediaList.count == 0)
{
[messageDownloadProgress removeAllObjects];
}
else
{
[mediaList enumerateKeysAndObjectsUsingBlock:^(__unused NSString *path, TGDownloadItem *item, __unused BOOL *stop)
{
if (item.itemId != nil)
[messageDownloadProgress setObject:[[NSNumber alloc] initWithFloat:item.progress] forKey:item.itemId];
}];
}
NSNumber *nProgress = messageDownloadProgress[_mediaId];
if (nProgress != nil && fabs(nProgress.floatValue - _progress) > FLT_EPSILON)
{
_progress = nProgress.floatValue;
if (self.progressBlock != nil)
self.progressBlock(_progress);
}
if (arguments != nil)
{
NSMutableDictionary *completedItemStatuses = [[NSMutableDictionary alloc] init];
for (id mediaId in [arguments objectForKey:@"completedItemIds"])
[completedItemStatuses setObject:@(true) forKey:mediaId];
for (id mediaId in [arguments objectForKey:@"failedItemIds"])
[completedItemStatuses setObject:@(false) forKey:mediaId];
NSNumber *nResult = completedItemStatuses[_mediaId];
if (nResult != nil)
{
bool succeed = nResult.boolValue;
if (self.completionBlock != nil)
{
if (succeed)
{
NSString *path = nil;
if ([_attachment isKindOfClass:[TGDocumentMediaAttachment class]])
path = [TGDownloadAudioSignal pathForDocumentMediaAttachment:(TGDocumentMediaAttachment *)_attachment];
else if ([_attachment isKindOfClass:[TGAudioMediaAttachment class]])
path = ((TGAudioMediaAttachment *)_attachment).localFilePath;
self.completionBlock(path);
}
else
{
self.completionBlock(nil);
}
}
}
}
}
}
@end
@implementation TGDownloadAudioSignal
+ (SSignal *)downloadAudioWithAttachment:(TGMediaAttachment *)attachment conversationId:(int64_t)cid messageId:(int32_t)mid
{
if ([attachment isKindOfClass:[TGDocumentMediaAttachment class]] && ((TGDocumentMediaAttachment *)attachment).documentId == 0 && ((TGDocumentMediaAttachment *)attachment).localDocumentId == 0)
return [SSignal fail:nil];
else if ([attachment isKindOfClass:[TGAudioMediaAttachment class]] && ((TGAudioMediaAttachment *)attachment).audioId == 0 && ((TGAudioMediaAttachment *)attachment).localAudioId == 0)
return [SSignal fail:nil];
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
{
TGDownloadMediaAdapter *adapter = [[TGDownloadMediaAdapter alloc] initWithAttachment:attachment conversationId:cid messageId:mid];
[adapter startWithCompletion:^(NSString *path)
{
if (path != nil)
{
[subscriber putNext:path];
[subscriber putCompletion];
}
else
{
[subscriber putError:nil];
}
} progress:nil];
return [[SBlockDisposable alloc] initWithBlock:^
{
[adapter description];
}];
}];
}
+ (TGBridgeSignalManager *)signalManager
{
static dispatch_once_t onceToken;
static TGBridgeSignalManager *signalManager;
dispatch_once(&onceToken, ^
{
signalManager = [[TGBridgeSignalManager alloc] init];
});
return signalManager;
}
+ (NSString *)pathForDocumentMediaAttachment:(TGDocumentMediaAttachment *)documentMedia
{
if (documentMedia.localDocumentId != 0)
{
NSString *path = [[TGPreparedLocalDocumentMessage localDocumentDirectoryForLocalDocumentId:documentMedia.localDocumentId] stringByAppendingPathComponent:documentMedia.safeFileName];
return path;
}
NSString *path = [[TGPreparedLocalDocumentMessage localDocumentDirectoryForDocumentId:documentMedia.documentId] stringByAppendingPathComponent:documentMedia.safeFileName];
return path;
}
@end