VLCPlayerControlWebSocket.m 9.77 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*****************************************************************************
 * VLCPlayerControlWebSocket.m
 * VLC for iOS
 *****************************************************************************
 * Copyright (c) 2015 VideoLAN. All rights reserved.
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan.org>
 *
 * Refer to the COPYING file of the official project for license.
 *****************************************************************************/

#import "VLCPlayerControlWebSocket.h"
14
#import "VLCMetadata.h"
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

@implementation VLCPlayerControlWebSocket

- (void)didOpen
{
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter addObserver:self
                           selector:@selector(playbackStarted)
                               name:VLCPlaybackControllerPlaybackDidStart
                             object:nil];
    [notificationCenter addObserver:self
                           selector:@selector(playbackStarted)
                               name:VLCPlaybackControllerPlaybackDidResume
                             object:nil];
    [notificationCenter addObserver:self
                           selector:@selector(_respondToPlaying)
                               name:VLCPlaybackControllerPlaybackMetadataDidChange
                             object:nil];
    [notificationCenter addObserver:self
                           selector:@selector(playbackPaused)
                               name:VLCPlaybackControllerPlaybackDidPause
                             object:nil];
    [notificationCenter addObserver:self
                           selector:@selector(playbackEnded)
                               name:VLCPlaybackControllerPlaybackDidStop
                             object:nil];
    [notificationCenter addObserver:self
                           selector:@selector(playbackEnded)
                               name:VLCPlaybackControllerPlaybackDidFail
                             object:nil];
    [notificationCenter addObserver:self
                           selector:@selector(playbackSeekTo)
                               name:VLCPlaybackControllerPlaybackPositionUpdated
                             object:nil];

    APLog(@"web socket did open");

    [super didOpen];
}

- (void)didReceiveMessage:(NSString *)msg
{
57 58 59 60 61 62 63 64 65 66 67 68 69 70
    NSError *error;
    NSDictionary *receivedDict = [NSJSONSerialization JSONObjectWithData:[msg dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];

    if (error != nil) {
        APLog(@"JSON deserialization failed for %@", msg);
        return;
    }

    NSString *type = receivedDict[@"type"];
    if (!type) {
        APLog(@"No type in received JSON dict %@", receivedDict);
    }

    if ([type isEqualToString:@"playing"]) {
71
        [self _respondToPlaying];
72
    } else if ([type isEqualToString:@"play"]) {
73
        [self _respondToPlay];
74
    } else if ([type isEqualToString:@"pause"]) {
75
        [self _respondToPause];
76
    } else if ([type isEqualToString:@"ended"]) {
77
        [self _respondToEnded];
78 79
    } else if ([type isEqualToString:@"seekTo"]) {
        [self _respondToSeek:receivedDict];
80
    } else if ([type isEqualToString:@"openURL"]) {
81
        [self performSelectorOnMainThread:@selector(_respondToOpenURL:) withObject:receivedDict waitUntilDone:NO];
82
    } else if ([type isEqualToString:@"volume"]) {
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        [self sendMessage:@"VOLUME CONTROL NOT SUPPORTED ON THIS DEVICE"];
    } else
        [self sendMessage:@"INVALID REQUEST!"];
}

#ifndef NDEBUG
- (void)didClose
{
    APLog(@"web socket did close");

    [super didClose];
}
#endif

- (void)_respondToPlaying
{
    /* JSON response
     {
        "type": "playing",
        "currentTime": 42,
        "media": {
            "id": "some id",
            "title": "some title",
            "duration": 120000
        }
     }
     */

    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
    NSDictionary *returnDict;

114 115 116 117 118 119 120 121
    if (vpc.isPlaying) {
        VLCMedia *media = [vpc currentlyPlayingMedia];

        if (media) {
            NSURL *url = media.url;
            NSString *mediaTitle = vpc.metadata.title;
            if (!mediaTitle) {
                mediaTitle = url.lastPathComponent;
122
            }
123 124 125 126 127 128
            NSDictionary *mediaDict = @{ @"id" : url.absoluteString,
                                         @"title" : mediaTitle,
                                         @"duration" : @([vpc mediaDuration])};
            returnDict = @{ @"currentTime" : @([vpc playedTime].intValue),
                            @"type" : @"playing",
                            @"media" : mediaDict };
129 130 131 132 133
        }
    }
    if (!returnDict) {
        returnDict = [NSDictionary dictionary];
    }
134
    [self sendDataWithDict:returnDict];
135 136 137 138 139 140 141
}

#pragma mark - play

- (void)_respondToPlay
{
    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
142
    [vpc play];
143 144 145 146 147 148 149
}

- (void)playbackStarted
{
    /*
     {
        "type": "play",
150
        "currentTime": 42
151 152
     }
     */
153 154 155 156
     VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
    NSDictionary *dict = @{ @"currentTime" : @([vpc playedTime].intValue),
                                  @"type" : @"play" };
    [self sendDataWithDict:dict];
157 158 159 160 161 162 163 164

}

#pragma mark - pause

- (void)_respondToPause
{
    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
165
    [vpc pause];
166 167 168 169 170 171 172 173 174 175
}

- (void)playbackPaused
{
    /*
     {
        "type": "pause",
        "currentTime": 42,
     }
     */
176 177 178 179 180
     VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
    NSDictionary *dict = @{ @"currentTime" : @([vpc playedTime].intValue),
                            @"type" : @"pause" };
    [self sendDataWithDict:dict];
}
181

182 183
- (void)sendDataWithDict:(NSDictionary *)dict
{
184 185
    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];

186 187 188 189 190 191
    VLCMedia *media = [vpc currentlyPlayingMedia];
    if (media) {
        NSError *error;
        NSData *returnData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
        if (error != nil) {
            APLog(@"%s: JSON serialization failed %@", __PRETTY_FUNCTION__, error);
192
        }
193 194

        [self sendData:returnData];
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    }
}

