瀏覽代碼

now playing info view with basic control works

Tobias Conradi 10 年之前
父節點
當前提交
9e558dafaa

+ 18 - 8
Sources/VLCAppDelegate.m

@@ -15,7 +15,6 @@
  * Refer to the COPYING file of the official project for license.
  *****************************************************************************/
 
-#import <notify.h>
 #import "VLCAppDelegate.h"
 #import "VLCMediaFileDiscoverer.h"
 #import "NSString+SupportedMedia.h"
@@ -32,6 +31,7 @@
 #import "BWQuincyManager.h"
 #import "VLCAlertView.h"
 #import <BoxSDK/BoxSDK.h>
+#import "VLCNotificationRelay.h"
 
 @interface VLCAppDelegate () <PAPasscodeViewControllerDelegate, VLCMediaFileDiscovererDelegate, BWQuincyManagerDelegate> {
     PAPasscodeViewController *_passcodeLockController;
@@ -144,7 +144,9 @@
         setupBlock();
     }
 
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notifiyWatchForDBUpdate) name:NSManagedObjectContextDidSaveNotification object:nil];
+    [[VLCNotificationRelay sharedRelay] addRelayLocalName:NSManagedObjectContextDidSaveNotification toRemoteName:@"org.videolan.ios-app.dbupdate"];
+
+    [[VLCNotificationRelay sharedRelay] addRelayLocalName:NSManagedObjectContextDidSaveNotification toRemoteName:@"org.videolan.ios-app.nowPlayingInfoUpdate"];
 
     return YES;
 }
@@ -563,12 +565,20 @@
 }
 
 #pragma mark - watch struff
-- (void)notifiyWatchForDBUpdate
-{
-    notify_post("org.videolan.ios-app.dbupdate");
-}
 - (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply {
-
+    NSDictionary *reponseDict = nil;
+    if ([userInfo[@"name"] isEqualToString:@"getNowPlayingInfo"]) {
+        reponseDict = [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo;
+    } else if ([userInfo[@"name"] isEqualToString:@"playpause"]) {
+        [_movieViewController playPause];
+    } else if ([userInfo[@"name"] isEqualToString:@"skipForward"]) {
+        [_movieViewController forward:nil];
+    } else if ([userInfo[@"name"] isEqualToString:@"skipBackward"]) {
+        [_movieViewController backward:nil];
+    }
+    else {
+        NSLog(@"Did not handle request from WatchKit Extension: %@",userInfo);
+    }
+    reply(reponseDict);
 }
-
 @end

+ 1 - 0
Sources/VLCMovieViewController.m

@@ -2311,6 +2311,7 @@ static inline NSArray * RemoteCommandCenterCommandsToHandle(MPRemoteCommandCente
     }
 
     [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = currentlyPlayingTrackInfo;
+    [[NSNotificationCenter defaultCenter] postNotificationName:@"nowPlayingInfoUpdate" object:self];
 }
 
 #pragma mark - autorotation

+ 39 - 3
VLC for iOS WatchKit App/Base.lproj/Interface.storyboard

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="6751" systemVersion="14C1514" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="AgC-eL-Hgc">
+<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="7528.3" systemVersion="14C1514" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="AgC-eL-Hgc">
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7518.3"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="3737"/>
     </dependencies>
     <scenes>
@@ -33,7 +33,43 @@
                     </connections>
                 </controller>
             </objects>
-            <point key="canvasLocation" x="250" y="208"/>
+            <point key="canvasLocation" x="221" y="216"/>
+        </scene>
+        <!--nowPlaying-->
+        <scene sceneID="NHj-Mq-ifc">
+            <objects>
+                <controller identifier="nowPlaying" id="Mzo-Y8-gdK" customClass="VLCNowPlayingInterfaceController">
+                    <items>
+                        <label alignment="left" text="title" textAlignment="left" numberOfLines="0" id="H58-Y8-Tbc"/>
+                        <label alignment="left" text="duration" id="D0h-cq-wsv"/>
+                        <button width="1" alignment="left" title="playpause" id="BAZ-aC-ETt">
+                            <connections>
+                                <action selector="playPausePressed" destination="Mzo-Y8-gdK" id="6p8-JZ-0Gh"/>
+                            </connections>
+                        </button>
+                        <group width="1" alignment="left" id="uwS-0S-Ag2">
+                            <items>
+                                <button width="0.5" alignment="left" title="&lt;&lt;" id="uKa-8V-C8x">
+                                    <connections>
+                                        <action selector="skipBackward" destination="Mzo-Y8-gdK" id="aP1-vb-XwF"/>
+                                    </connections>
+                                </button>
+                                <button width="0.5" alignment="left" title="&gt;&gt;" id="w8s-Mc-7oV">
+                                    <connections>
+                                        <action selector="skipForward" destination="Mzo-Y8-gdK" id="1kf-Nh-kjr"/>
+                                    </connections>
+                                </button>
+                            </items>
+                        </group>
+                    </items>
+                    <connections>
+                        <outlet property="durationLabel" destination="D0h-cq-wsv" id="3AN-YZ-yEj"/>
+                        <outlet property="playPauseButton" destination="BAZ-aC-ETt" id="X17-bz-cFy"/>
+                        <outlet property="titleLabel" destination="H58-Y8-Tbc" id="xZs-ZW-Shj"/>
+                    </connections>
+                </controller>
+            </objects>
+            <point key="canvasLocation" x="221" y="605"/>
         </scene>
     </scenes>
 </document>

+ 19 - 8
VLC for iOS WatchKit Extension/InterfaceController.m

@@ -10,9 +10,12 @@
 #import <MediaLibraryKit/MediaLibraryKit.h>
 #import "VLCRowController.h"
 #import <MobileVLCKit/VLCTime.h>
-#import "VLCDBChangeNotifier.h"
+
+#import "VLCNotificationRelay.h"
 
 static NSString *const rowType = @"mediaRow";
+static NSString *const VLCDBUpdateNotification = @"VLCUpdateDataBase";
+static NSString *const VLCDBUpdateNotificationRemote = @"org.videolan.ios-app.dbupdate";
 
 @interface InterfaceController()
 @property (nonatomic, strong) NSMutableArray *mediaObjects;
@@ -32,19 +35,20 @@ static NSString *const rowType = @"mediaRow";
     mediaLibrary.additionalPersitentStoreOptions = @{NSReadOnlyPersistentStoreOption : @YES};
 
     self.title = NSLocalizedString(@"LIBRARY_MUSIC", nil);
-    [[VLCDBChangeNotifier sharedNotifier] addObserver:self block:^{
-        [self updateData];
-    }];
+    [[VLCNotificationRelay sharedRelay] addRelayRemoteName:VLCDBUpdateNotificationRemote toLocalName:VLCDBUpdateNotification];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateData) name:VLCDBUpdateNotification object:nil];
+
     [self updateData];
