Commit 6ac9d0ba authored by Tobias's avatar Tobias

create WatchOS2 app and copy old app contents into new app

parent ab552890
Did you know that git does not support storing empty directories?
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "tableview-gradient.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "tableview-gradient@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
//
// ExtensionDelegate.swift
// watchkitapp Extension
//
// Created by Tobias Conradi on 28.07.15.
// Copyright © 2015 VideoLAN. All rights reserved.
//
import WatchKit
class ExtensionDelegate: NSObject, WKExtensionDelegate {
func applicationDidFinishLaunching() {
// Perform any final initialization of your application.
}
func applicationDidBecomeActive() {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillResignActive() {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, etc.
}
}
//
// InterfaceController.swift
// watchkitapp Extension
//
// Created by Tobias Conradi on 28.07.15.
// Copyright © 2015 VideoLAN. All rights reserved.
//
import WatchKit
import Foundation
class InterfaceController: WKInterfaceController {
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
// Configure interface objects here.
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
}
/*****************************************************************************
* NSManagedObjectContext+refreshAll.h
* VLC for iOS
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <CoreData/CoreData.h>
@interface NSManagedObjectContext (refreshAll)
// mergeChanges has same sematics as - (void)refreshObject:(NSManagedObject *)object mergeChanges:(BOOL)flag;
- (void)vlc_refreshAllObjectsMerge:(BOOL)mergeChanges;
@end
/*****************************************************************************
* NSManagedObjectContext+refreshAll.m
* VLC for iOS
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "NSManagedObjectContext+refreshAll.h"
@implementation NSManagedObjectContext (refreshAll)
- (void)vlc_refreshAllObjectsMerge:(BOOL)mergeChanges
{
for (NSManagedObject *object in self.registeredObjects) {
[self refreshObject:object mergeChanges:mergeChanges];
}
}
@end
/*****************************************************************************
* Prefix header for all source files of the 'VLC for iOS WK Ext' target
* 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 <Availability.h>
#ifndef __IPHONE_8_2
#error "This project uses features only available in iOS SDK 8.2 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
#import "VLCAudio.h"
#import "VLCLibrary.h"
#import "VLCMedia.h"
#import "VLCMediaDiscoverer.h"
#import "VLCMediaList.h"
#import "VLCMediaPlayer.h"
#import "VLCMediaListPlayer.h"
#import "VLCMediaThumbnailer.h"
#import "VLCTime.h"
#import "MLFile.h"
#import "MLLabel.h"
#import "MLMediaLibrary.h"
#import "MLShow.h"
#import "MLShowEpisode.h"
#import "MLAlbum.h"
#import "MLAlbumTrack.h"
#ifndef NDEBUG
#define APLog(format, ...) NSLog(format, ## __VA_ARGS__)
#else
#define APLog(format, ...)
#endif
/*****************************************************************************
* VLCBaseInterfaceController.h
* 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 <WatchKit/WatchKit.h>
@interface VLCBaseInterfaceController : WKInterfaceController
@property (nonatomic, assign, readonly, getter=isActivated) BOOL activated;
- (void)addNowPlayingMenu;
- (void)showNowPlaying:(id)sender;
// calls updataData if interface is currenlty active
// otherwise it sets a flag so update data when the interface is activated
- (void)setNeedsUpdateData;
// actual update logic should be overwritten by subclasses that needs an update logic
- (void)updateData;
@end
/*****************************************************************************
* VLCBaseInterfaceController.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 "VLCBaseInterfaceController.h"
static NSString *const VLCDBUpdateNotification = @"VLCUpdateDataBase";
@interface VLCBaseInterfaceController()
@property (nonatomic) BOOL needsUpdate;
@end
@implementation VLCBaseInterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setNeedsUpdateData) name:VLCDBUpdateNotification object:nil];
}
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:VLCDBUpdateNotification object:nil];
}
- (void)addNowPlayingMenu {
[self addMenuItemWithItemIcon:WKMenuItemIconMore title: NSLocalizedString(@"NOW_PLAYING", nil) action:@selector(showNowPlaying:)];
}
- (void)showNowPlaying:(id)sender {
[self presentControllerWithName:@"nowPlaying" context:nil];
}
- (void)willActivate {
[super willActivate];
_activated = YES;
[self updateDataIfNeeded];
}
- (void)didDeactivate {
[super didDeactivate];
_activated = NO;
}
- (void)setNeedsUpdateData
{
self.needsUpdate = YES;
[self updateDataIfNeeded];
}
- (void)updateDataIfNeeded
{
// if not activated/visible we defer the update til activation
if (self.needsUpdate && self.activated) {
[self updateData];
self.needsUpdate = NO;
}
}
- (void)updateData
{
self.needsUpdate = NO;
}
@end
/*****************************************************************************
* VLCDetailInterfaceController.h
* VLC for iOS
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#import "VLCBaseInterfaceController.h"
@interface VLCDetailInterfaceController : VLCBaseInterfaceController
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *titleLabel;
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *durationLabel;
@property (weak, nonatomic) IBOutlet WKInterfaceButton *playNowButton;
@property (weak, nonatomic) IBOutlet WKInterfaceGroup *group;
@property (weak, nonatomic) IBOutlet WKInterfaceObject *progressObject;
@property (copy, nonatomic) NSString *mediaTitle;
@property (copy, nonatomic) NSString *mediaDuration;
@property (nonatomic) CGFloat playbackProgress;
- (IBAction)playNow;
@end
/*****************************************************************************
* VLCDetailInterfaceController.m
* VLC for iOS
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "VLCDetailInterfaceController.h"
#import "VLCTime.h"
#import "VLCThumbnailsCache.h"
#import "WKInterfaceObject+VLCProgress.h"
#import "VLCWatchMessage.h"
@interface VLCDetailInterfaceController ()
@property (nonatomic, weak) NSManagedObject *managedObject;
@end
@implementation VLCDetailInterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
self.title = NSLocalizedString(@"DETAIL", nil);
self.playNowButton.accessibilityLabel = NSLocalizedString(@"PLAY_NOW", nil);
self.titleLabel.accessibilityLabel = NSLocalizedString(@"TITLE", nil);
self.durationLabel.accessibilityLabel = NSLocalizedString(@"DURATION", nil);
[self addNowPlayingMenu];
[self configureWithFile:context];
}
- (void)updateData {
[super updateData];
NSManagedObject *managedObject = self.managedObject;
[managedObject.managedObjectContext refreshObject:managedObject mergeChanges:NO];
[self configureWithFile:managedObject];
}
- (void)configureWithFile:(NSManagedObject *)managedObject {
self.managedObject = managedObject;
NSString *title = nil;
NSString *durationString = nil;
float playbackProgress = 0.0;
if ([managedObject isKindOfClass:[MLShowEpisode class]]) {
title = ((MLShowEpisode *)managedObject).name;
} else if ([managedObject isKindOfClass:[MLFile class]]) {
MLFile *file = (MLFile *)managedObject;
durationString = [VLCTime timeWithNumber:file.duration].stringValue;
playbackProgress = file.lastPosition.floatValue;
title = ((MLFile *)file).title;
} else if ([managedObject isKindOfClass:[MLAlbumTrack class]]) {
title = ((MLAlbumTrack *)managedObject).title;
} else {
NSAssert(NO, @"check what filetype we try to show here and add it above");
}
BOOL playEnabled = managedObject != nil;
self.playNowButton.enabled = playEnabled;
self.mediaTitle = title;
self.mediaDuration = durationString;
self.playbackProgress = playbackProgress;
/* do not block the main thread */
[self performSelectorInBackground:@selector(loadThumbnailForManagedObject:) withObject:managedObject];
}
- (void)loadThumbnailForManagedObject:(NSManagedObject *)managedObject
{
UIImage *thumbnail = [VLCThumbnailsCache thumbnailForManagedObject:managedObject];
if (thumbnail) {
[self.group performSelectorOnMainThread:@selector(setBackgroundImage:) withObject:thumbnail waitUntilDone:NO];
}
}
- (IBAction)playNow {
id payload = self.managedObject.objectID.URIRepresentation.absoluteString;
NSDictionary *dict = [VLCWatchMessage messageDictionaryForName:@"playFile"
payload:payload];
[self updateUserActivity:@"org.videolan.vlc-ios.playing" userInfo:@{@"playingmedia":self.managedObject.objectID.URIRepresentation} webpageURL:nil];
// TODO: toco
// [WKInterfaceController openParentApplication:dict reply:^(NSDictionary *replyInfo, NSError *error) {
// [self showNowPlaying:nil];
// }];
}
- (void)setMediaTitle:(NSString *)mediaTitle {
if (![_mediaTitle isEqualToString:mediaTitle]) {
_mediaTitle = [mediaTitle copy];
self.titleLabel.text = mediaTitle;
self.titleLabel.accessibilityValue = mediaTitle;
self.titleLabel.hidden = mediaTitle.length == 0;
}
}
- (void)setMediaDuration:(NSString *)mediaDuration {
if (![_mediaDuration isEqualToString:mediaDuration]) {
_mediaDuration = [mediaDuration copy];
self.durationLabel.text = mediaDuration;
self.durationLabel.hidden = mediaDuration.length == 0;
self.durationLabel.accessibilityValue = mediaDuration;
}
}
- (void)setPlaybackProgress:(CGFloat)playbackProgress {
if (_playbackProgress != playbackProgress) {
_playbackProgress = playbackProgress;
[self.progressObject vlc_setProgress:playbackProgress hideForNoProgress:YES];
}
}
@end
/*****************************************************************************
* VLCNotificationRelay.h
* 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 <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
/*****************************************************************************
* VLCNotificationRelay.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 "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);
self.remoteToLocal[remoteName] = localName;
}
- (void)removeRelayRemoteName:(NSString *)remoteName {
CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationCenterRemoveObserver(center, (__bridge const void *)(self), (__bridge CFStringRef)remoteName, NULL);
[self.remoteToLocal removeObjectForKey:remoteName];
}
#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];
/*
* in current version of iOS this is ignored for the darwin center
* nevertheless we use it to be future proof
*/
NSDictionary *dict = (__bridge NSDictionary *)userInfo;
[[NSNotificationCenter defaultCenter] postNotificationName:localName object:nil userInfo:dict];
}
@end
/*****************************************************************************
* VLCNowPlayingInterfaceController.h
* VLC for iOS
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
@interface VLCNowPlayingInterfaceController : WKInterfaceController
@property (weak, nonatomic) IBOutlet WKInterfaceGroup *playElementsGroup;
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *titleLabel;
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *durationLabel;
@property (weak, nonatomic) IBOutlet WKInterfaceButton *skipBackwardButton;
@property (weak, nonatomic) IBOutlet WKInterfaceButton *playPauseButton;
@property (weak, nonatomic) IBOutlet WKInterfaceGroup *playPauseButtonGroup;
@property (weak, nonatomic) IBOutlet WKInterfaceButton *skipForwardButton;
@property (weak, nonatomic) IBOutlet WKInterfaceObject *progressObject;
@property (weak, nonatomic) IBOutlet WKInterfaceSlider *volumeSlider;
- (IBAction)playPausePressed;
- (IBAction)skipForward;
- (IBAction)skipBackward;
- (IBAction)volumeSliderChanged:(float)value;
@end
/*****************************************************************************
* VLCNowPlayingInterfaceController.m
* VLC for iOS
*****************************************************************************
* Copyright (c) 2015 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Tobias Conradi <videolan # tobias-conradi.de>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
#import "VLCNowPlayingInterfaceController.h"
#import "VLCTime.h"
#import "VLCNotificationRelay.h"
#import "WKInterfaceObject+VLCProgress.h"
#import "VLCWatchMessage.h"
#import "VLCThumbnailsCache.h"
@interface VLCNowPlayingInterfaceController ()
{
CGRect _screenBounds;
CGFloat _screenScale;
}
@property (nonatomic, copy) NSString *titleString;
@property (nonatomic, copy) NSNumber *playBackDurationNumber;
@property (nonatomic, getter=isPlaying) BOOL playing;
@property (nonatomic) NSTimer *updateTimer;
@property (nonatomic, weak) MLFile *currentFile;
@property (nonatomic) float volume;
@end
@implementation VLCNowPlayingInterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
WKInterfaceDevice *currentDevice = [WKInterfaceDevice currentDevice];
_screenBounds = currentDevice.screenBounds;
_screenScale = currentDevice.screenScale;
[self setTitle:NSLocalizedString(@"PLAYING", nil)];
self.skipBackwardButton.accessibilityLabel = NSLocalizedString(@"BWD_BUTTON", nil);
self.skipForwardButton.accessibilityLabel = NSLocalizedString(@"FWD_BUTTON", nil);
self.volumeSlider.accessibilityLabel = NSLocalizedString(@"VOLUME", nil);
self.durationLabel.accessibilityLabel = NSLocalizedString(@"DURATION", nil);
self.titleLabel.accessibilityLabel = NSLocalizedString(@"TITLE", nil);
[self setPlaying:YES];
[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