#pragma mark - ended

- (void)_respondToEnded
{
    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
    [vpc stopPlayback];
}

- (void)playbackEnded
{
    /*
     {
210
        "type": "ended"
211 212
     }
     */
213 214
    NSDictionary *dict = @{ @"type" : @"ended" };
    [self sendDataWithDict:dict];
215 216 217 218
}

#pragma mark - seek

219
- (void)_respondToSeek:(NSDictionary *)dictionary
220
{
221 222 223 224 225 226 227 228
    /*
     {
        "currentTime" = 12514;
        "type" = seekTo;
     }
     */
    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];

229
    VLCMedia *media = [vpc currentlyPlayingMedia];
230 231 232
    if (!media)
        return;

233
    vpc.playbackPosition = [dictionary[@"currentTime"] floatValue] / (CGFloat)media.length.intValue;
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
}

- (void)playbackSeekTo
{
    /* 
     {
        "type": "seekTo",
        "currentTime": 42,
        "media": {
            "id": 42
        }
     }
     */

    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
249 250 251 252 253 254
    VLCMedia *media = [vpc currentlyPlayingMedia];
    NSDictionary *mediaDict = @{ @"id" : media.url.absoluteString};
    NSDictionary *dict = @{ @"currentTime" : @([vpc playedTime].intValue),
                                  @"type" : @"seekTo",
                                  @"media" : mediaDict };
    [self sendDataWithDict:dict];
255 256
}

257 258 259 260 261 262 263 264 265
#pragma mark - openURL
- (void)_respondToOpenURL:(NSDictionary *)dictionary
{
    /*
     {
        "type": "OpenURL",
        "url": "https://vimeo.com/74370512"
     }
     */
266
    BOOL needsMediaList = NO;
267 268 269 270 271 272 273 274

    VLCPlaybackController *vpc = [VLCPlaybackController sharedInstance];
    VLCMediaList *mediaList = vpc.mediaList;
    if (!mediaList) {
        needsMediaList = YES;
        mediaList = [[VLCMediaList alloc] init];
    }

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
    NSString *urlString = dictionary[@"url"];
    if (urlString == nil || urlString.length == 0)
        return;

    /* force store update */
    NSUbiquitousKeyValueStore *ubiquitousKeyValueStore = [NSUbiquitousKeyValueStore defaultStore];
    [ubiquitousKeyValueStore synchronize];

    /* fetch data from cloud */
    NSMutableArray *recentURLs = [NSMutableArray arrayWithArray:[ubiquitousKeyValueStore arrayForKey:kVLCRecentURLs]];

    /* re-order array and add item */
    if ([recentURLs indexOfObject:urlString] != NSNotFound)
        [recentURLs removeObject:urlString];

    if (recentURLs.count >= 100)
        [recentURLs removeLastObject];
    [recentURLs addObject:urlString];

    /* sync back */
    [ubiquitousKeyValueStore setArray:recentURLs forKey:kVLCRecentURLs];

    [mediaList addMedia:[VLCMedia mediaWithURL:[NSURL URLWithString:urlString]]];
298
    if (needsMediaList) {
299
        [vpc playMediaList:mediaList firstIndex:0 subtitlesFilePath:nil];
300

301
        VLCFullscreenMovieTVViewController *movieVC = [VLCFullscreenMovieTVViewController fullscreenMovieTVViewController];
302 303 304 305 306 307 308 309 310 311
        if ([[[UIApplication sharedApplication].delegate.window rootViewController] presentedViewController] != nil) {
            [[[[UIApplication sharedApplication].delegate.window rootViewController] presentedViewController] presentViewController:movieVC
                                                                                                                           animated:NO
                                                                                                                         completion:nil];
        } else {
            [[[UIApplication sharedApplication].delegate.window rootViewController] presentViewController:movieVC
                                                                                                 animated:NO
                                                                                               completion:nil];
        }
    }
312 313
}

314
@end