+
+    [self addMenuItemWithItemIcon:WKMenuItemIconMore title:@"currently playing" action:@selector(showNowPlaying:)];
 }
 
 - (void)willActivate {
     // This method is called when watch view controller is about to be visible to user
     [super willActivate];
     NSLog(@"%s",__PRETTY_FUNCTION__);
-    [[VLCDBChangeNotifier sharedNotifier] addObserver:self block:^{
-        [self updateData];
-    }];
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateData) name:VLCDBUpdateNotification object:nil];
 }
 
 - (void)didDeactivate {
@@ -52,9 +56,16 @@ static NSString *const rowType = @"mediaRow";
     [super didDeactivate];
     NSLog(@"%s",__PRETTY_FUNCTION__);
 
-    [[VLCDBChangeNotifier sharedNotifier] removeObserver:self];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:VLCDBUpdateNotification object:nil];
 }
 
+
+- (void)showNowPlaying:(id)sender {
+    [self presentControllerWithName:@"nowPlaying" context:nil];
+}
+
+#pragma mark - data handling
+
 - (void)updateData {
     NSArray *oldObjects = self.mediaObjects;
     NSSet *oldSet = [[NSSet alloc] initWithArray:oldObjects];

+ 0 - 15
VLC for iOS WatchKit Extension/VLCDBChangeNotifier.h

@@ -1,15 +0,0 @@
-//
-//  VLCDBChangeNotifier.h
-//  VLC for iOS
-//
-//  Created by Tobias Conradi on 01.04.15.
-//  Copyright (c) 2015 VideoLAN. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface VLCDBChangeNotifier : NSObject
-+ (instancetype)sharedNotifier;
-- (void)addObserver:(id)observer block:(void (^)(void))onUpdate;
-- (void)removeObserver:(id)observer;
-@end

+ 0 - 67
VLC for iOS WatchKit Extension/VLCDBChangeNotifier.m

@@ -1,67 +0,0 @@
-//
-//  VLCDBChangeNotifier.m
-//  VLC for iOS
-//
-//  Created by Tobias Conradi on 01.04.15.
-//  Copyright (c) 2015 VideoLAN. All rights reserved.
-//
-
-#import "VLCDBChangeNotifier.h"
-#import <notify.h>
-
-
-@interface VLCDBChangeNotifier ()
-@property (nonatomic, strong) NSMapTable *observers;
-@property (nonatomic, assign) int notification_token;
-@end
-@implementation VLCDBChangeNotifier
-
-- (id)init
-{
-    self = [super init];
-    if (self) {
-        self.observers = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality valueOptions:NSPointerFunctionsCopyIn];
-    }
-    [self startListening];
-    return self;
-}
-
-- (void)dealloc {
-    notify_cancel(_notification_token);
-}
-
-+ (instancetype)sharedNotifier
-{
-    static dispatch_once_t onceToken;
-    static VLCDBChangeNotifier *instance;
-    dispatch_once(&onceToken, ^{
-        instance = [VLCDBChangeNotifier new];
-    });
-    return instance;
-}
-
-- (void)addObserver:(id)observer block:(void (^)(void))onUpdate {
-    [self.observers setObject:onUpdate forKey:observer];
-}
-
-- (void)removeObserver:(id)observer {
-    [self.observers removeObjectForKey:observer];
-}
-
-- (void)dbDidChange {
-    for (void(^onUpdate)() in self.observers.objectEnumerator) {
-        onUpdate();
-    }
-}
-- (void)startListening {
-    const char *notification_name = "org.videolan.ios-app.dbupdate";
-    dispatch_queue_t queue = dispatch_get_main_queue();
-    int registration_token;
-    __weak typeof(self) weakSelf = self;
-    notify_register_dispatch(notification_name, &registration_token, queue, ^ (int token) {
-        [weakSelf dbDidChange];
-    });
-    self.notification_token = registration_token;
-}
-
-@end

