VLCWatchCommunication.m 6.66 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*****************************************************************************
 * VLCWatchCommunication.m
 * VLC for iOS
 *****************************************************************************
 * Copyright (c) 2015 VideoLAN. All rights reserved.
 * $Id$
 *
 * Author: Tobias Conradi <videolan # tobias-conradi.de>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/


#import "VLCWatchCommunication.h"
#import "VLCWatchMessage.h"
#import "VLCPlaybackController+MediaLibrary.h"
#import <MediaPlayer/MediaPlayer.h>

@implementation VLCWatchCommunication

Tobias's avatar
Tobias committed
21
22
23
24
+ (BOOL)isSupported {
    return [WCSession class] != nil && [WCSession isSupported];
}

25
26
27
28
29
30
31
32
33
34
35
36
37
- (instancetype)init
{
    self = [super init];
    if (self) {
        if ([WCSession isSupported]) {
            WCSession *session = [WCSession defaultSession];
            session.delegate = self;
            [session activateSession];
        }
    }
    return self;
}

38
39
40
41
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:nil];
}

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
static VLCWatchCommunication *_singeltonInstance = nil;

+ (VLCWatchCommunication *)sharedInstance
{
    @synchronized(self) {
        static dispatch_once_t pred;
        dispatch_once(&pred, ^{
            _singeltonInstance = [[self alloc] init];
        });
    }
    return _singeltonInstance;
}

- (void)playFileFromWatch:(VLCWatchMessage *)message
{
    NSManagedObject *managedObject = nil;
    NSString *uriString = (id)message.payload;
    if ([uriString isKindOfClass:[NSString class]]) {
        NSURL *uriRepresentation = [NSURL URLWithString:uriString];
        managedObject = [[MLMediaLibrary sharedMediaLibrary] objectForURIRepresentation:uriRepresentation];
    }
    if (managedObject == nil) {
        APLog(@"%s file not found: %@",__PRETTY_FUNCTION__,message);
        return;
    }

    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
    [vpc playMediaLibraryObject:managedObject];
}

72
- (NSDictionary *)handleMessage:(nonnull VLCWatchMessage *)message {
73
74
75
76
77
78
79
80
81
    UIApplication *application = [UIApplication sharedApplication];
    /* dispatch background task */
    __block UIBackgroundTaskIdentifier taskIdentifier = [application beginBackgroundTaskWithName:nil
                                                                               expirationHandler:^{
                                                                                   [application endBackgroundTask:taskIdentifier];
                                                                                   taskIdentifier = UIBackgroundTaskInvalid;
                                                                               }];

    NSString *name = message.name;
82
    NSDictionary *responseDict = @{};
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    if ([name isEqualToString:VLCWatchMessageNameGetNowPlayingInfo]) {
        responseDict = [self nowPlayingResponseDict];
    } else if ([name isEqualToString:VLCWatchMessageNamePlayPause]) {
        [[VLCPlaybackController sharedInstance] playPause];
        responseDict = @{@"playing": @([VLCPlaybackController sharedInstance].isPlaying)};
    } else if ([name isEqualToString:VLCWatchMessageNameSkipForward]) {
        [[VLCPlaybackController sharedInstance] forward];
    } else if ([name isEqualToString:VLCWatchMessageNameSkipBackward]) {
        [[VLCPlaybackController sharedInstance] backward];
    } else if ([name isEqualToString:VLCWatchMessageNamePlayFile]) {
        [self playFileFromWatch:message];
    } else if ([name isEqualToString:VLCWatchMessageNameSetVolume]) {
        [self setVolumeFromWatch:message];
    } else {
97
        APLog(@"Did not handle request from WatchKit Extension: %@",message);
98
    }
99
100
101
102
103
104
    return responseDict;
}

- (void)session:(nonnull WCSession *)session didReceiveMessage:(nonnull NSDictionary<NSString *,id> *)userInfo replyHandler:(nonnull void (^)(NSDictionary<NSString *,id> * _Nonnull))replyHandler {
    VLCWatchMessage *message = [[VLCWatchMessage alloc] initWithDictionary:userInfo];
    NSDictionary *responseDict = [self handleMessage:message];
105
106
107
    replyHandler(responseDict);
}

108
109
110
111
112
- (void)session:(nonnull WCSession *)session didReceiveMessage:(nonnull NSDictionary<NSString *,id> *)messageDict {
    VLCWatchMessage *message = [[VLCWatchMessage alloc] initWithDictionary:messageDict];
    [self handleMessage:message];
}

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

- (void)setVolumeFromWatch:(VLCWatchMessage *)message
{
    NSNumber *volume = (id)message.payload;
    if ([volume isKindOfClass:[NSNumber class]]) {
        /*
         * Since WatchKit doesn't provide something like MPVolumeView we use deprecated API.
         * rdar://20783803 Feature Request: WatchKit equivalent for MPVolumeView
         */
        [MPMusicPlayerController applicationMusicPlayer].volume = volume.floatValue;
    }
}

- (NSDictionary *)nowPlayingResponseDict {
    NSMutableDictionary *response = [NSMutableDictionary new];
    NSMutableDictionary *nowPlayingInfo = [[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo mutableCopy];
    NSNumber *playbackTime = [VLCPlaybackController sharedInstance].mediaPlayer.time.numberValue;
    if (playbackTime) {
        nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(playbackTime.floatValue/1000);
    }
    if (nowPlayingInfo) {
        response[@"nowPlayingInfo"] = nowPlayingInfo;
    }
    MLFile *currentFile = [VLCPlaybackController sharedInstance].currentlyPlayingMediaFile;
    NSString *URIString = currentFile.objectID.URIRepresentation.absoluteString;
    if (URIString) {
        response[@"URIRepresentation"] = URIString;
    }

    response[@"volume"] = @([MPMusicPlayerController applicationMusicPlayer].volume);

    return response;
}

147
148
149
150
151
152
153
154
#pragma mark - Notifications
- (void)startRelayingNotificationName:(nullable NSString *)name object:(nullable id)object {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(relayNotification:) name:name object:object];
}
- (void)stopRelayingNotificationName:(nullable NSString *)name object:(nullable id)object {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:name object:object];
}
- (void)relayNotification:(NSNotification *)notification {
155
156
157
158
159
160

    NSMutableDictionary *payload = [NSMutableDictionary dictionary];
    payload[@"name"] = notification.name;
    if (notification.userInfo) {
        payload[@"userInfo"] = notification.userInfo;
    }
161
    NSDictionary *dict = [VLCWatchMessage messageDictionaryForName:VLCWatchMessageNameNotification
162
                                                           payload:payload];
163
164
165
166
167
    if ([WCSession isSupported] && [[WCSession defaultSession] isReachable]) {
        [[WCSession defaultSession] sendMessage:dict replyHandler:nil errorHandler:nil];
    }
}

168
@end