+ 23 - 0
VLC for iOS WatchKit Extension/VLCNotificationRelay.h

@@ -0,0 +1,23 @@
+//
+//  VLCNotificationRelay.h
+//  VLC for iOS
+//
+//  Created by Tobias Conradi on 02.04.15.
+//  Copyright (c) 2015 VideoLAN. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface VLCNotificationRelay : NSObject
++ (instancetype)sharedRelay;
+
+/* relays NSNotificationCenter notifications with localName to CFNotifactionCenter with remoteName */
+- (void)addRelayLocalName:(NSString *)localName toRemoteName:(NSString *)remoteName;
+- (void)removeRelayLocalName:(NSString *)localName;
+
+
+/* relays CFNotifactionCenter with remoteName to  NSNotificationCenter notifications with localName */
+- (void)addRelayRemoteName:(NSString *)remoteName toLocalName:(NSString *)localName;
+- (void)removeRelayRemoteName:(NSString *)remoteName;
+
+@end

+ 85 - 0
VLC for iOS WatchKit Extension/VLCNotificationRelay.m

@@ -0,0 +1,85 @@
+//
+//  VLCNotificationRelay.m
+//  VLC for iOS
+//
+//  Created by Tobias Conradi on 02.04.15.
+//  Copyright (c) 2015 VideoLAN. All rights reserved.
+//
+
+#import "VLCNotificationRelay.h"
+
+@interface VLCNotificationRelay ()
+@property (nonatomic, readonly) NSMutableDictionary *localToRemote;
+@property (nonatomic, readonly) NSMutableDictionary *remoteToLocal;
+@end
+
+@implementation VLCNotificationRelay
+
++ (instancetype)sharedRelay
+{
+    static dispatch_once_t onceToken;
+    static VLCNotificationRelay *instance;
+    dispatch_once(&onceToken, ^{
+        instance = [VLCNotificationRelay new];
+    });
+    return instance;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        _localToRemote = [NSMutableDictionary dictionary];
+        _remoteToLocal = [NSMutableDictionary dictionary];
+    }
+    return self;
+}
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
+    CFNotificationCenterRemoveObserver(center, (__bridge const void *)(self), NULL, NULL);
+}
+
+- (void)addRelayLocalName:(NSString *)localName toRemoteName:(NSString *)remoteName {
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localNotification:) name:localName object:nil];
+    self.localToRemote[localName] = remoteName;
+}
+- (void)removeRelayLocalName:(NSString *)localName {
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:localName object:nil];
+    [self.localToRemote removeObjectForKey:localName];
+}
+
+- (void)addRelayRemoteName:(NSString *)remoteName toLocalName:(NSString *)localName {
+    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
+    CFNotificationCenterAddObserver(center, (__bridge  const void *)(self), notificationCallback, (__bridge CFStringRef)remoteName, NULL, CFNotificationSuspensionBehaviorHold);
+}
+- (void)removeRelayRemoteName:(NSString *)remoteName {
+    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
+    CFNotificationCenterRemoveObserver(center, (__bridge const void *)(self), (__bridge CFStringRef)remoteName, NULL);
+}
+
+#pragma mark - notification handeling
+- (void)localNotification:(NSNotification *)notification {
+
+    NSString *localName = notification.name;
+    NSString *remoteName = self.localToRemote[localName];
+
+    /* in current version of iOS this is ignored for the darwin center
+     * nevertheless we use it to be future proof
+     */
+    NSDictionary *userInfo = notification.userInfo;
+
+    CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
+    CFNotificationCenterPostNotification(center, (__bridge CFStringRef)remoteName, NULL, (__bridge CFDictionaryRef)userInfo, false);
+}
+
+static void notificationCallback(CFNotificationCenterRef center, void* observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
+{
+    VLCNotificationRelay *relay = (__bridge VLCNotificationRelay*) observer;
+    NSString *remoteName = (__bridge NSString *)name;
+    NSString *localName = relay.remoteToLocal[remoteName];
+    [[NSNotificationCenter defaultCenter] postNotificationName:localName object:nil userInfo:(__bridge NSDictionary *)userInfo];
+}
+
+
+@end

+ 22 - 0
VLC for iOS WatchKit Extension/VLCNowPlayingInterfaceController.h

@@ -0,0 +1,22 @@
+//
+//  VLCNowPlayingInterfaceController.h
+//  VLC for iOS
+//
+//  Created by Tobias Conradi on 02.04.15.
+//  Copyright (c) 2015 VideoLAN. All rights reserved.
+//
+
+#import <WatchKit/WatchKit.h>
+#import <Foundation/Foundation.h>
+
+@interface VLCNowPlayingInterfaceController : WKInterfaceController
+@property (weak, nonatomic) IBOutlet WKInterfaceLabel *titleLabel;
+@property (weak, nonatomic) IBOutlet WKInterfaceLabel *durationLabel;
+@property (weak, nonatomic) IBOutlet WKInterfaceButton *playPauseButton;
+
+- (IBAction)playPausePressed;
+- (IBAction)skipForward;
+- (IBAction)skipBackward;
+
+
+@end

+ 89 - 0
VLC for iOS WatchKit Extension/VLCNowPlayingInterfaceController.m

@@ -0,0 +1,89 @@
+//
+//  VLCNowPlayingInterfaceController.m
+//  VLC for iOS
+//
+//  Created by Tobias Conradi on 02.04.15.
+//  Copyright (c) 2015 VideoLAN. All rights reserved.
+//
+
+#import "VLCNowPlayingInterfaceController.h"
+#import <MediaPlayer/MediaPlayer.h>
+#import <MobileVLCKit/VLCTime.h>
+#import "VLCNotificationRelay.h"
+
+@interface VLCNowPlayingInterfaceController ()
+@property (nonatomic, copy) NSString *titleString;
+@property (nonatomic, copy) NSNumber *playBackDurationNumber;
+@end
+
+@implementation VLCNowPlayingInterfaceController
+
+- (void)awakeWithContext:(id)context {
+    [super awakeWithContext:context];
+
+    // Configure interface objects here.
+    [self requestNowPlayingInfo];
+    [[VLCNotificationRelay sharedRelay] addRelayRemoteName:@"org.videolan.ios-app.nowPlayingInfoUpdate" toLocalName:@"nowPlayingInfoUpdate"];
+}
+
+- (void)willActivate {
+    // This method is called when watch view controller is about to be visible to user
+    [super willActivate];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(requestNowPlayingInfo) name:@"nowPlayingInfoUpdate" object:nil];
+    [self requestNowPlayingInfo];
+
+}
+- (void)didDeactivate {
+    // This method is called when watch view controller is no longer visible
+    [super didDeactivate];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"nowPlayingInfoUpdate" object:nil];
+}
+
+- (void)requestNowPlayingInfo {
+    [WKInterfaceController openParentApplication:@{@"name": @"getNowPlayingInfo"} reply:^(NSDictionary *replyInfo, NSError *error) {
+        [self updateWithNowPlayingInfo:replyInfo];
+        NSLog(@"nowplayingInfo: %@",replyInfo);
+    }];
+}
+- (void)updateWithNowPlayingInfo:(NSDictionary*)nowPlayingInfo {
+    self.titleString = nowPlayingInfo[MPMediaItemPropertyTitle];
+    self.playBackDurationNumber = nowPlayingInfo[MPMediaItemPropertyPlaybackDuration];
+}
+
+- (IBAction)playPausePressed {
+    [WKInterfaceController openParentApplication:@{@"name": @"playpause"} reply:^(NSDictionary *replyInfo, NSError *error) {
+        NSLog(@"playpause %@",replyInfo);
+    }];
+}
+
+- (IBAction)skipForward {
+    [WKInterfaceController openParentApplication:@{@"name": @"skipForward"} reply:^(NSDictionary *replyInfo, NSError *error) {
+        NSLog(@"skipForward %@",replyInfo);
+    }];
+}
+
+- (IBAction)skipBackward {
+    [WKInterfaceController openParentApplication:@{@"name": @"skipBackward"} reply:^(NSDictionary *replyInfo, NSError *error) {
+        NSLog(@"skipBackward %@",replyInfo);
+    }];
+}
+
+
+
+- (void)setTitleString:(NSString *)titleString {
+    if (![_titleString isEqualToString:titleString] || (_titleString==nil && titleString)) {
+        _titleString = [titleString copy];
+        [self.titleLabel setText:titleString];
+    }
+}
+
+- (void)setPlayBackDurationNumber:(NSNumber *)playBackDurationNumber {
+    if (![_playBackDurationNumber isEqualToNumber:playBackDurationNumber] || (_playBackDurationNumber==nil && playBackDurationNumber)) {
+        _playBackDurationNumber = playBackDurationNumber;
+        [self.durationLabel setText:[VLCTime timeWithNumber:playBackDurationNumber].stringValue];
+    }
+}
+
+@end
+
+

+ 14 - 6
VLC for iOS.xcodeproj/project.pbxproj

@@ -540,7 +540,9 @@
 		DD02C3071ACAEC690026EFEE /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1BBC4D170493A300A20CBF /* libbz2.dylib */; };
 		DD02C30B1ACAF0370026EFEE /* libstdc++.6.0.9.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DD02C30A1ACAF0370026EFEE /* libstdc++.6.0.9.dylib */; };
 		DD02C30E1ACAF4A50026EFEE /* VLCRowController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD02C30D1ACAF4A50026EFEE /* VLCRowController.m */; };
-		DDCA94791ACC12630044449A /* VLCDBChangeNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = DDCA94781ACC12630044449A /* VLCDBChangeNotifier.m */; };
+		DD6FA7B01ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = DD6FA7AF1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m */; };
+		DDE4906C1ACDB63F00B1B5E3 /* VLCNotificationRelay.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE4906B1ACDB63F00B1B5E3 /* VLCNotificationRelay.m */; };
+		DDE4906D1ACDBEA000B1B5E3 /* VLCNotificationRelay.m in Sources */ = {isa = PBXBuildFile; fileRef = DDE4906B1ACDB63F00B1B5E3 /* VLCNotificationRelay.m */; };
 		DDF157B11ACB162700AAFBC6 /* MediaLibrary.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7D594CBC1A969E33004BFB17 /* MediaLibrary.xcdatamodeld */; };
 		DDF157B21ACB169600AAFBC6 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC1BBC57170493E100A20CBF /* CoreData.framework */; };
 		DDF157B41ACB169B00AAFBC6 /* WatchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDF157B31ACB169B00AAFBC6 /* WatchKit.framework */; };
@@ -1573,8 +1575,10 @@
 		DD02C30A1ACAF0370026EFEE /* libstdc++.6.0.9.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.6.0.9.dylib"; path = "usr/lib/libstdc++.6.0.9.dylib"; sourceTree = SDKROOT; };
 		DD02C30C1ACAF4A50026EFEE /* VLCRowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCRowController.h; sourceTree = "<group>"; };
 		DD02C30D1ACAF4A50026EFEE /* VLCRowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCRowController.m; sourceTree = "<group>"; };
-		DDCA94771ACC12630044449A /* VLCDBChangeNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCDBChangeNotifier.h; sourceTree = "<group>"; };
-		DDCA94781ACC12630044449A /* VLCDBChangeNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCDBChangeNotifier.m; sourceTree = "<group>"; };
+		DD6FA7AE1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCNowPlayingInterfaceController.h; sourceTree = "<group>"; };
+		DD6FA7AF1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCNowPlayingInterfaceController.m; sourceTree = "<group>"; };
+		DDE4906A1ACDB63F00B1B5E3 /* VLCNotificationRelay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCNotificationRelay.h; sourceTree = "<group>"; };
+		DDE4906B1ACDB63F00B1B5E3 /* VLCNotificationRelay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCNotificationRelay.m; sourceTree = "<group>"; };
 		DDF157B31ACB169B00AAFBC6 /* WatchKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WatchKit.framework; path = System/Library/Frameworks/WatchKit.framework; sourceTree = SDKROOT; };
 		E09EACF57CDD22ABAE66CDD0 /* Pods-vlc-ios.distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-vlc-ios.distribution.xcconfig"; path = "Pods/Target Support Files/Pods-vlc-ios/Pods-vlc-ios.distribution.xcconfig"; sourceTree = "<group>"; };
 		E0C04F931A25B4410080331A /* VLCDocumentPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCDocumentPickerController.h; path = Sources/VLCDocumentPickerController.h; sourceTree = SOURCE_ROOT; };
@@ -1786,10 +1790,12 @@
 			isa = PBXGroup;
 			children = (
 				DD02C2FC1ACACF400026EFEE /* VLC for iOS WatchKit Extension.entitlements */,
-				DDCA94771ACC12630044449A /* VLCDBChangeNotifier.h */,
-				DDCA94781ACC12630044449A /* VLCDBChangeNotifier.m */,
+				DDE4906A1ACDB63F00B1B5E3 /* VLCNotificationRelay.h */,
+				DDE4906B1ACDB63F00B1B5E3 /* VLCNotificationRelay.m */,
 				4173AEA41ABF1B850004101D /* InterfaceController.h */,
 				4173AEA51ABF1B850004101D /* InterfaceController.m */,
+				DD6FA7AE1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.h */,
+				DD6FA7AF1ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m */,
 				DD02C30C1ACAF4A50026EFEE /* VLCRowController.h */,
 				DD02C30D1ACAF4A50026EFEE /* VLCRowController.m */,
 				4173AEA71ABF1B850004101D /* Images.xcassets */,
@@ -3547,8 +3553,9 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				DD6FA7B01ACD641C006DEB2E /* VLCNowPlayingInterfaceController.m in Sources */,
 				DDF157B11ACB162700AAFBC6 /* MediaLibrary.xcdatamodeld in Sources */,
-				DDCA94791ACC12630044449A /* VLCDBChangeNotifier.m in Sources */,
+				DDE4906C1ACDB63F00B1B5E3 /* VLCNotificationRelay.m in Sources */,
 				DD02C30E1ACAF4A50026EFEE /* VLCRowController.m in Sources */,
 				4173AEA61ABF1B850004101D /* InterfaceController.m in Sources */,
 			);
@@ -3662,6 +3669,7 @@
 				7D30F3E2183AB33200FFC021 /* VLCSidebarViewCell.m in Sources */,
 				7D30F3EA183AB34200FFC021 /* VLCGoogleDriveController.m in Sources */,
 				9B088308183D7BEC004B5C2A /* VLCCloudStorageTableViewController.m in Sources */,
+				DDE4906D1ACDBEA000B1B5E3 /* VLCNotificationRelay.m in Sources */,
 				7D30F3EC183AB34200FFC021 /* VLCGoogleDriveTableViewController.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;