<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>mediaListViewItemDoubleClicked</key>
+ <string>id</string>
+ <key>videoViewItemClicked</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>VLCMainWindowController</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>OUTLETS</key>
+ <dict>
+ <key>addPlaylistButton</key>
+ <string>NSButton</string>
+ <key>categoriesListView</key>
+ <string>NSOutlineView</string>
+ <key>categoriesTreeController</key>
+ <string>NSTreeController</string>
+ <key>controller</key>
+ <string>VLCController</string>
+ <key>mainSplitView</key>
+ <string>VLCOneSplitView</string>
+ <key>mediaArrayController</key>
+ <string>VLCMediaArrayController</string>
+ <key>mediaListView</key>
+ <string>NSTableView</string>
+ <key>mediaPlayer</key>
+ <string>VLCMediaPlayer</string>
+ <key>mediaPlayerBackwardPrevButton</key>
+ <string>NSButton</string>
+ <key>mediaPlayerForwardNextButton</key>
+ <string>NSButton</string>
+ <key>mediaPlayerPlayPauseStopButton</key>
+ <string>NSButton</string>
+ <key>removePlaylistButton</key>
+ <string>NSButton</string>
+ <key>toolbarMediaAudioVolume</key>
+ <string>NSView</string>
+ <key>toolbarMediaControl</key>
+ <string>NSView</string>
+ <key>toolbarMediaDescription</key>
+ <string>NSView</string>
+ <key>videoView</key>
+ <string>VLCBrowsableVideoView</string>
+ </dict>
+ <key>SUPERCLASS</key>
+ <string>NSWindowController</string>
+ </dict>
<dict>
<key>CLASS</key>
<string>FirstResponder</string>
<key>SUPERCLASS</key>
<string>NSObject</string>
</dict>
+ <dict>
+ <key>CLASS</key>
+ <string>VLCOneSplitView</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSSplitView</string>
+ </dict>
+ <dict>
+ <key>CLASS</key>
+ <string>VLCMediaArrayController</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>SUPERCLASS</key>
+ <string>NSArrayController</string>
+ </dict>
<dict>
<key>ACTIONS</key>
<dict>
<string>ObjC</string>
<key>OUTLETS</key>
<dict>
+ <key>mainWindowController</key>
+ <string>VLCMainWindowController</string>
<key>selectedObject</key>
<string>id</string>
<key>target</key>
<key>SUPERCLASS</key>
<string>NSView</string>
</dict>
+ <dict>
+ <key>CLASS</key>
+ <string>VLCMediaPlayer</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ </dict>
</array>
<key>IBVersion</key>
<string>1</string>
<dict>
<key>IBFramework Version</key>
<string>629</string>
- <key>IBLastKnownRelativeProjectPath</key>
- <string>../../VLC.xcodeproj</string>
<key>IBOldestOS</key>
<integer>5</integer>
<key>IBOpenObjects</key>
--- /dev/null
+/*****************************************************************************
+ * AppleRemote.h
+ * AppleRemote
+ * $Id: AppleRemote.h 22000 2007-09-13 19:12:49Z funman $
+ *
+ * Created by Martin Kahr on 11.03.06 under a MIT-style license.
+ * Copyright (c) 2006 martinkahr.com. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *****************************************************************************
+ *
+ * Note that changes made by any members or contributors of the VideoLAN team
+ * (i.e. changes that were checked in exclusively into one of VideoLAN's source code
+ * repositories) are licensed under the GNU General Public License version 2,
+ * or (at your option) any later version.
+ * Thus, the following statements apply to our changes:
+ *
+ * Copyright (C) 2006-2007 the VideoLAN team
+ * Authors: Eric Petit <titer@m0k.org>
+ * Felix Kühne <fkuehne at videolan dot org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+#import <mach/mach.h>
+#import <mach/mach_error.h>
+#import <IOKit/IOKitLib.h>
+#import <IOKit/IOCFPlugIn.h>
+#import <IOKit/hid/IOHIDLib.h>
+#import <IOKit/hid/IOHIDKeys.h>
+
+enum AppleRemoteEventIdentifier
+{
+ kRemoteButtonVolume_Plus =1<<1,
+ kRemoteButtonVolume_Minus =1<<2,
+ kRemoteButtonMenu =1<<3,
+ kRemoteButtonPlay =1<<4,
+ kRemoteButtonRight =1<<5,
+ kRemoteButtonLeft =1<<6,
+ kRemoteButtonRight_Hold =1<<7,
+ kRemoteButtonLeft_Hold =1<<8,
+ kRemoteButtonMenu_Hold =1<<9,
+ kRemoteButtonPlay_Sleep =1<<10,
+ kRemoteControl_Switched =1<<11,
+ kRemoteButtonVolume_Plus_Hold =1<<12,
+ kRemoteButtonVolume_Minus_Hold =1<<13
+};
+typedef enum AppleRemoteEventIdentifier AppleRemoteEventIdentifier;
+
+/* Encapsulates usage of the apple remote control
+This class is implemented as a singleton as there is exactly one remote per machine (until now)
+The class is not thread safe
+*/
+@interface AppleRemote : NSObject {
+ IOHIDDeviceInterface** hidDeviceInterface;
+ IOHIDQueueInterface** queue;
+ NSMutableArray* allCookies;
+ NSMutableDictionary* cookieToButtonMapping;
+
+ BOOL openInExclusiveMode;
+ BOOL simulatePlusMinusHold;
+ BOOL processesBacklog;
+
+ /* state for simulating plus/minus hold */
+ BOOL lastEventSimulatedHold;
+ AppleRemoteEventIdentifier lastPlusMinusEvent;
+ NSTimeInterval lastPlusMinusEventTime;
+
+ int remoteId;
+ unsigned int clickCountEnabledButtons;
+ NSTimeInterval maxClickTimeDifference;
+ NSTimeInterval lastClickCountEventTime;
+ AppleRemoteEventIdentifier lastClickCountEvent;
+ unsigned int eventClickCount;
+
+ IBOutlet id delegate;
+}
+
+- (int) remoteId;
+
+- (BOOL) isRemoteAvailable;
+
+- (BOOL) isListeningToRemote;
+- (void) setListeningToRemote: (BOOL) value;
+
+- (BOOL) isOpenInExclusiveMode;
+- (void) setOpenInExclusiveMode: (BOOL) value;
+
+/* click counting makes it possible to recognize if the user has pressed a button repeatedly
+ * click counting does delay each event as it has to wait if there is another event (second click)
+ * therefore there is a slight time difference (maximumClickCountTimeDifference) between a single click
+ * of the user and the call of your delegate method
+ * click counting can be enabled individually for specific buttons. Use the property clickCountEnableButtons
+ * to set the buttons for which click counting shall be enabled */
+- (BOOL) clickCountingEnabled;
+- (void) setClickCountingEnabled: (BOOL) value;
+
+- (unsigned int) clickCountEnabledButtons;
+- (void) setClickCountEnabledButtons: (unsigned int)value;
+
+/* the maximum time difference till which clicks are recognized as multi clicks */
+- (NSTimeInterval) maximumClickCountTimeDifference;
+- (void) setMaximumClickCountTimeDifference: (NSTimeInterval) timeDiff;
+
+/* When your application needs to much time on the main thread when processing an event other events
+ * may already be received which are put on a backlog. As soon as your main thread
+ * has some spare time this backlog is processed and may flood your delegate with calls.
+ * Backlog processing is turned off by default. */
+- (BOOL) processesBacklog;
+- (void) setProcessesBacklog: (BOOL) value;
+
+/* Sets an NSApplication delegate which starts listening when application is becoming active
+ * and stops listening when application resigns being active.
+ * If an NSApplication delegate has been already set all method calls will be forwarded to this delegate, too. */
+- (BOOL) listeningOnAppActivate;
+- (void) setListeningOnAppActivate: (BOOL) value;
+
+/* Simulating plus/minus hold does deactivate sending of individual requests for plus/minus pressed down/released.
+ * Instead special hold events are being triggered when the user is pressing and holding plus/minus for a small period.
+ * With simulating enabled the plus/minus buttons do behave as the left/right buttons */
+- (BOOL) simulatesPlusMinusHold;
+- (void) setSimulatesPlusMinusHold: (BOOL) value;
+
+/* Delegates are not retained */
+- (void) setDelegate: (id) delegate;
+- (id) delegate;
+
+- (IBAction) startListening: (id) sender;
+- (IBAction) stopListening: (id) sender;
+@end
+
+@interface AppleRemote (Singleton)
+
++ (AppleRemote*) sharedRemote;
+
+@end
+
+/* Method definitions for the delegate of the AppleRemote class */
+@interface NSObject(NSAppleRemoteDelegate)
+
+- (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier pressedDown: (BOOL) pressedDown clickCount: (unsigned int) count;
+
+@end
+
+@interface AppleRemote (PrivateMethods)
+- (void) setRemoteId: (int) aValue;
+- (NSDictionary*) cookieToButtonMapping;
+- (IOHIDQueueInterface**) queue;
+- (IOHIDDeviceInterface**) hidDeviceInterface;
+- (void) handleEventWithCookieString: (NSString*) cookieString sumOfValues: (SInt32) sumOfValues;
+@end
+
+@interface AppleRemote (IOKitMethods)
+- (io_object_t) findAppleRemoteDevice;
+- (IOHIDDeviceInterface**) createInterfaceForDevice: (io_object_t) hidDevice;
+- (BOOL) initializeCookies;
+- (BOOL) openDevice;
+@end
+
+/* A NSApplication delegate which is used to activate and deactivate listening to the remote control
+ * dependent on the activation state of your application.
+ * All events are delegated to the original NSApplication delegate if necessary */
+@interface AppleRemoteApplicationDelegate : NSObject {
+ id applicationDelegate;
+}
+
+- (id) initWithApplicationDelegate: (id) delegate;
+- (id) applicationDelegate;
+@end
--- /dev/null
+/*****************************************************************************
+ * AppleRemote.m
+ * AppleRemote
+ * $Id: AppleRemote.m 23523 2007-12-10 00:35:23Z fkuehne $
+ *
+ * Created by Martin Kahr on 11.03.06 under a MIT-style license.
+ * Copyright (c) 2006 martinkahr.com. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *****************************************************************************
+ *
+ * Note that changes made by any members or contributors of the VideoLAN team
+ * (i.e. changes that were exclusively checked in to one of VideoLAN's source code
+ * repositories) are licensed under the GNU General Public License version 2,
+ * or (at your option) any later version.
+ * Thus, the following statements apply to our changes:
+ *
+ * Copyright (C) 2006-2007 the VideoLAN team
+ * Authors: Eric Petit <titer@m0k.org>
+ * Felix Kühne <fkuehne at videolan dot org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "AppleRemote.h"
+
+#define MACOS_VERSION [[[NSDictionary dictionaryWithContentsOfFile: \
+ @"/System/Library/CoreServices/SystemVersion.plist"] \
+ objectForKey: @"ProductVersion"] floatValue]
+
+const char* AppleRemoteDeviceName = "AppleIRController";
+const int REMOTE_SWITCH_COOKIE=19;
+const NSTimeInterval DEFAULT_MAXIMUM_CLICK_TIME_DIFFERENCE=0.35;
+const NSTimeInterval HOLD_RECOGNITION_TIME_INTERVAL=0.4;
+
+@implementation AppleRemote
+
+#pragma public interface
+
+- (id) init {
+ if ( self = [super init] ) {
+ openInExclusiveMode = YES;
+ queue = NULL;
+ hidDeviceInterface = NULL;
+ cookieToButtonMapping = [[NSMutableDictionary alloc] init];
+
+ if( MACOS_VERSION < 10.5f )
+ {
+ /* use the traditional cookies for Tiger (and Panther, if it is supported by the frame app) */
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonVolume_Plus] forKey:@"14_12_11_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonVolume_Minus] forKey:@"14_13_11_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu] forKey:@"14_7_6_14_7_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay] forKey:@"14_8_6_14_8_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight] forKey:@"14_9_6_14_9_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft] forKey:@"14_10_6_14_10_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight_Hold] forKey:@"14_6_4_2_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft_Hold] forKey:@"14_6_3_2_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu_Hold] forKey:@"14_6_14_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay_Sleep] forKey:@"18_14_6_18_14_6_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteControl_Switched] forKey:@"19_"];
+ }
+ else
+ {
+ /* we're on Leopard and need to use a new set of cookies */
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonVolume_Plus] forKey:@"31_29_28_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonVolume_Minus] forKey:@"31_30_28_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu] forKey:@"31_20_18_31_20_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay] forKey:@"31_21_18_31_21_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight] forKey:@"31_22_18_31_22_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft] forKey:@"31_23_18_31_23_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonRight_Hold] forKey:@"31_18_4_2_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonLeft_Hold] forKey:@"31_18_3_2_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonMenu_Hold] forKey:@"31_18_31_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteButtonPlay_Sleep] forKey:@"35_31_18_35_31_18_"];
+ [cookieToButtonMapping setObject:[NSNumber numberWithInt:kRemoteControl_Switched] forKey:@"19_"];
+ }
+
+ /* defaults */
+ [self setSimulatesPlusMinusHold: YES];
+ maxClickTimeDifference = DEFAULT_MAXIMUM_CLICK_TIME_DIFFERENCE;
+ }
+
+ return self;
+}
+
+- (void) dealloc {
+ [self stopListening:self];
+ [cookieToButtonMapping release];
+ [super dealloc];
+}
+
+- (int) remoteId {
+ return remoteId;
+}
+
+- (BOOL) isRemoteAvailable {
+ io_object_t hidDevice = [self findAppleRemoteDevice];
+ if (hidDevice != 0) {
+ IOObjectRelease(hidDevice);
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
+- (BOOL) isListeningToRemote {
+ return (hidDeviceInterface != NULL && allCookies != NULL && queue != NULL);
+}
+
+- (void) setListeningToRemote: (BOOL) value {
+ if (value == NO) {
+ [self stopListening:self];
+ } else {
+ [self startListening:self];
+ }
+}
+
+/* Delegates are not retained!
+ * http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CommunicatingWithObjects/chapter_6_section_4.html
+ * Delegating objects do not (and should not) retain their delegates.
+ * However, clients of delegating objects (applications, usually) are responsible for ensuring that their delegates are around
+ * to receive delegation messages. To do this, they may have to retain the delegate. */
+- (void) setDelegate: (id) _delegate {
+ if (_delegate && [_delegate respondsToSelector:@selector(appleRemoteButton:pressedDown:clickCount:)]==NO) return;
+
+ delegate = _delegate;
+}
+- (id) delegate {
+ return delegate;
+}
+
+- (BOOL) isOpenInExclusiveMode {
+ return openInExclusiveMode;
+}
+- (void) setOpenInExclusiveMode: (BOOL) value {
+ openInExclusiveMode = value;
+}
+
+- (BOOL) clickCountingEnabled {
+ return clickCountEnabledButtons != 0;
+}
+- (void) setClickCountingEnabled: (BOOL) value {
+ if (value) {
+ [self setClickCountEnabledButtons: kRemoteButtonVolume_Plus | kRemoteButtonVolume_Minus | kRemoteButtonPlay | kRemoteButtonLeft | kRemoteButtonRight | kRemoteButtonMenu];
+ } else {
+ [self setClickCountEnabledButtons: 0];
+ }
+}
+
+- (unsigned int) clickCountEnabledButtons {
+ return clickCountEnabledButtons;
+}
+- (void) setClickCountEnabledButtons: (unsigned int)value {
+ clickCountEnabledButtons = value;
+}
+
+- (NSTimeInterval) maximumClickCountTimeDifference {
+ return maxClickTimeDifference;
+}
+- (void) setMaximumClickCountTimeDifference: (NSTimeInterval) timeDiff {
+ maxClickTimeDifference = timeDiff;
+}
+
+- (BOOL) processesBacklog {
+ return processesBacklog;
+}
+- (void) setProcessesBacklog: (BOOL) value {
+ processesBacklog = value;
+}
+
+- (BOOL) listeningOnAppActivate {
+ id appDelegate = [NSApp delegate];
+ return (appDelegate!=nil && [appDelegate isKindOfClass: [AppleRemoteApplicationDelegate class]]);
+}
+- (void) setListeningOnAppActivate: (BOOL) value {
+ if (value) {
+ if ([self listeningOnAppActivate]) return;
+ AppleRemoteApplicationDelegate* appDelegate = [[AppleRemoteApplicationDelegate alloc] initWithApplicationDelegate: [NSApp delegate]];
+ /* NSApp does not retain its delegate therefore we keep retain count on 1 */
+ [NSApp setDelegate: appDelegate];
+ } else {
+ if ([self listeningOnAppActivate]==NO) return;
+ AppleRemoteApplicationDelegate* appDelegate = (AppleRemoteApplicationDelegate*)[NSApp delegate];
+ id previousAppDelegate = [appDelegate applicationDelegate];
+ [NSApp setDelegate: previousAppDelegate];
+ [appDelegate release];
+ }
+}
+
+- (BOOL) simulatesPlusMinusHold {
+ return simulatePlusMinusHold;
+}
+- (void) setSimulatesPlusMinusHold: (BOOL) value {
+ simulatePlusMinusHold = value;
+}
+
+- (IBAction) startListening: (id) sender {
+ if ([self isListeningToRemote]) return;
+
+ io_object_t hidDevice = [self findAppleRemoteDevice];
+ if (hidDevice == 0) return;
+
+ if ([self createInterfaceForDevice:hidDevice] == NULL) {
+ goto error;
+ }
+
+ if ([self initializeCookies]==NO) {
+ goto error;
+ }
+
+ if ([self openDevice]==NO) {
+ goto error;
+ }
+ goto cleanup;
+
+error:
+ [self stopListening:self];
+
+cleanup:
+ IOObjectRelease(hidDevice);
+}
+
+- (IBAction) stopListening: (id) sender {
+ if (queue != NULL) {
+ (*queue)->stop(queue);
+
+ //dispose of queue
+ (*queue)->dispose(queue);
+
+ //release the queue we allocated
+ (*queue)->Release(queue);
+
+ queue = NULL;
+ }
+
+ if (allCookies != nil) {
+ [allCookies autorelease];
+ allCookies = nil;
+ }
+
+ if (hidDeviceInterface != NULL) {
+ //close the device
+ (*hidDeviceInterface)->close(hidDeviceInterface);
+
+ //release the interface
+ (*hidDeviceInterface)->Release(hidDeviceInterface);
+
+ hidDeviceInterface = NULL;
+ }
+}
+
+@end
+
+@implementation AppleRemote (Singleton)
+
+static AppleRemote* sharedInstance=nil;
+
++ (AppleRemote*) sharedRemote {
+ @synchronized(self) {
+ if (sharedInstance == nil) {
+ sharedInstance = [[self alloc] init];
+ }
+ }
+ return sharedInstance;
+}
++ (id)allocWithZone:(NSZone *)zone {
+ @synchronized(self) {
+ if (sharedInstance == nil) {
+ return [super allocWithZone:zone];
+ }
+ }
+ return sharedInstance;
+}
+- (id)copyWithZone:(NSZone *)zone {
+ return self;
+}
+- (id)retain {
+ return self;
+}
+- (unsigned)retainCount {
+ return UINT_MAX; //denotes an object that cannot be released
+}
+- (void)release {
+ //do nothing
+}
+- (id)autorelease {
+ return self;
+}
+
+@end
+
+@implementation AppleRemote (PrivateMethods)
+
+- (void) setRemoteId: (int) value {
+ remoteId = value;
+}
+
+- (IOHIDQueueInterface**) queue {
+ return queue;
+}
+
+- (IOHIDDeviceInterface**) hidDeviceInterface {
+ return hidDeviceInterface;
+}
+
+
+- (NSDictionary*) cookieToButtonMapping {
+ return cookieToButtonMapping;
+}
+
+- (NSString*) validCookieSubstring: (NSString*) cookieString {
+ if (cookieString == nil || [cookieString length] == 0) return nil;
+ NSEnumerator* keyEnum = [[self cookieToButtonMapping] keyEnumerator];
+ NSString* key;
+ while(key = [keyEnum nextObject]) {
+ NSRange range = [cookieString rangeOfString:key];
+ if (range.location == 0) return key;
+ }
+ return nil;
+}
+
+- (void) sendSimulatedPlusMinusEvent: (id) time {
+ BOOL startSimulateHold = NO;
+ AppleRemoteEventIdentifier event = lastPlusMinusEvent;
+ @synchronized(self) {
+ startSimulateHold = (lastPlusMinusEvent>0 && lastPlusMinusEventTime == [time doubleValue]);
+ }
+ if (startSimulateHold) {
+ lastEventSimulatedHold = YES;
+ event = (event==kRemoteButtonVolume_Plus) ? kRemoteButtonVolume_Plus_Hold : kRemoteButtonVolume_Minus_Hold;
+ [delegate appleRemoteButton:event pressedDown: YES clickCount: 1];
+ }
+}
+
+- (void) sendRemoteButtonEvent: (AppleRemoteEventIdentifier) event pressedDown: (BOOL) pressedDown {
+ if (delegate) {
+ if (simulatePlusMinusHold) {
+ if (event == kRemoteButtonVolume_Plus || event == kRemoteButtonVolume_Minus) {
+ if (pressedDown) {
+ lastPlusMinusEvent = event;
+ lastPlusMinusEventTime = [NSDate timeIntervalSinceReferenceDate];
+ [self performSelector:@selector(sendSimulatedPlusMinusEvent:)
+ withObject:[NSNumber numberWithDouble:lastPlusMinusEventTime]
+ afterDelay:HOLD_RECOGNITION_TIME_INTERVAL];
+ return;
+ } else {
+ if (lastEventSimulatedHold) {
+ event = (event==kRemoteButtonVolume_Plus) ? kRemoteButtonVolume_Plus_Hold : kRemoteButtonVolume_Minus_Hold;
+ lastPlusMinusEvent = 0;
+ lastEventSimulatedHold = NO;
+ } else {
+ @synchronized(self) {
+ lastPlusMinusEvent = 0;
+ }
+ pressedDown = YES;
+ }
+ }
+ }
+ }
+
+ if (([self clickCountEnabledButtons] & event) == event) {
+ if (pressedDown==NO && (event == kRemoteButtonVolume_Minus || event == kRemoteButtonVolume_Plus)) {
+ return; // this one is triggered automatically by the handler
+ }
+ NSNumber* eventNumber;
+ NSNumber* timeNumber;
+ @synchronized(self) {
+ lastClickCountEventTime = [NSDate timeIntervalSinceReferenceDate];
+ if (lastClickCountEvent == event) {
+ eventClickCount = eventClickCount + 1;
+ } else {
+ eventClickCount = 1;
+ }
+ lastClickCountEvent = event;
+ timeNumber = [NSNumber numberWithDouble:lastClickCountEventTime];
+ eventNumber= [NSNumber numberWithUnsignedInt:event];
+ }
+ [self performSelector: @selector(executeClickCountEvent:)
+ withObject: [NSArray arrayWithObjects:eventNumber, timeNumber, nil]
+ afterDelay: maxClickTimeDifference];
+ } else {
+ [delegate appleRemoteButton:event pressedDown: pressedDown clickCount:1];
+ }
+ }
+}
+
+- (void) executeClickCountEvent: (NSArray*) values {
+ AppleRemoteEventIdentifier event = [[values objectAtIndex: 0] unsignedIntValue];
+ NSTimeInterval eventTimePoint = [[values objectAtIndex: 1] doubleValue];
+
+ BOOL finishedClicking = NO;
+ int finalClickCount = eventClickCount;
+
+ @synchronized(self) {
+ finishedClicking = (event != lastClickCountEvent || eventTimePoint == lastClickCountEventTime);
+ if (finishedClicking) eventClickCount = 0;
+ }
+
+ if (finishedClicking) {
+ [delegate appleRemoteButton:event pressedDown: YES clickCount:finalClickCount];
+ if ([self simulatesPlusMinusHold]==NO && (event == kRemoteButtonVolume_Minus || event == kRemoteButtonVolume_Plus)) {
+ // trigger a button release event, too
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow:0.1]];
+ [delegate appleRemoteButton:event pressedDown: NO clickCount:finalClickCount];
+ }
+ }
+
+}
+
+- (void) handleEventWithCookieString: (NSString*) cookieString sumOfValues: (SInt32) sumOfValues {
+ /*
+ if (previousRemainingCookieString) {
+ cookieString = [previousRemainingCookieString stringByAppendingString: cookieString];
+ NSLog(@"New cookie string is %@", cookieString);
+ [previousRemainingCookieString release], previousRemainingCookieString=nil;
+ }*/
+ if (cookieString == nil || [cookieString length] == 0) return;
+ NSNumber* buttonId = [[self cookieToButtonMapping] objectForKey: cookieString];
+ if (buttonId != nil) {
+ [self sendRemoteButtonEvent: [buttonId intValue] pressedDown: (sumOfValues>0)];
+ } else {
+ // let's see if a number of events are stored in the cookie string. this does
+ // happen when the main thread is too busy to handle all incoming events in time.
+ NSString* subCookieString;
+ NSString* lastSubCookieString=nil;
+ while(subCookieString = [self validCookieSubstring: cookieString]) {
+ cookieString = [cookieString substringFromIndex: [subCookieString length]];
+ lastSubCookieString = subCookieString;
+ if (processesBacklog) [self handleEventWithCookieString: subCookieString sumOfValues:sumOfValues];
+ }
+ if (processesBacklog == NO && lastSubCookieString != nil) {
+ // process the last event of the backlog and assume that the button is not pressed down any longer.
+ // The events in the backlog do not seem to be in order and therefore (in rare cases) the last event might be
+ // a button pressed down event while in reality the user has released it.
+ // NSLog(@"processing last event of backlog");
+ [self handleEventWithCookieString: lastSubCookieString sumOfValues:0];
+ }
+ if ([cookieString length] > 0) {
+ NSLog(@"Unknown button for cookiestring %@", cookieString);
+ }
+ }
+}
+
+@end
+
+/* Callback method for the device queue
+Will be called for any event of any type (cookie) to which we subscribe
+*/
+static void QueueCallbackFunction(void* target, IOReturn result, void* refcon, void* sender) {
+ AppleRemote* remote = (AppleRemote*)target;
+
+ IOHIDEventStruct event;
+ AbsoluteTime zeroTime = {0,0};
+ NSMutableString* cookieString = [NSMutableString string];
+ SInt32 sumOfValues = 0;
+ while (result == kIOReturnSuccess)
+ {
+ result = (*[remote queue])->getNextEvent([remote queue], &event, zeroTime, 0);
+ if ( result != kIOReturnSuccess )
+ continue;
+
+ //printf("%d %d %d\n", event.elementCookie, event.value, event.longValue);
+
+ if (REMOTE_SWITCH_COOKIE == (int)event.elementCookie) {
+ [remote setRemoteId: event.value];
+ [remote handleEventWithCookieString: @"19_" sumOfValues: 0];
+ } else {
+ if (((int)event.elementCookie)!=5) {
+ sumOfValues+=event.value;
+ [cookieString appendString:[NSString stringWithFormat:@"%d_", event.elementCookie]];
+ }
+ }
+ }
+
+ [remote handleEventWithCookieString: cookieString sumOfValues: sumOfValues];
+}
+
+@implementation AppleRemote (IOKitMethods)
+
+- (IOHIDDeviceInterface**) createInterfaceForDevice: (io_object_t) hidDevice {
+ io_name_t className;
+ IOCFPlugInInterface** plugInInterface = NULL;
+ HRESULT plugInResult = S_OK;
+ SInt32 score = 0;
+ IOReturn ioReturnValue = kIOReturnSuccess;
+
+ hidDeviceInterface = NULL;
+
+ ioReturnValue = IOObjectGetClass(hidDevice, className);
+
+ if (ioReturnValue != kIOReturnSuccess) {
+ NSLog(@"Error: Failed to get class name.");
+ return NULL;
+ }
+
+ ioReturnValue = IOCreatePlugInInterfaceForService(hidDevice,
+ kIOHIDDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugInInterface,
+ &score);
+ if (ioReturnValue == kIOReturnSuccess)
+ {
+ //Call a method of the intermediate plug-in to create the device interface
+ plugInResult = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID) &hidDeviceInterface);
+
+ if (plugInResult != S_OK) {
+ NSLog(@"Error: Couldn't create HID class device interface");
+ }
+ // Release
+ if (plugInInterface) (*plugInInterface)->Release(plugInInterface);
+ }
+ return hidDeviceInterface;
+}
+
+- (io_object_t) findAppleRemoteDevice {
+ CFMutableDictionaryRef hidMatchDictionary = NULL;
+ IOReturn ioReturnValue = kIOReturnSuccess;
+ io_iterator_t hidObjectIterator = 0;
+ io_object_t hidDevice = 0;
+
+ // Set up a matching dictionary to search the I/O Registry by class
+ // name for all HID class devices
+ hidMatchDictionary = IOServiceMatching(AppleRemoteDeviceName);
+
+ // Now search I/O Registry for matching devices.
+ ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, hidMatchDictionary, &hidObjectIterator);
+
+ if ((ioReturnValue == kIOReturnSuccess) && (hidObjectIterator != 0)) {
+ hidDevice = IOIteratorNext(hidObjectIterator);
+ }
+
+ // release the iterator
+ IOObjectRelease(hidObjectIterator);
+
+ return hidDevice;
+}
+
+- (BOOL) initializeCookies {
+ IOHIDDeviceInterface122** handle = (IOHIDDeviceInterface122**)hidDeviceInterface;
+ IOHIDElementCookie cookie;
+ long usage;
+ long usagePage;
+ id object;
+ NSArray* elements = nil;
+ NSDictionary* element;
+ IOReturn success;
+
+ if (!handle || !(*handle)) return NO;
+
+ /* Copy all elements, since we're grabbing most of the elements
+ * for this device anyway, and thus, it's faster to iterate them
+ * ourselves. When grabbing only one or two elements, a matching
+ * dictionary should be passed in here instead of NULL. */
+ success = (*handle)->copyMatchingElements(handle, NULL, (CFArrayRef*)&elements);
+
+ if (success == kIOReturnSuccess) {
+
+ [elements autorelease];
+ /*
+ cookies = calloc(NUMBER_OF_APPLE_REMOTE_ACTIONS, sizeof(IOHIDElementCookie));
+ memset(cookies, 0, sizeof(IOHIDElementCookie) * NUMBER_OF_APPLE_REMOTE_ACTIONS);
+ */
+ allCookies = [[NSMutableArray alloc] init];
+ int i;
+ for (i=0; i< [elements count]; i++) {
+ element = [elements objectAtIndex:i];
+
+ //Get cookie
+ object = [element valueForKey: (NSString*)CFSTR(kIOHIDElementCookieKey) ];
+ if (object == nil || ![object isKindOfClass:[NSNumber class]]) continue;
+ if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue;
+ cookie = (IOHIDElementCookie) [object longValue];
+
+ //Get usage
+ object = [element valueForKey: (NSString*)CFSTR(kIOHIDElementUsageKey) ];
+ if (object == nil || ![object isKindOfClass:[NSNumber class]]) continue;
+ usage = [object longValue];
+
+ //Get usage page
+ object = [element valueForKey: (NSString*)CFSTR(kIOHIDElementUsagePageKey) ];
+ if (object == nil || ![object isKindOfClass:[NSNumber class]]) continue;
+ usagePage = [object longValue];
+
+ [allCookies addObject: [NSNumber numberWithInt:(int)cookie]];
+ }
+ } else {
+ return NO;
+ }
+
+ return YES;
+}
+
+- (BOOL) openDevice {
+ HRESULT result;
+
+ IOHIDOptionsType openMode = kIOHIDOptionsTypeNone;
+ if ([self isOpenInExclusiveMode]) openMode = kIOHIDOptionsTypeSeizeDevice;
+ IOReturn ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, openMode);
+
+ if (ioReturnValue == KERN_SUCCESS) {
+ queue = (*hidDeviceInterface)->allocQueue(hidDeviceInterface);
+ if (queue) {
+ result = (*queue)->create(queue, 0, 12); //depth: maximum number of elements in queue before oldest elements in queue begin to be lost.
+
+ int i=0;
+ for(i=0; i<[allCookies count]; i++) {
+ IOHIDElementCookie cookie = (IOHIDElementCookie)[[allCookies objectAtIndex:i] intValue];
+ (*queue)->addElement(queue, cookie, 0);
+ }
+
+ // add callback for async events
+ CFRunLoopSourceRef eventSource;
+ ioReturnValue = (*queue)->createAsyncEventSource(queue, &eventSource);
+ if (ioReturnValue == KERN_SUCCESS) {
+ ioReturnValue = (*queue)->setEventCallout(queue,QueueCallbackFunction, self, NULL);
+ if (ioReturnValue == KERN_SUCCESS) {
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode);
+ //start data delivery to queue
+ (*queue)->start(queue);
+ return YES;
+ } else {
+ NSLog(@"Error when setting event callout");
+ }
+ } else {
+ NSLog(@"Error when creating async event source");
+ }
+ } else {
+ NSLog(@"Error when opening device");
+ }
+ }
+ return NO;
+}
+
+@end
+
+@implementation AppleRemoteApplicationDelegate
+
+- (id) initWithApplicationDelegate: (id) delegate {
+ if (self = [super init]) {
+ applicationDelegate = [delegate retain];
+ }
+ return self;
+}
+
+- (void) dealloc {
+ [applicationDelegate release];
+ [super dealloc];
+}
+
+- (id) applicationDelegate {
+ return applicationDelegate;
+}
+
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification {
+ if ([applicationDelegate respondsToSelector: @selector(applicationWillBecomeActive:)]) {
+ [applicationDelegate applicationWillBecomeActive: aNotification];
+ }
+}
+- (void)applicationDidBecomeActive:(NSNotification *)aNotification {
+ [[AppleRemote sharedRemote] setListeningToRemote: YES];
+
+ if ([applicationDelegate respondsToSelector: @selector(applicationDidBecomeActive:)]) {
+ [applicationDelegate applicationDidBecomeActive: aNotification];
+ }
+}
+- (void)applicationWillResignActive:(NSNotification *)aNotification {
+ [[AppleRemote sharedRemote] setListeningToRemote: NO];
+
+ if ([applicationDelegate respondsToSelector: @selector(applicationWillResignActive:)]) {
+ [applicationDelegate applicationWillResignActive: aNotification];
+ }
+}
+- (void)applicationDidResignActive:(NSNotification *)aNotification {
+ if ([applicationDelegate respondsToSelector: @selector(applicationDidResignActive:)]) {
+ [applicationDelegate applicationDidResignActive: aNotification];
+ }
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
+ NSMethodSignature* signature = [super methodSignatureForSelector: aSelector];
+ if (signature == nil && applicationDelegate != nil) {
+ signature = [applicationDelegate methodSignatureForSelector: aSelector];
+ }
+ return signature;
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation {
+ SEL aSelector = [invocation selector];
+
+ if (applicationDelegate==nil || [applicationDelegate respondsToSelector:aSelector]==NO) {
+ [super forwardInvocation: invocation];
+ return;
+ }
+
+ [invocation invokeWithTarget:applicationDelegate];
+}
+@end
*****************************************************************************/
@interface VLCOneSplitView : NSSplitView
{
- BOOL fixedCursorDuringResize;
}
-@property (assign) BOOL fixedCursorDuringResize;
- (float)sliderPosition;
- (void)setSliderPosition:(float)newPosition;
@end
@interface NSImageView (VLCAppAdditions)
- (BOOL)mouseDownCanMoveWindow;
@end
+
+/*****************************************************************************
+ * NSImage (VLCAppAdditions)
+ *
+ * Make the image view move the window by mouse down by default
+ *****************************************************************************/
+
+@interface NSImage (VLCAppAdditions)
+- (CGImageRef)CGImage;
+@end
/* Split view that supports slider animation */
@implementation VLCOneSplitView
-@synthesize fixedCursorDuringResize;
+- (CGFloat)dividerThickness
+{
+ return 1.;
+}
+- (void)drawDividerInRect:(NSRect)aRect
+{
+ [self lockFocus];
+ [[NSColor blackColor] set];
+ NSRectFill(aRect);
+ [self unlockFocus];
+}
- (float)sliderPosition
{
- return [[[self subviews] objectAtIndex:0] frame].size.height;
+ NSSize size = [[[self subviews] objectAtIndex:0] frame].size;
+ return [self isVertical] ? size.width : size.height;
}
- (void)setSliderPosition:(float)newPosition
{
}
return [super defaultAnimationForKey: key];
}
-- (void)adjustSubviews
-{
- if( !fixedCursorDuringResize )
- {
- [super adjustSubviews];
- return;
- }
- NSRect frame0 = [[[self subviews] objectAtIndex:0] frame];
- NSRect frame1 = [[[self subviews] objectAtIndex:1] frame];
- frame1.size.height = [self bounds].size.height - frame0.size.height - [self dividerThickness];
- if( frame1.size.height < 0. )
- {
- float delta = -frame1.size.height;
- frame1.size.height = 0.;
- frame0.size.height -= delta;
- frame1.origin.y = frame0.size.height + [self dividerThickness];
- [[[self subviews] objectAtIndex:1] setFrame: frame0];
- }
- [[[self subviews] objectAtIndex:1] setFrame: frame1];
-}
@end
/*****************************************************************************
}
@end
+/*****************************************************************************
+ * NSImage (VLCAppAdditions)
+ *
+ * Make the image view move the window by mouse down by default
+ *****************************************************************************/
+
+@implementation NSImage (VLCAppAdditions)
+- (CGImageRef)CGImage
+{
+ return [[NSBitmapImageRep imageRepWithData:[NSBitmapImageRep TIFFRepresentationOfImageRepsInArray: [self representations]]] CGImage];
+}
+@end
+
+
#import <VLCKit/VLCKit.h>
#import "VLCAppAdditions.h"
-@interface VLCBrowsableVideoView : VLCVideoView {
+@class VLCMainWindowController;
+@class VLCMediaListLayer;
+
+@interface VLCBrowsableVideoView : NSView {
BOOL menuDisplayed;
NSArray * itemsTree;
NSRange displayedItems;
NSViewAnimation * fullScreenAnim1;
NSViewAnimation * fullScreenAnim2;
NSView * tempFullScreenView;
+ IBOutlet VLCMainWindowController * mainWindowController;
+ VLCVideoLayer * videoLayer;
+ VLCMediaListLayer * mediaListLayer;
}
/* Binds an nsarray to that property. But don't forget the set the access keys. */
@property (readonly, retain) id selectedObject;
@property (readwrite) BOOL fullScreen;
+@property (readonly) BOOL hasVideo;
+
+@property (readonly) VLCVideoLayer * videoLayer;
/* Set up a specific action to do, on items that don't have node.
* action first argument is the browsableVideoView. You can get the selected object,
- (void)toggleMenu;
- (void)displayMenu;
- (void)hideMenu;
+
+- (IBAction)backToMediaListView:(id)sender;
@end
#import "VLCBrowsableVideoView.h"
#import "VLCAppAdditions.h"
+#import "VLCMediaListLayer.h"
+#import "VLCMainWindowController.h"
/* TODO: We may want to clean up the private functions a bit... */
@end
+#pragma mark -
/******************************************************************************
* VLCBrowsableVideoView
*/
@synthesize selectedObject;
@synthesize target;
@synthesize action;
+@synthesize videoLayer;
- (NSArray *)itemsTree {
return itemsTree;
}
}
+- (BOOL)hasVideo
+{
+ return videoLayer.hasVideo;
+}
+
+/* Binded to VideoLayer's hasVideo */
+- (void)setHasVideo:(BOOL)hasVideo
+{
+ if( hasVideo )
+ {
+ [CATransaction begin];
+ [videoLayer removeFromSuperlayer];
+ [self.layer addSublayer:videoLayer];
+ videoLayer.frame = [self layer].bounds;
+ [videoLayer setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
+ [mediaListLayer removeFromSuperlayer];
+ [CATransaction commit];
+ }
+ else
+ {
+ [CATransaction begin];
+ [mediaListLayer removeFromSuperlayer];
+ [self.layer addSublayer:mediaListLayer];
+ mediaListLayer.frame = [self layer].bounds;
+ [mediaListLayer setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
+ [videoLayer removeFromSuperlayer];
+ [CATransaction commit];
+
+ }
+ [[self layer] setNeedsDisplay];
+ [self setNeedsDisplay:YES];
+}
+
/* Initializer */
- (void)awakeFromNib
{
selectedPath = [[NSIndexPath alloc] init];
tempFullScreenView = [[NSView alloc] init];
fullScreen = NO;
- /* Observe our bindings */
- //[self displayMenu];
- //[self changeSelectedIndex:0];
+
+ videoLayer = [[VLCVideoLayer layer] retain];
+ [videoLayer addObserver:self forKeyPath:@"hasVideo" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
+
+ [videoLayer setDelegate:self];
+ NSAssert( mainWindowController, @"No mainWindowController" );
+ [mainWindowController.mediaPlayer setVideoLayer: videoLayer];
+ mediaListLayer = [[VLCMediaListLayer layerWithMediaArrayController:mainWindowController.mediaArrayController] retain];
+ [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, @"VLCMediaURLType", nil]];
+ [mainWindowController.mediaArrayController setSelectsInsertedObjects:YES];
+ [mainWindowController.mediaArrayController setAvoidsEmptySelection:YES];
+ [[self layer] addSublayer:mediaListLayer];
+ mediaListLayer.frame = [self layer].bounds;
+ [mediaListLayer setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
+
+ [[self layer] setNeedsDisplay];
+
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if([keyPath isEqualToString:@"hasVideo"])
+ {
+ [self setHasVideo:[object hasVideo]];
+ return;
+ }
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
- (void)dealloc
{
+ /* Previously registered in */
+ [videoLayer removeObserver:self forKeyPath:@"hasVideo"];
+
+ [mediaListLayer release];
+ [videoLayer release];
[tempFullScreenView release];
[selectedPath release];
[super dealloc];
}
+#pragma mark -
+/* Drag and drop */
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ NSPasteboard *pboard;
+
+ pboard = [sender draggingPasteboard];
+
+ if ( [[pboard types] containsObject:NSFilenamesPboardType] &&
+ ![mainWindowController.mediaArrayController.contentMediaList isReadOnly] )
+ {
+ self.layer.borderColor = CGColorCreateGenericGray(0.5, 0.5);
+ self.layer.cornerRadius = 10.f;
+ self.layer.borderWidth = 10.0;
+ return NSDragOperationCopy;
+ }
+ return NSDragOperationNone;
+}
+
+- (void)draggingEnded:(id < NSDraggingInfo >)sender
+{
+ [CATransaction begin];
+ [CATransaction setValue:[NSNumber numberWithFloat:0.1] forKey:kCATransactionAnimationDuration];
+ self.layer.borderWidth = 0.;
+ [CATransaction commit];
+ [CATransaction begin];
+ [mainWindowController.mediaArrayController setFilterPredicate:nil];
+ [mainWindowController.mediaArrayController setSelectionIndex:[mainWindowController.mediaArrayController.contentMediaList count] - 1];
+ [CATransaction commit];
+}
+
+- (void)draggingExited:(id < NSDraggingInfo >)sender
+{
+ self.layer.borderWidth = 0.;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ NSPasteboard *pboard;
+ NSDragOperation sourceDragMask;
+
+ sourceDragMask = [sender draggingSourceOperationMask];
+ pboard = [sender draggingPasteboard];
+
+ if ( [[pboard types] containsObject:NSFilenamesPboardType] )
+ {
+ NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
+ VLCMediaList * mediaList = mainWindowController.mediaArrayController.contentMediaList;
+ if( [mediaList isReadOnly] )
+ return NO;
+
+ [CATransaction begin];
+ for( NSString * filePath in files )
+ [mediaList addMedia:[VLCMedia mediaWithPath:filePath]];
+ [CATransaction commit];
+ }
+ return YES;
+}
+
+- (void)showDrag
+{
+
+}
+
+#pragma mark -
/* Hiding/Displaying the menu */
- (void)hideMenu
[self displayMenu];
}
+- (IBAction)backToMediaListView:(id)sender
+{
+ [mainWindowController.mediaPlayer stop];
+ [self setHasVideo: NO];
+}
+
+#pragma mark -
+/* drawRect */
+
- (void)drawRect:(NSRect)rect
{
- if( [[[self layer] sublayers] count] )
+ if( [self hasVideo] )
{
- /* Don't draw the empty view if we have a video output on screen */
- [super drawRect:rect];
+ [[NSColor blackColor] set];
+ NSRectFill(rect);
return;
}
- NSColor * bottomGradient = [NSColor colorWithCalibratedWhite:0.10 alpha:1.0];
- NSColor * topGradient = [NSColor colorWithCalibratedWhite:0.45 alpha:1.0];
- NSGradient * gradient = [[NSGradient alloc] initWithStartingColor:bottomGradient endingColor:topGradient];
- [gradient drawInRect:self.bounds angle:90.0];
+ NSColor * topGradient = [NSColor colorWithCalibratedWhite:.0f alpha:1.0];
+ NSColor * bottomGradient = [NSColor colorWithCalibratedWhite:0.35f alpha:1.0];
+ NSGradient * gradient = [[NSGradient alloc] initWithColorsAndLocations:bottomGradient, 0.f, topGradient, 0.65f, topGradient, 1.f, nil];
+ [gradient drawInRect:self.bounds angle:100.0];
}
-
+#pragma mark -
/* Event handling */
- (BOOL)acceptsFirstResponder
- (void)mouseDown:(NSEvent *)theEvent
{
- if([theEvent clickCount] != 2)
+ if([theEvent clickCount] == 1)
+ {
+ NSRect rect1 = [self bounds];
+ NSRect rect2 = [self bounds];
+ rect1.origin.x += [self bounds].size.width * 4./5.;
+ rect1.size.width /= 5.;
+ rect2.size.width /= 5.;
+ if(NSPointInRect([self convertPoint:[theEvent locationInWindow] fromView:nil], rect1))
+ {
+ [mainWindowController.mediaArrayController selectNext:self];
+ }
+ else if(NSPointInRect([self convertPoint:[theEvent locationInWindow] fromView:nil], rect2))
+ {
+ [mainWindowController.mediaArrayController selectPrevious:self];
+ }
return;
-
- self.fullScreen = !self.fullScreen;
+ }
+ if([theEvent clickCount] == 2)
+ {
+ [mainWindowController mediaListViewItemDoubleClicked:self];
+ return;
+ }
+ if([theEvent clickCount] == 3)
+ {
+ self.fullScreen = !self.fullScreen;
+ }
}
- (void)keyDown:(NSEvent *)theEvent
else
[self hideMenu];
}
- else if(!menuDisplayed)
+ else if(!menuDisplayed && [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSRightArrowFunctionKey)
{
[self displayMenu];
}
@end
+#pragma mark -
/******************************************************************************
* VLCBrowsableVideoView (Private)
*/
+
@implementation VLCBrowsableVideoView (Private)
+ (CAScrollLayer *)menuLayer
{
@end
+#pragma mark -
+
@implementation VLCBrowsableVideoView (FullScreenTransition)
- (void)enterFullScreen:(NSScreen *)screen
VLCURLToRepresentedFileNameTransformer *urlToRepresentedFileName;
urlToRepresentedFileName = [[[VLCURLToRepresentedFileNameTransformer alloc] init] autorelease];
[NSValueTransformer setValueTransformer:(id)urlToRepresentedFileName forName:@"URLToRepresentedFileNameTransformer"];
+ VLCSelectionIndexToDescriptionTransformer *indexToDescription;
+ indexToDescription = [[[VLCSelectionIndexToDescriptionTransformer alloc] init] autorelease];
+ [NSValueTransformer setValueTransformer:(id)indexToDescription forName:@"SelectionIndexToDescriptionTransformer"];
/***********************************
* categories: Main content
NSArray * mediaDiscoverers = [NSArray arrayWithObjects:
[[[VLCMediaDiscoverer alloc] initWithName:@"shoutcasttv"] autorelease],
[[[VLCMediaDiscoverer alloc] initWithName:@"shoutcast"] autorelease],
- [[[VLCMediaDiscoverer alloc] initWithName:@"sap"] autorelease], nil];
-
- NSArray * playlists = [NSMutableArray arrayWithObjects:[VLCMedia mediaAsNodeWithName:@"Default Playlist"], nil];
-
- NSDictionary * playlistsAsDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- [@"Playlists" uppercaseString], @"descriptionInCategoriesList",
- @"Playlists", @"descriptionInVideoView",
- [NSNumber numberWithBool:NO], @"selectableInCategoriesList",
- playlists, @"childrenInCategoriesList",
- playlists, @"childrenInVideoView",
- nil];
+ [[[VLCMediaDiscoverer alloc] initWithName:@"sap"] autorelease],
+ [[[VLCMediaDiscoverer alloc] initWithName:@"freebox"] autorelease], nil];
self.categories = [NSArray arrayWithObjects:
[NSMutableDictionary dictionaryWithObjectsAndKeys:
mediaDiscoverers, @"childrenInCategoriesList",
mediaDiscoverers, @"childrenInVideoView",
nil],
- playlistsAsDictionary,
+ [VLCMedia mediaAsNodeWithName:@"Playlist"],
nil];
/* Execution will continue in applicationDidFinishLaunching */
- (BOOL)exceptionHandler:(NSExceptionHandler *)sender shouldLogException:(NSException *)exception mask:(unsigned int)aMask
{
[self printStackTrace:exception];
- NSRunCriticalAlertPanel(@"Exception not handled!",
+ NSLog(@"*** Exception Handled! %@: %@", [exception name], [exception reason]);
+ int ret = NSRunCriticalAlertPanel(@"Exception not handled!",
[NSString stringWithFormat:@"%@: %@\n\nBack trace has been printed to Console.\n\nWe will now wait for debugger connection...\n",
[exception name], [exception reason]],
- @"Wait Debugger", nil, nil);
- NSLog(@"*** Exception Handled! %@: %@", [exception name], [exception reason]);
+ @"Quit", @"Wait Debugger", nil);
+ if( ret == NSOKButton )
+ {
+ [NSApp terminate:self];
+ }
return YES;
}
#import <Cocoa/Cocoa.h>
#import <VLCKit/VLCKit.h>
#import "VLCAppAdditions.h"
-#import "VLCMainWindow.h"
+#import "VLCMainWindowController.h"
@interface VLCFullScreenControllerWindow : NSPanel
BOOL active;
/* Owner */
- IBOutlet VLCMainWindow * mainWindow;
+ IBOutlet VLCMainWindowController * mainWindowController;
/* Draging the window using its content */
NSPoint mouseClic;
hideWindowTimer = nil;
/* WindowView setup */
- [[mainWindow.videoView window] setAcceptsMouseMovedEvents:YES];
- [[mainWindow.videoView window] makeFirstResponder:mainWindow.videoView];
- [mainWindow.videoView setPostsBoundsChangedNotifications: YES];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoViewDidChangeBounds:) name:NSViewBoundsDidChangeNotification object:(id)mainWindow.videoView];
+ [[mainWindowController.videoView window] setAcceptsMouseMovedEvents:YES];
+ [[mainWindowController.videoView window] makeFirstResponder:mainWindowController.videoView];
+ [mainWindowController.videoView setPostsBoundsChangedNotifications: YES];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoViewDidChangeBounds:) name:NSViewBoundsDidChangeNotification object:(id)mainWindowController.videoView];
/* Make sure we can know when the mouse is inside us */
[[self contentView] addTrackingRect:[[self contentView] bounds] owner:self userData:nil assumeInside:NO];
[mediaPositionSlider setBackgroundImage:[NSImage imageNamed:@"fs_time_slider.png"]];
[mediaPositionSlider setNeedsDisplay:YES];
- [mediaPositionSlider bind:@"enabled" toObject:mainWindow.mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
- [mediaPositionSlider bind:@"enabled2" toObject:mainWindow.mediaPlayer withKeyPath:@"seekable" options: nil];
+ [mediaPositionSlider bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [mediaPositionSlider bind:@"enabled2" toObject:mainWindowController.mediaPlayer withKeyPath:@"seekable" options: nil];
- [mediaPositionSlider bind:@"value" toObject:mainWindow.mediaPlayer withKeyPath:@"position" options:
+ [mediaPositionSlider bind:@"value" toObject:mainWindowController.mediaPlayer withKeyPath:@"position" options:
[NSDictionary dictionaryWithObjectsAndKeys:@"Float10000FoldTransformer", NSValueTransformerNameBindingOption,
[NSNumber numberWithBool:NO], NSConditionallySetsEnabledBindingOption, nil ]];
- [fillScreenButton bind:@"value" toObject:mainWindow.videoView withKeyPath:@"fillScreen" options: nil];
- [fullScreenButton bind:@"value" toObject:mainWindow.videoView withKeyPath:@"fullScreen" options: nil];
+ [fillScreenButton bind:@"value" toObject:mainWindowController.videoView withKeyPath:@"videoLayer.fillScreen" options: nil];
+ [fullScreenButton bind:@"value" toObject:mainWindowController.videoView withKeyPath:@"fullScreen" options: nil];
- [mediaReadingProgressText bind:@"value" toObject:mainWindow.mediaPlayer withKeyPath:@"time.stringValue" options: nil];
- [mediaDescriptionText bind:@"value" toObject:mainWindow.mediaPlayer withKeyPath:@"description" options: nil];
+ [mediaReadingProgressText bind:@"value" toObject:mainWindowController.mediaPlayer withKeyPath:@"time.stringValue" options: nil];
+ [mediaDescriptionText bind:@"value" toObject:mainWindowController.mediaPlayer withKeyPath:@"description" options: nil];
- /* mediaPlayer */
- [mediaPlayerPlayPauseStopButton bind:@"enabled" toObject:mainWindow.mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
- [mediaPlayerPlayPauseStopButton bind:@"state" toObject:mainWindow.mediaPlayer withKeyPath:@"playing" options: nil];
- [mediaPlayerPlayPauseStopButton bind:@"alternateImage" toObject:mainWindow.mediaPlayer withKeyPath:@"stateAsFullScreenButtonAlternateImage" options: nil];
- [mediaPlayerPlayPauseStopButton bind:@"image" toObject:mainWindow.mediaPlayer withKeyPath:@"stateAsFullScreenButtonImage" options: nil];
- [mediaPlayerBackwardPrevButton bind:@"enabled" toObject:mainWindow.mediaPlayer withKeyPath:@"playing" options: nil];
- [mediaPlayerForwardNextButton bind:@"enabled" toObject:mainWindow.mediaPlayer withKeyPath:@"playing" options: nil];
- [mediaPlayerForwardNextButton setTarget:mainWindow.mediaPlayer];
+ /* mainWindowController.mediaPlayer */
+ [mediaPlayerPlayPauseStopButton bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [mediaPlayerPlayPauseStopButton bind:@"state" toObject:mainWindowController.mediaPlayer withKeyPath:@"playing" options: nil];
+ [mediaPlayerPlayPauseStopButton bind:@"alternateImage" toObject:mainWindowController.mediaPlayer withKeyPath:@"stateAsFullScreenButtonAlternateImage" options: nil];
+ [mediaPlayerPlayPauseStopButton bind:@"image" toObject:mainWindowController.mediaPlayer withKeyPath:@"stateAsFullScreenButtonImage" options: nil];
+ [mediaPlayerBackwardPrevButton bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"playing" options: nil];
+ [mediaPlayerForwardNextButton bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"playing" options: nil];
+ [mediaPlayerForwardNextButton setTarget:mainWindowController.mediaPlayer];
[mediaPlayerForwardNextButton setAction:@selector(fastForward)];
- [mediaPlayerBackwardPrevButton setTarget:mainWindow.mediaPlayer];
+ [mediaPlayerBackwardPrevButton setTarget:mainWindowController.mediaPlayer];
[mediaPlayerBackwardPrevButton setAction:@selector(rewind)];
- [mediaPlayerPlayPauseStopButton setTarget:mainWindow.mediaPlayer];
+ [mediaPlayerPlayPauseStopButton setTarget:mainWindowController.mediaPlayer];
[mediaPlayerPlayPauseStopButton setAction:@selector(pause)];
- [self bind:@"fullScreen" toObject:mainWindow.videoView withKeyPath:@"fullScreen" options: nil];
+ [self bind:@"fullScreen" toObject:mainWindowController.videoView withKeyPath:@"fullScreen" options: nil];
active = NO;
}
- (void)updateTrackingRect
{
- VLCVideoView * videoView = mainWindow.videoView;
+ VLCBrowsableVideoView * videoView = mainWindowController.videoView;
if( videoViewTrackingArea )
{
*****************************************************************************/
#import <Cocoa/Cocoa.h>
-#import "VLCController.h"
-#import "VLCMediaArrayController.h"
-#import "VLCAppAdditions.h"
-#import "VLCBrowsableVideoView.h"
@interface VLCMainWindow : NSWindow {
- /* IB elements */
- IBOutlet id mediaListItemFetchedStatus;
- IBOutlet id mediaListItemsCount;
- IBOutlet id mediaListSearchField;
-
- IBOutlet NSOutlineView * categoriesListView;
- IBOutlet NSTableView * mediaListView;
-
- IBOutlet VLCBrowsableVideoView * videoView;
- IBOutlet id fillScreenButton;
- IBOutlet id fullScreenButton;
- IBOutlet NSSlider * mediaReadingProgressSlider;
- IBOutlet NSTextField * mediaReadingProgressText;
- IBOutlet NSTextField * mediaDescriptionText;
-
- IBOutlet NSSlider * mediaSoundVolume;
-
- IBOutlet NSButton * mediaPlayerForwardNextButton;
- IBOutlet NSButton * mediaPlayerBackwardPrevButton;
- IBOutlet NSButton * mediaPlayerPlayPauseStopButton;
-
- IBOutlet id navigatorViewToggleButton;
- IBOutlet VLCOneSplitView * mainSplitView;
- IBOutlet NSView * navigatorView;
- IBOutlet NSView * videoPlayerAndControlView;
- IBOutlet NSView * controlView;
-
- IBOutlet NSButton * addPlaylistButton;
- IBOutlet NSButton * removePlaylistButton;
-
- /* Toolbar */
- IBOutlet NSView * toolbarMediaAudioVolume;
- IBOutlet NSView * toolbarMediaDescription;
- IBOutlet NSView * toolbarMediaControl;
-
- IBOutlet VLCMediaPlayer * mediaPlayer;
-
- IBOutlet VLCController * controller; /* This is a VLCController binded to the File's Owner of the nib */
-
- /* Controllers */
- NSTreeController * categoriesTreeController;
- VLCMediaArrayController * mediaArrayController;
-
- /* Window state */
- CGFloat navigatorHeight;
}
-@property BOOL navigatorViewVisible;
-@property (readonly) VLCMediaPlayer * mediaPlayer;
-@property (readonly) VLCBrowsableVideoView * videoView;
@end
*****************************************************************************/
#import "VLCMainWindow.h"
-#import "ImageAndTextCell.h"
-#import "VLCMediaArrayController.h"
-#import "VLCBrowsableVideoView.h"
-#import "VLCAppAdditions.h"
-#import "VLCFullScreenControllerWindow.h"
-@interface VLCMainWindow (NavigatorViewHidingShowing)
-@property float contentHeight; /* animatable, keep the mainSplitView cursor at the same place, enabling playlist(navigator) togling */
-@end
-
-/******************************************************************************
- * VLCMainWindow (CategoriesListDelegate)
- */
-@implementation VLCMainWindow (CategoriesListDelegate)
-- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
-{
- return [[item representedObject] isKindOfClass:[NSDictionary class]];
-}
-- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
-{
- return !([[item representedObject] isKindOfClass:[NSDictionary class]]);
-}
-- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
-{
- [cell setRepresentedObject:[item representedObject]];
-}
-@end
-
-/******************************************************************************
- * VLCMainWindow (CategoriesListDataSource)
- */
-@implementation VLCMainWindow (CategoriesListDataSource)
-/* Drag and drop */
-- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index
-{
- int i;
-
- if(![item respondsToSelector:@selector(representedObject)])
- return NO;
-
- NSArray *droppedItems = [[info draggingPasteboard] propertyListForType:@"VLCMediaURLType"];
- if( !droppedItems )
- droppedItems = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
- if( !droppedItems )
- droppedItems = [[info draggingPasteboard] propertyListForType:NSURLPboardType];
-
- NSAssert( droppedItems, @"Dropped an unsupported object type on the outline View" );
-
- VLCMediaList * mediaList = [(VLCMedia *)[item representedObject] subitems];
-
- for (i = 0; i < [droppedItems count]; i++)
- {
- NSString * filename = [droppedItems objectAtIndex:i];
- VLCMedia *media = [VLCMedia mediaWithPath:filename];
- [mediaList lock];
- [mediaList insertMedia:media atIndex:index+1];
- [mediaList unlock];
- }
- return YES;
-}
-
-- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
-{
- NSArray *droppedItems = [[info draggingPasteboard] propertyListForType:@"VLCMediaURLType"];
- if( !droppedItems )
- droppedItems = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
- if( !droppedItems )
- droppedItems = [[info draggingPasteboard] propertyListForType:NSURLPboardType];
-
- if(! droppedItems ||
- ![item respondsToSelector:@selector(representedObject)] ||
- ![[item representedObject] isKindOfClass:[VLCMedia class]] )
- {
- return NSDragOperationNone;
- }
-
- return NSDragOperationMove;
-}
-@end
/******************************************************************************
* VLCMainWindow
*/
@implementation VLCMainWindow
-@synthesize mediaPlayer;
-@synthesize videoView;
-
-- (void)awakeFromNib;
-{
- NSTableColumn * tableColumn;
-
- /* Check ib outlets */
- NSAssert( mainSplitView, @"No split view or wrong split view");
- NSAssert( fullScreenButton, @"No fullscreen button");
-
- /***********************************
- * Init the media player
- */
- [mediaPlayer setVideoView:videoView];
-
- /***********************************
- * CategoriesList OutlineView content
- */
- /* categoriesTreeController */
- categoriesTreeController = [[NSTreeController alloc] init];
- [categoriesTreeController setContent:controller.categories];
-
- [categoriesTreeController setChildrenKeyPath:@"childrenInCategoriesList"];
- //[categoriesTreeController bind:@"contentArray" toObject:controller withKeyPath:@"arrayOfMasters" options:nil];
-
- /* Bind the "name" table column */
- tableColumn = [categoriesListView tableColumnWithIdentifier:@"name"];
- [tableColumn bind:@"value" toObject: categoriesTreeController withKeyPath:@"arrangedObjects.descriptionInCategoriesList" options:nil];
- [tableColumn setEditable:YES];
- /* FIXME: this doesn't work obviously. */
- [tableColumn bind:@"editable" toObject: categoriesTreeController withKeyPath:@"arrangedObjects.editableInCategoriesList" options:nil];
-
- /* Use an ImageAndTextCell in the "name" table column */
- ImageAndTextCell * cell = [[ImageAndTextCell alloc] init];
- [cell setFont:[[tableColumn dataCell] font]];
- [cell setImageKeyPath:@"image"];
-
- [tableColumn setDataCell:cell];
-
- /* Other setup */
- [categoriesListView setIndentationMarkerFollowsCell:YES];
- [categoriesListView setAutoresizesOutlineColumn:NO];
- [categoriesListView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
- [categoriesListView setDelegate:self];
-
- [categoriesListView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, @"VLCMediaURLType", nil]];
- [categoriesListView setDataSource: self];
-
- /***********************************
- * mediaListView setup
- */
-
- mediaArrayController = [[VLCMediaArrayController alloc] init];
-
- /* 1- Drag and drop */
- [mediaListView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]];
- [mediaListView setDataSource:mediaArrayController];
-
- /* 2- Double click */
- [mediaListView setTarget:self];
- [mediaListView setDoubleAction:@selector(mediaListViewItemDoubleClicked:)];
-
- /* 3- binding for "title" column */
- tableColumn = [mediaListView tableColumnWithIdentifier:@"title"];
- [tableColumn bind:@"value" toObject: mediaArrayController withKeyPath:@"arrangedObjects.metaDictionary.title" options:nil];
-
- /* 4- binding for "state" column */
- tableColumn = [mediaListView tableColumnWithIdentifier:@"state"];
- [tableColumn bind:@"value" toObject: mediaArrayController withKeyPath:@"arrangedObjects.stateAsImage" options:nil];
-
- /* 5- Search & Predicate */
- NSMutableDictionary * bindingOptions = [NSMutableDictionary dictionary];
- [bindingOptions setObject:@"metaDictionary.title contains[c] $value" forKey:NSPredicateFormatBindingOption];
- [bindingOptions setObject:@"No Title" forKey:NSDisplayNameBindingOption];
- [mediaListSearchField bind:@"predicate" toObject: mediaArrayController withKeyPath:@"filterPredicate" options:bindingOptions];
-
- /* 6- Bind the @"contentArray" and contentMediaList of the mediaArrayController */
- [mediaArrayController bind:@"contentArray" toObject:categoriesTreeController withKeyPath:@"selection.childrenInCategoriesListForDetailView.media" options:nil];
- [mediaArrayController bind:@"contentMediaList" toObject:categoriesTreeController withKeyPath:@"selection.childrenInCategoriesListForDetailView.parentMediaList" options:nil];
-
- /* 7- Aspect */
- [mediaListView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
- [mediaListView setAllowsTypeSelect:YES];
-
- /***********************************
- * videoView setup
- */
- [videoView setItemsTree:controller.categories];
- [videoView setNodeKeyPath:@"childrenInVideoView"];
- [videoView setContentKeyPath:@"descriptionInVideoView"];
- [videoView setTarget:self];
- [videoView setAction:@selector(videoViewItemClicked:)];
-
- /***********************************
- * Toolbar setup
- */
- [[self toolbar] setDelegate:self];
-
- /***********************************
- * Other interface element setup
- */
-
- [mediaListItemsCount bind:@"displayPatternValue1" toObject:mediaArrayController withKeyPath:@"arrangedObjects.@count" options:[NSDictionary dictionaryWithObject:@"%{value1}@ items" forKey:NSDisplayPatternBindingOption]];
- [mediaListItemFetchedStatus bind:@"animate" toObject:categoriesTreeController withKeyPath:@"selection.currentlyFetchingItems" options:[NSDictionary dictionaryWithObject:@"%{value1}@ items" forKey:NSDisplayPatternBindingOption]];
-
- [fillScreenButton bind:@"value" toObject:videoView withKeyPath:@"fillScreen" options: nil];
- [fullScreenButton bind:@"value" toObject:videoView withKeyPath:@"fullScreen" options: nil];
- [fullScreenButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
- [fillScreenButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
-
- [mediaReadingProgressSlider bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
- [mediaReadingProgressSlider bind:@"enabled2" toObject:mediaPlayer withKeyPath:@"seekable" options: nil];
-
- [mediaReadingProgressSlider bind:@"value" toObject:mediaPlayer withKeyPath:@"position" options:
- [NSDictionary dictionaryWithObjectsAndKeys:@"Float10000FoldTransformer", NSValueTransformerNameBindingOption,
- [NSNumber numberWithBool:NO], NSConditionallySetsEnabledBindingOption, nil ]];
- [mediaReadingProgressText bind:@"value" toObject:mediaPlayer withKeyPath:@"time.stringValue" options: nil];
- [mediaDescriptionText bind:@"value" toObject:mediaPlayer withKeyPath:@"description" options: nil];
- [self bind:@"representedFilename" toObject:mediaPlayer withKeyPath:@"media.url" options: [NSDictionary dictionaryWithObject:@"URLToRepresentedFileNameTransformer" forKey:NSValueTransformerNameBindingOption]];
- [self bind:@"title" toObject:mediaPlayer withKeyPath:@"description" options: nil];
-
- [navigatorViewToggleButton bind:@"value" toObject:self withKeyPath:@"navigatorViewVisible" options: nil];
-
- /* Playlist buttons */
- [removePlaylistButton bind:@"enabled" toObject:categoriesTreeController withKeyPath:@"selection.editableInCategoriesList" options: nil];
- [removePlaylistButton setTarget:categoriesTreeController];
- [removePlaylistButton setAction:@selector(remove:)];
- [addPlaylistButton setTarget:controller];
- [addPlaylistButton setAction:@selector(addPlaylist:)];
-
- [mainSplitView setDelegate:self];
-
- /* Sound */
- [mediaSoundVolume bind:@"value" toObject:[VLCLibrary sharedLibrary] withKeyPath:@"audio.volume" options: nil];
-
- /* mediaPlayer */
- [mediaPlayerPlayPauseStopButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
- [mediaPlayerPlayPauseStopButton bind:@"state" toObject:mediaPlayer withKeyPath:@"playing" options: nil];
- [mediaPlayerPlayPauseStopButton bind:@"alternateImage" toObject:mediaPlayer withKeyPath:@"stateAsButtonAlternateImage" options: nil];
- [mediaPlayerPlayPauseStopButton bind:@"image" toObject:mediaPlayer withKeyPath:@"stateAsButtonImage" options: nil];
- [mediaPlayerBackwardPrevButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"playing" options: nil];
- [mediaPlayerForwardNextButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"playing" options: nil];
- [mediaPlayerForwardNextButton setTarget:mediaPlayer];
- [mediaPlayerForwardNextButton setAction:@selector(fastForward)];
- [mediaPlayerBackwardPrevButton setTarget:mediaPlayer];
- [mediaPlayerBackwardPrevButton setAction:@selector(rewind)];
- [mediaPlayerPlayPauseStopButton setTarget:mediaPlayer];
- [mediaPlayerPlayPauseStopButton setAction:@selector(pause)];
-
- /* Last minute setup */
- [categoriesListView expandItem:nil expandChildren:YES];
- [categoriesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:[categoriesListView numberOfRows] > 0 ? [categoriesListView numberOfRows]-1 : 0] byExtendingSelection:NO];
-}
-
-- (void)dealloc
-{
- [navigatorView release];
- [mediaPlayer release];
- [categoriesTreeController release];
- [mediaArrayController release];
- [super dealloc];
-}
-
-- (void)mediaListViewItemDoubleClicked:(id)sender
-{
- if([[mediaArrayController selectedObjects] count] <= 0 )
- return;
- [mediaPlayer setMedia:[[mediaArrayController selectedObjects] objectAtIndex:0]];
- [mediaPlayer play];
-}
-
-- (void)videoViewItemClicked:(id)sender
-{
- id object = [sender selectedObject];
- NSAssert( [object isKindOfClass:[VLCMedia class]], @"Object is not a VLCMedia" );
-
- [mediaPlayer setMedia:object];
- [mediaPlayer play];
-}
-
-- (BOOL)videoViewVisible
-{
- NSAssert( mainSplitView && [[mainSplitView subviews] count] == 2, @"No split view or wrong split view");
- return ([[[mainSplitView subviews] objectAtIndex:0] frame].size.height > 50.);
-}
-
-- (BOOL)navigatorViewVisible
-{
- NSAssert( mainSplitView && [[mainSplitView subviews] count] == 2, @"No split view or wrong split view");
- return ([[[mainSplitView subviews] objectAtIndex:1] frame].size.height > 6.);
-}
-
-
-- (void)setNavigatorViewVisible:(BOOL)visible
-{
- NSAssert( mainSplitView && [[mainSplitView subviews] count] == 2, @"No split view or wrong split view");
- if(!([self navigatorViewVisible] ^ visible))
- return; /* Nothing to do */
-
- if(visible)
- {
- /* Show the navigator view (playlist view) */
- if( navigatorHeight < 100.f ) navigatorHeight = 100.f;
- if( ![self videoViewVisible] && ![self navigatorViewVisible] )
- {
- /* Nothing is visible, only our toolbar */
- NSRect frame = [self frame];
- frame.origin.y += navigatorHeight;
- frame.size.height += navigatorHeight;
- [[self animator] setFrame:frame display:YES];
- }
- else
- [[self animator] setContentHeight:[[self contentView] frame].size.height + navigatorHeight ];
- /* Hack, because sliding cause some glitches */
- [navigatorView moveSubviewsToVisible];
- }
- else
- {
- /* Hide the navigator view (playlist view) */
- navigatorHeight = [navigatorView bounds].size.height;
- [[self animator] setContentHeight:[[self contentView] frame].size.height - navigatorHeight];
- /* Hack, because sliding cause some glitches */
- [navigatorView moveSubviewsToVisible];
- }
-}
@end
-@implementation VLCMainWindow (SplitViewDelegating)
-- (CGFloat)splitView:(NSSplitView *)sender constrainSplitPosition:(CGFloat)proposedPosition ofSubviewAt:(NSInteger)offset
-{
- CGFloat minHeight = 34.;
-
- /* Hack, because sliding cause some glitches */
- [navigatorView moveSubviewsToVisible];
-
- /* Make a stuck point at the bottom of the nav view */
- if( [sender bounds].size.height - proposedPosition < minHeight )
- return [sender bounds].size.height;
-
- return proposedPosition;
-}
-
-- (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize
-{
- [sender adjustSubviews];
-
- /* Hack, because sliding cause some glitches */
- [navigatorView setFrame:[[navigatorView superview] bounds]];
- [navigatorView moveSubviewsToVisible];
-}
-
-- (void)splitViewWillResizeSubviews:(NSNotification *)aNotification
-{
- /* Hack, because sliding cause some glitches */
- [navigatorView moveSubviewsToVisible];
-
- /* This could be changed from now on, so post a KVO notification */
- [self willChangeValueForKey:@"navigatorViewVisible"];
-}
-- (void)splitViewDidResizeSubviews:(NSNotification *)aNotification
-{
- [self didChangeValueForKey:@"navigatorViewVisible"];
-}
-@end
-
-@implementation VLCMainWindow (NSWindowDelegating)
-- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
-{
- if( proposedFrameSize.height < 120.f)
- proposedFrameSize.height = [self minSize].height;
- return proposedFrameSize;
-}
-@end
-
-@implementation VLCMainWindow (NavigatorViewHidingShowing)
-- (float)contentHeight
-{
- return [self contentRectForFrameRect:[self frame]].size.height;
-}
-
-- (void)setContentHeight:(float)height
-{
- /* Set the Height while keeping the mainSplitView at his current position */
- [mainSplitView setFixedCursorDuringResize:YES];
- NSRect contentRect = [self contentRectForFrameRect:[self frame]];
- float delta = height - contentRect.size.height;
- contentRect.size.height = height;
- NSRect windowFrame = [self frameRectForContentRect:contentRect];
- windowFrame.origin.y -= delta;
- windowFrame = [self constrainFrameRect:windowFrame toScreen:[self screen]];
- [self setFrame:windowFrame display:YES];
- [mainSplitView setFixedCursorDuringResize:NO];
-}
-
-+ (id)defaultAnimationForKey:(NSString *)key
-{
- if([key isEqualToString:@"contentHeight"])
- {
- return [CABasicAnimation animation];
- }
- return [super defaultAnimationForKey: key];
-}
-@end
-
-@implementation VLCMainWindow (NSToolbarDelegating)
-/* Our item identifiers */
-static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl";
-static NSString * VLCToolbarMediaAudioVolume = @"VLCToolbarMediaAudioVolume";
-static NSString * VLCToolbarMediaDescription = @"VLCToolbarMediaDescription";
-
-- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
-{
- return [NSArray arrayWithObjects:
- NSToolbarCustomizeToolbarItemIdentifier,
- NSToolbarFlexibleSpaceItemIdentifier,
- NSToolbarSpaceItemIdentifier,
- NSToolbarSeparatorItemIdentifier,
- VLCToolbarMediaControl,
- VLCToolbarMediaAudioVolume,
- VLCToolbarMediaDescription,
- nil ];
-}
-
-- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
-{
- return [NSArray arrayWithObjects:
- VLCToolbarMediaControl,
- VLCToolbarMediaAudioVolume,
- VLCToolbarMediaDescription,
- nil ];
-}
-
-- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
-{
- NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
-
- if( [itemIdentifier isEqual: VLCToolbarMediaControl] )
- {
- [toolbarItem setLabel:@"Media Controls"];
- [toolbarItem setPaletteLabel:@"Media Controls"];
-
- [toolbarItem setView:toolbarMediaControl];
- [toolbarItem setMinSize:[[toolbarItem view] frame].size];
- [toolbarItem setMaxSize:[[toolbarItem view] frame].size];
-
- /* TODO: setup a menu */
- }
- else if( [itemIdentifier isEqual: VLCToolbarMediaAudioVolume] )
- {
- [toolbarItem setLabel:@"Audio Volume"];
- [toolbarItem setPaletteLabel:@"Audio Volume"];
-
- [toolbarItem setView:toolbarMediaAudioVolume];
- [toolbarItem setMinSize:[[toolbarItem view] frame].size];
- [toolbarItem setMaxSize:[[toolbarItem view] frame].size];
-
- /* TODO: setup a menu */
- }
- else if( [itemIdentifier isEqual: VLCToolbarMediaDescription] )
- {
- [toolbarItem setLabel:@"Media Description"];
- [toolbarItem setPaletteLabel:@"Media Description"];
-
- [toolbarItem setView:toolbarMediaDescription];
- [toolbarItem setMinSize:[[toolbarItem view] frame].size];
- [toolbarItem setMaxSize:NSMakeSize(10000 /* Can be really big */, NSHeight([[toolbarItem view] frame]))];
-
- /* TODO: setup a menu */
- }
- else
- {
- /* itemIdentifier referred to a toolbar item that is not
- * provided or supported by us or Cocoa
- * Returning nil will inform the toolbar
- * that this kind of item is not supported */
- toolbarItem = nil;
- }
- return toolbarItem;
-}
-@end
--- /dev/null
+/*****************************************************************************
+ * VLCMainWindowController.h: VLCMainWindowController implementation
+ *****************************************************************************
+ * Copyright (C) 2007 Pierre d'Herbemont
+ * Copyright (C) 2007 the VideoLAN team
+ * $Id: VLCMainWindow.h 24209 2008-01-09 22:05:17Z pdherbemont $
+ *
+ * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+#import "VLCController.h"
+#import "VLCMediaArrayController.h"
+#import "VLCAppAdditions.h"
+#import "VLCBrowsableVideoView.h"
+#import "VLCMainWindow.h"
+
+
+@interface VLCMainWindowController : NSWindowController
+{
+ IBOutlet VLCOneSplitView * mainSplitView;
+
+ /* Media List */
+ IBOutlet NSTableView * mediaListView;
+
+ /* Categories List */
+ IBOutlet NSOutlineView * categoriesListView;
+
+ IBOutlet NSButton * addPlaylistButton;
+ IBOutlet NSButton * removePlaylistButton;
+
+ /* Toolbar control buttons */
+ IBOutlet NSButton * mediaPlayerForwardNextButton;
+ IBOutlet NSButton * mediaPlayerBackwardPrevButton;
+ IBOutlet NSButton * mediaPlayerPlayPauseStopButton;
+
+
+ /* Toolbar */
+ IBOutlet NSView * toolbarMediaAudioVolume;
+ IBOutlet NSView * toolbarMediaDescription;
+ IBOutlet NSView * toolbarMediaControl;
+
+ /* Video */
+ IBOutlet VLCBrowsableVideoView * videoView;
+
+ /* Controllers */
+ IBOutlet NSTreeController * categoriesTreeController;
+ IBOutlet VLCMediaArrayController * mediaArrayController;
+ IBOutlet VLCMediaPlayer * mediaPlayer;
+ IBOutlet VLCController * controller; /* This is a VLCController binded to the File's Owner of the nib */
+
+ /* States */
+ float navigatorViewWidth;
+}
+
+@property BOOL navigatorViewVisible;
+
+- (void)setNavigatorViewVisible:(BOOL)wantsVisible animate:(BOOL)animate;
+
+@property (readonly) VLCMediaPlayer * mediaPlayer;
+@property (readonly) VLCBrowsableVideoView * videoView;
+@property (readonly) VLCMediaArrayController * mediaArrayController;
+
+- (IBAction)mediaListViewItemDoubleClicked:(id)sender;
+- (void)videoViewItemClicked:(id)sender;
+@end
--- /dev/null
+/*****************************************************************************
+ * VLCMainWindowController.m: VLCMainWindowController implementation
+ *****************************************************************************
+ * Copyright (C) 2007 Pierre d'Herbemont
+ * Copyright (C) 2007 the VideoLAN team
+ * $Id: VLCMainWindow.h 24209 2008-01-09 22:05:17Z pdherbemont $
+ *
+ * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "VLCMainWindowController.h"
+#import "VLCAppAdditions.h"
+#import "ImageAndTextCell.h"
+
+/******************************************************************************
+ * @implementation VLCMainWindowController
+ */
+
+@implementation VLCMainWindowController
+
+@synthesize mediaPlayer;
+@synthesize videoView;
+@synthesize mediaArrayController;
+
+- (void)awakeFromNib
+{
+ NSTableColumn * tableColumn;
+
+ /***********************************
+ * Init the media player
+ */
+
+ NSAssert( mediaPlayer, @"No mediaPlayer" );
+
+ categoriesTreeController = [[NSTreeController alloc] init];
+
+ /***********************************
+ * CategoriesList OutlineView content
+ */
+ /* categoriesTreeController */
+ NSAssert( categoriesTreeController, @"No categoriesTreeController" );
+ NSAssert( categoriesListView, @"No categoriesListView" );
+ NSAssert( controller, @"No controller" );
+
+ [categoriesTreeController setContent:controller.categories];
+ //[categoriesTreeController bind:@"content" toObject:controller withKeyPath:@"categories" options:nil];
+
+ [categoriesTreeController setChildrenKeyPath:@"childrenInCategoriesList"];
+
+ /* Bind the "name" table column */
+ tableColumn = [categoriesListView tableColumnWithIdentifier:@"name"];
+ [tableColumn bind:@"value" toObject:categoriesTreeController withKeyPath:@"arrangedObjects.descriptionInCategoriesList" options:nil];
+
+ /* Use an ImageAndTextCell in the "name" table column */
+ ImageAndTextCell * cell = [[ImageAndTextCell alloc] init];
+ [cell setFont:[[tableColumn dataCell] font]];
+ [cell setImageKeyPath:@"image"];
+ [tableColumn setDataCell: cell];
+
+ /* Other setup */
+ [categoriesListView setIndentationMarkerFollowsCell:YES];
+ [categoriesListView setAutoresizesOutlineColumn:NO];
+ [categoriesListView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
+ [categoriesListView setDelegate:self];
+
+ [categoriesListView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, @"VLCMediaURLType", nil]];
+ [categoriesListView setDataSource: self];
+
+ /***********************************
+ * mediaListView setup
+ */
+
+ /* 1- Drag and drop */
+ NSAssert( mediaArrayController, @"No mediaArrayController" );
+ NSAssert( mediaListView, @"No mediaListView" );
+ [mediaListView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSURLPboardType, nil]];
+ [mediaListView setDataSource:mediaArrayController];
+ /* 3- binding for "title" column */
+ tableColumn = [mediaListView tableColumnWithIdentifier:@"title"];
+ [tableColumn bind:@"value" toObject: mediaArrayController withKeyPath:@"arrangedObjects.metaDictionary.title" options:nil];
+
+
+ /* 2- Double click */
+ [mediaListView setTarget:self];
+ [mediaListView setDoubleAction:@selector(mediaListViewItemDoubleClicked:)];
+
+
+ /* 4- binding for "state" column */
+ tableColumn = [mediaListView tableColumnWithIdentifier:@"state"];
+ [tableColumn bind:@"value" toObject: mediaArrayController withKeyPath:@"arrangedObjects.stateAsImage" options:nil];
+
+ /* 6- Bind the @"contentArray" and contentMediaList of the mediaArrayController */
+ [mediaArrayController bind:@"contentArray" toObject:categoriesTreeController withKeyPath:@"selection.childrenInCategoriesListForDetailView.media" options:nil];
+
+ [mediaArrayController bind:@"contentMediaList" toObject:categoriesTreeController withKeyPath:@"selection.childrenInCategoriesListForDetailView.parentMediaList" options:nil];
+
+ /* 7- Aspect */
+ [mediaListView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
+ [mediaListView setAllowsTypeSelect:YES];
+
+ /***********************************
+ * videoView setup
+ */
+ [videoView setItemsTree:controller.categories];
+ [videoView setNodeKeyPath:@"childrenInVideoView"];
+ [videoView setContentKeyPath:@"descriptionInVideoView"];
+ [videoView setTarget:self];
+ [videoView setAction:@selector(videoViewItemClicked:)];
+
+ /***********************************
+ * Toolbar setup
+ */
+
+ /***********************************
+ * Other interface element setup
+ */
+#if 0
+
+ [mediaListItemsCount bind:@"displayPatternValue1" toObject:mediaArrayController withKeyPath:@"arrangedObjects.@count" options:[NSDictionary dictionaryWithObject:@"%{value1}@ items" forKey:NSDisplayPatternBindingOption]];
+ [mediaListItemFetchedStatus bind:@"animate" toObject:categoriesTreeController withKeyPath:@"selection.currentlyFetchingItems" options:[NSDictionary dictionaryWithObject:@"%{value1}@ items" forKey:NSDisplayPatternBindingOption]];
+
+ [fillScreenButton bind:@"value" toObject:videoView withKeyPath:@"fillScreen" options: nil];
+ [fullScreenButton bind:@"value" toObject:videoView withKeyPath:@"fullScreen" options: nil];
+ [fullScreenButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [fillScreenButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [mediaReadingProgressSlider bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [mediaReadingProgressSlider bind:@"enabled2" toObject:mediaPlayer withKeyPath:@"seekable" options: nil];
+
+ [mediaReadingProgressSlider bind:@"value" toObject:mediaPlayer withKeyPath:@"position" options:
+ [NSDictionary dictionaryWithObjectsAndKeys:@"Float10000FoldTransformer", NSValueTransformerNameBindingOption,
+ [NSNumber numberWithBool:NO], NSConditionallySetsEnabledBindingOption, nil ]];
+ [mediaReadingProgressText bind:@"value" toObject:mediaPlayer withKeyPath:@"time.stringValue" options: nil];
+ [mediaDescriptionText bind:@"value" toObject:mediaPlayer withKeyPath:@"description" options: nil];
+ [self bind:@"representedFilename" toObject:mediaPlayer withKeyPath:@"media.url" options: [NSDictionary dictionaryWithObject:@"URLToRepresentedFileNameTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [self bind:@"title" toObject:mediaPlayer withKeyPath:@"description" options: nil];
+
+ [navigatorViewToggleButton bind:@"value" toObject:self withKeyPath:@"navigatorViewVisible" options: nil];
+#endif
+
+ /* Playlist buttons */
+#if 0
+ [removePlaylistButton bind:@"enabled" toObject:categoriesTreeController withKeyPath:@"selection.editableInCategoriesList" options: nil];
+#endif
+ [removePlaylistButton setTarget:categoriesTreeController];
+ [removePlaylistButton setAction:@selector(remove:)];
+ [addPlaylistButton setTarget:controller];
+ [addPlaylistButton setAction:@selector(addPlaylist:)];
+
+ /* mediaPlayer */
+#if 0
+ [mediaPlayerPlayPauseStopButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
+ [mediaPlayerPlayPauseStopButton bind:@"state" toObject:mediaPlayer withKeyPath:@"playing" options: nil];
+ [mediaPlayerPlayPauseStopButton bind:@"alternateImage" toObject:mediaPlayer withKeyPath:@"stateAsButtonAlternateImage" options: nil];
+ [mediaPlayerPlayPauseStopButton bind:@"image" toObject:mediaPlayer withKeyPath:@"stateAsButtonImage" options: nil];
+ [mediaPlayerBackwardPrevButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"playing" options: nil];
+ [mediaPlayerForwardNextButton bind:@"enabled" toObject:mediaPlayer withKeyPath:@"playing" options: nil];
+#endif
+
+ [mediaPlayerForwardNextButton setTarget:mediaPlayer];
+ [mediaPlayerForwardNextButton setAction:@selector(fastForward)];
+ [mediaPlayerBackwardPrevButton setTarget:mediaPlayer];
+ [mediaPlayerBackwardPrevButton setAction:@selector(rewind)];
+ [mediaPlayerPlayPauseStopButton setTarget:mediaPlayer];
+ [mediaPlayerPlayPauseStopButton setAction:@selector(pause)];
+
+ /* Last minute setup */
+ [categoriesListView expandItem:nil expandChildren:YES];
+ [categoriesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:[categoriesListView numberOfRows] > 0 ? [categoriesListView numberOfRows]-1 : 0] byExtendingSelection:NO];
+ [self setNavigatorViewVisible:NO animate:NO];
+ [self showWindow:self];
+ [mainSplitView setDelegate:self];
+}
+
+- (BOOL)navigatorViewVisible
+{
+ return [mainSplitView sliderPosition] <= [mainSplitView bounds].size.width - [mainSplitView dividerThickness] - 30.f /* To be tolerant */;
+}
+
+- (void)setNavigatorViewVisible:(BOOL)wantsVisible animate:(BOOL)animate
+{
+ if( [self navigatorViewVisible] == wantsVisible )
+ return;
+
+ if( !animate ) [self willChangeValueForKey:@"navigatorViewVisible"];
+
+ VLCOneSplitView * splitView = animate ? [mainSplitView animator] : mainSplitView;
+
+ if( wantsVisible )
+ {
+ if( navigatorViewWidth >= [mainSplitView bounds].size.width - 200.f )
+ navigatorViewWidth = [mainSplitView bounds].size.width - 200.f;
+ [splitView setSliderPosition:navigatorViewWidth];
+ }
+ else
+ {
+ navigatorViewWidth = [videoView frame].size.width;
+ [splitView setSliderPosition:[mainSplitView bounds].size.width - [mainSplitView dividerThickness]];
+ }
+ if( !animate ) [self didChangeValueForKey:@"navigatorViewVisible"];
+}
+
+- (void)setNavigatorViewVisible:(BOOL)wantsVisible
+{
+ [self setNavigatorViewVisible:wantsVisible animate:YES];
+}
+
+- (IBAction)mediaListViewItemDoubleClicked:(id)sender
+{
+ if([[mediaArrayController selectedObjects] count] <= 0 )
+ return;
+ [mediaPlayer setMedia:[[mediaArrayController selectedObjects] objectAtIndex:0]];
+ [mediaPlayer play];
+}
+
+- (void)videoViewItemClicked:(id)sender
+{
+ id object = [sender selectedObject];
+ NSAssert( [object isKindOfClass:[VLCMedia class]], @"Object is not a VLCMedia" );
+
+ [mediaPlayer setMedia:object];
+ [mediaPlayer play];
+}
+
+@end
+
+/******************************************************************************
+ * @implementation VLCMainWindowController (NSToolbarDelegating)
+ */
+
+@implementation VLCMainWindowController (NSToolbarDelegating)
+/* Our item identifiers */
+static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl";
+static NSString * VLCToolbarMediaAudioVolume = @"VLCToolbarMediaAudioVolume";
+static NSString * VLCToolbarMediaDescription = @"VLCToolbarMediaDescription";
+
+- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
+{
+ return [NSArray arrayWithObjects:
+ NSToolbarCustomizeToolbarItemIdentifier,
+ NSToolbarFlexibleSpaceItemIdentifier,
+ NSToolbarSpaceItemIdentifier,
+ NSToolbarSeparatorItemIdentifier,
+ VLCToolbarMediaControl,
+ VLCToolbarMediaAudioVolume,
+ VLCToolbarMediaDescription,
+ nil ];
+}
+
+- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
+{
+ return [NSArray arrayWithObjects:
+ VLCToolbarMediaControl,
+ VLCToolbarMediaAudioVolume,
+ VLCToolbarMediaDescription,
+ nil ];
+}
+
+- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
+{
+ NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
+
+ if( [itemIdentifier isEqual: VLCToolbarMediaControl] )
+ {
+ [toolbarItem setLabel:@"Media Controls"];
+ [toolbarItem setPaletteLabel:@"Media Controls"];
+
+ [toolbarItem setView:toolbarMediaControl];
+ [toolbarItem setMinSize:[[toolbarItem view] frame].size];
+ [toolbarItem setMaxSize:[[toolbarItem view] frame].size];
+
+ /* TODO: setup a menu */
+ }
+ else if( [itemIdentifier isEqual: VLCToolbarMediaAudioVolume] )
+ {
+ [toolbarItem setLabel:@"Audio Volume"];
+ [toolbarItem setPaletteLabel:@"Audio Volume"];
+
+ [toolbarItem setView:toolbarMediaAudioVolume];
+ [toolbarItem setMinSize:[[toolbarItem view] frame].size];
+ [toolbarItem setMaxSize:[[toolbarItem view] frame].size];
+
+ /* TODO: setup a menu */
+ }
+ else if( [itemIdentifier isEqual: VLCToolbarMediaDescription] )
+ {
+ [toolbarItem setLabel:@"Media Description"];
+ [toolbarItem setPaletteLabel:@"Media Description"];
+
+ [toolbarItem setView:toolbarMediaDescription];
+ [toolbarItem setMinSize:[[toolbarItem view] frame].size];
+ [toolbarItem setMaxSize:NSMakeSize(10000 /* Can be really big */, NSHeight([[toolbarItem view] frame]))];
+
+ /* TODO: setup a menu */
+ }
+ else
+ {
+ /* itemIdentifier referred to a toolbar item that is not
+ * provided or supported by us or Cocoa
+ * Returning nil will inform the toolbar
+ * that this kind of item is not supported */
+ toolbarItem = nil;
+ }
+ return toolbarItem;
+}
+@end
+
+/******************************************************************************
+ * VLCMainWindowController (CategoriesListDelegate)
+ */
+@implementation VLCMainWindowController (CategoriesListDelegate)
+- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
+{
+ return [[item representedObject] isKindOfClass:[NSDictionary class]];
+}
+- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
+{
+ return !([[item representedObject] isKindOfClass:[NSDictionary class]]);
+}
+- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
+{
+ [cell setRepresentedObject:[item representedObject]];
+}
+@end
+
+/******************************************************************************
+ * VLCMainWindowController (CategoriesListDataSource)
+ */
+@implementation VLCMainWindowController (CategoriesListDataSource)
+/* Drag and drop */
+- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index
+{
+ int i;
+
+ if(![item respondsToSelector:@selector(representedObject)])
+ return NO;
+
+ NSArray *droppedItems = [[info draggingPasteboard] propertyListForType:@"VLCMediaURLType"];
+ if( !droppedItems )
+ droppedItems = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
+ if( !droppedItems )
+ droppedItems = [[info draggingPasteboard] propertyListForType:NSURLPboardType];
+
+ NSAssert( droppedItems, @"Dropped an unsupported object type on the outline View" );
+
+ VLCMediaList * mediaList = [(VLCMedia *)[item representedObject] subitems];
+
+ for (i = 0; i < [droppedItems count]; i++)
+ {
+ NSString * filename = [droppedItems objectAtIndex:i];
+ VLCMedia *media = [VLCMedia mediaWithPath:filename];
+ [mediaList lock];
+ [mediaList insertMedia:media atIndex:index+1];
+ [mediaList unlock];
+ }
+ return YES;
+}
+
+- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
+{
+ NSArray *droppedItems = [[info draggingPasteboard] propertyListForType:@"VLCMediaURLType"];
+ if( !droppedItems )
+ droppedItems = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
+ if( !droppedItems )
+ droppedItems = [[info draggingPasteboard] propertyListForType:NSURLPboardType];
+
+ if(! droppedItems ||
+ ![item respondsToSelector:@selector(representedObject)] ||
+ ![[item representedObject] isKindOfClass:[VLCMedia class]] )
+ {
+ return NSDragOperationNone;
+ }
+
+ return NSDragOperationMove;
+}
+@end
+
+/******************************************************************************
+ * VLCMainWindowController (SplitViewDelegate)
+ */
+@implementation VLCMainWindowController (SplitViewDelegate)
+
+- (void)splitViewWillResizeSubviews:(NSNotification *)aNotification
+{
+ [self willChangeValueForKey:@"navigatorViewVisible"];
+}
+- (void)splitViewDidResizeSubviews:(NSNotification *)aNotification
+{
+ [self didChangeValueForKey:@"navigatorViewVisible"];
+}
+
+@end
NSArray *droppedItems = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
if( !droppedItems )
droppedItems = [[info draggingPasteboard] propertyListForType:NSURLPboardType];
+
+ NSAssert( contentMediaList, @"No contentMediaList" );
+
for (i = 0; i < [droppedItems count]; i++)
{
NSString * filename = [droppedItems objectAtIndex:i];
--- /dev/null
+//
+// VLCMediaLayer.h
+// VLC
+//
+// Created by Pierre d'Herbemont on 1/14/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/QuartzCore.h>
+#import <VLCKit/VLCKit.h>
+
+
+@interface VLCMediaLayer : CALayer {
+ BOOL displayFullInformation;
+ VLCMedia * media;
+ CATextLayer * titleLayer;
+ CATextLayer * artistLayer;
+ CATextLayer * genreLayer;
+ CALayer * artworkLayer;
+}
+
++ (id)layerWithMedia:(VLCMedia *)media;
+
+@property (assign) BOOL displayFullInformation;
+@property (retain,readonly) VLCMedia * media;
+@property (retain,readonly) CATextLayer * titleLayer;
+@property (retain,readonly) CATextLayer * artistLayer;
+@property (retain,readonly) CATextLayer * genreLayer;
+@property (retain,readonly) CALayer * artworkLayer;
+
+@end
--- /dev/null
+//
+// VLCMediaLayer.m
+// VLC
+//
+// Created by Pierre d'Herbemont on 1/14/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import "VLCMediaLayer.h"
+
+/*****************************************************************************
+ * Some configuration first. Defines the size of the artwork layer.
+ */
+static CGSize kArtworkSize = { 256., 256. };
+
+/*****************************************************************************
+ * @interface VLCMediaLayer (Private)
+ */
+
+@interface VLCMediaLayer (Private)
+- (void)updateSublayers;
+@end
+
+/*****************************************************************************
+ * @interface VLCMediaLayer ()
+ */
+@interface VLCMediaLayer ()
+@property (retain,readwrite) VLCMedia * media;
+@property (retain,readwrite) CATextLayer * titleLayer;
+@property (retain,readwrite) CATextLayer * artistLayer;
+@property (retain,readwrite) CATextLayer * genreLayer;
+@property (retain,readwrite) CALayer * artworkLayer;
+@end
+
+/*****************************************************************************
+ * @implementation VLCMediaLayer
+ */
+@implementation VLCMediaLayer
+@synthesize displayFullInformation;
+@synthesize media;
+@synthesize titleLayer;
+@synthesize genreLayer;
+@synthesize artistLayer;
+@synthesize artworkLayer;
+
++ (id)layer
+{
+ return [self layerWithMedia:[VLCMedia mediaAsNodeWithName:@"Empty Media"]];
+}
++ (id)layerWithMedia:(VLCMedia *)aMedia
+{
+ VLCMediaLayer * me = [super layer];
+
+ if(!me) return nil;
+
+ me.media = aMedia;
+ me.displayFullInformation = YES;
+
+ /* Set the default layout */
+ me.titleLayer = [CATextLayer layer];
+ me.artistLayer = [CATextLayer layer];
+ me.genreLayer = [CATextLayer layer];
+ CALayer * textLayer = [CALayer layer];
+ NSDictionary * textStyle = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger:12], @"cornerRadius",
+ [NSValue valueWithSize:NSMakeSize(5, 0)], @"margin",
+ @"Lucida-Bold", @"font",
+ CGColorCreateGenericGray(0.5, 1.),@"foregroundColor",
+ [NSNumber numberWithInteger:18], @"fontSize",
+ [NSNumber numberWithFloat: .8], @"shadowOpacity",
+ [NSNumber numberWithFloat: 1.], @"shadowRadius",
+ kCAAlignmentLeft, @"alignmentMode",
+ nil];
+ NSDictionary * textTitleStyle = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger:12], @"cornerRadius",
+ [NSValue valueWithSize:NSMakeSize(5, 0)], @"margin",
+ @"Lucida", @"font",
+ [NSNumber numberWithInteger:26], @"fontSize",
+ [NSNumber numberWithFloat: .7], @"shadowOpacity",
+ [NSNumber numberWithFloat: 3.], @"shadowRadius",
+ kCAAlignmentLeft, @"alignmentMode",
+ nil];
+ /* First off, text */
+ me.titleLayer.style = textTitleStyle;
+ me.titleLayer.string = @"Title";
+ me.titleLayer.name = @"title";
+ [me.titleLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"superlayer" attribute:kCAConstraintMinX offset:0.]];
+ [me.titleLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMaxX offset:0.]];
+ [me.titleLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinY relativeTo:@"artist" attribute:kCAConstraintMaxY offset:10.]];
+ me.artistLayer.style = textStyle;
+ me.artistLayer.string = @"Artist";
+ me.artistLayer.name = @"artist";
+ [me.artistLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"title" attribute:kCAConstraintMinX]];
+ [me.artistLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"title" attribute:kCAConstraintMaxX]];
+ [me.artistLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]];
+ me.genreLayer.style = textStyle;
+ me.genreLayer.string = @"Genre";
+ me.genreLayer.name = @"genre";
+ [me.genreLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"title" attribute:kCAConstraintMinX]];
+ [me.genreLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"title" attribute:kCAConstraintMaxX]];
+ [me.genreLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxY relativeTo:@"artist" attribute:kCAConstraintMinY offset:-10.]];
+
+
+ [textLayer addSublayer:me.titleLayer];
+ [textLayer addSublayer:me.artistLayer];
+ [textLayer addSublayer:me.genreLayer];
+ textLayer.contentsGravity = kCAGravityCenter;
+ textLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
+
+ /* Empty layer for picture */
+ me.artworkLayer = [CALayer layer];
+ me.artworkLayer.backgroundColor = CGColorCreateGenericGray(0.5, 0.4);
+ me.artworkLayer.borderColor = CGColorCreateGenericRGB(1., 1., 1., .8);
+ me.artworkLayer.borderWidth = 3.0;
+
+ // me.artworkLayer.frame = CGRectMake(0.,0., kArtworkSize.width, kArtworkSize.height);
+ textLayer.frame = CGRectMake(0.,0., kArtworkSize.width, kArtworkSize.height);
+
+ /* Position the text and the artwork layer */
+ CALayer * container = [CALayer layer];
+ me.artworkLayer.name = @"artworkLayer";
+ textLayer.name = @"textLayer";
+ container.name = @"artContainer";
+ container.layoutManager = [CAConstraintLayoutManager layoutManager];
+
+ [container addSublayer:me.artworkLayer];
+ [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"superlayer" attribute:kCAConstraintMinX offset:60.]];
+ [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]];
+ [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintHeight relativeTo:@"superlayer" attribute:kCAConstraintHeight scale:.6 offset:0.]];
+ [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMidX]];
+
+ [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"superlayer" attribute:kCAConstraintMinX]];
+ [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinY relativeTo:@"superlayer" attribute:kCAConstraintMinY]];
+ [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxY relativeTo:@"superlayer" attribute:kCAConstraintMaxY]];
+ [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMaxX]];
+
+ [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"artContainer" attribute:kCAConstraintMaxX]];
+ [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMaxX ]];
+ [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"artContainer" attribute:kCAConstraintMidY]];
+
+ me.artworkLayer.zPosition = -30.f;
+
+ me.artworkLayer.shadowOpacity = .3;
+ me.artworkLayer.shadowRadius = 10.;
+ static CATransform3D rot, projection;
+ static BOOL transformInited = NO;
+ if( !transformInited )
+ {
+ rot = CATransform3DMakeRotation(.1
+ , 0., 1., 0.);
+ projection = CATransform3DIdentity;
+ projection.m34 = 1. / -80.;
+ transformInited = YES;
+ }
+ me.artworkLayer.transform = rot;
+ container.sublayerTransform = projection;
+
+ me.layoutManager = [CAConstraintLayoutManager layoutManager];
+ [me addSublayer:textLayer];
+ [me addSublayer:container];
+
+ [me updateSublayers];
+
+ /* The following will trigger -observeValueForKeyPath: ofObject: change: context: */
+ [me.media addObserver:me forKeyPath:@"metaDictionary.title" options:NSKeyValueObservingOptionNew context:nil];
+ [me.media addObserver:me forKeyPath:@"metaDictionary.genre" options:NSKeyValueObservingOptionNew context:nil];
+ [me.media addObserver:me forKeyPath:@"metaDictionary.artist" options:NSKeyValueObservingOptionNew context:nil];
+ [me.media addObserver:me forKeyPath:@"metaDictionary.artwork" options:NSKeyValueObservingOptionNew context:nil];
+
+ return me;
+}
+
+- (void)dealloc
+{
+ /* Previously registered in +layerWithMediaArrayController: +layerWithMedia:*/
+ [self.media removeObserver:self forKeyPath:@"metaDictionary.title"];
+ [self.media removeObserver:self forKeyPath:@"metaDictionary.genre"];
+ [self.media removeObserver:self forKeyPath:@"metaDictionary.artist"];
+ [self.media removeObserver:self forKeyPath:@"metaDictionary.artwork"];
+
+ [super dealloc];
+}
+@end
+
+/*****************************************************************************
+ * @implementation VLCMediaLayer (Private)
+ */
+@implementation VLCMediaLayer (Private)
+
+- (void)updateSublayers
+{
+ [CATransaction begin];
+ self.titleLayer.string = [self.media.metaDictionary objectForKey:@"title"];
+ NSString * artist = [self.media.metaDictionary objectForKey:@"artist"];
+ self.artistLayer.string = artist ? artist : @"No Artist";
+ NSString * genre = [self.media.metaDictionary objectForKey:@"genre"];
+ self.genreLayer.string = genre ? genre : @"No Genre";
+ if( [self.media.metaDictionary objectForKey:@"artwork"] )
+ {
+ self.artworkLayer.contents = (id)[[self.media.metaDictionary objectForKey:@"artwork"] CGImage];
+ self.artworkLayer.contentsGravity = kCAGravityResizeAspect;
+ self.artworkLayer.borderWidth = 0.;
+ self.artworkLayer.backgroundColor = nil;
+ }
+ [CATransaction commit];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if( [keyPath hasPrefix:@"metaDictionary"] )
+ {
+ [self updateSublayers];
+ return;
+ }
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+}
+@end
--- /dev/null
+//
+// VLCMediaListLayer.h
+// VLC
+//
+// Created by Pierre d'Herbemont on 1/14/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/QuartzCore.h>
+#import <VLCKit/VLCKit.h>
+#import "VLCMediaLayer.h"
+#import "VLCMediaArrayController.h"
+
+
+@interface VLCMediaListLayer : CALayer {
+ NSArray * content;
+ NSUInteger selectedIndex;
+
+ VLCMediaLayer * previousLayer;
+ VLCMediaLayer * selectedLayer;
+ VLCMediaLayer * nextLayer;
+
+ VLCMediaArrayController * controller;
+}
+
++ (id)layer;
++ (id)layerWithMediaArrayController:(VLCMediaArrayController *)aController;
+
+@property (retain,readwrite) NSArray * content;
+@property (readwrite) NSUInteger selectedIndex;
+@property (retain,readwrite) VLCMediaArrayController * controller;
+
+@end
--- /dev/null
+//
+// VLCMediaListLayer.m
+// VLC
+//
+// Created by Pierre d'Herbemont on 1/14/08.
+// Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import "VLCMediaListLayer.h"
+
+/*****************************************************************************
+ * @implementation VLCMediaListLayer
+ */
+
+@interface VLCMediaListLayer (Private)
+- (VLCMediaLayer *)selectedLayer;
+- (VLCMediaLayer *)previousLayer;
+- (VLCMediaLayer *)nextLayer;
+- (void)changeSelectedLayerToNextIndex;
+- (void)changeSelectedLayerToPreviousIndex;
+- (void)resetLayers;
+
+
+- (void)setSelectedLayer:(VLCMediaLayer *)layer;
+- (void)setPreviousLayer:(VLCMediaLayer *)layer;
+- (void)setNextLayer:(VLCMediaLayer *)layer;
+@end
+
+/*****************************************************************************
+ * @implementation VLCMediaListLayer
+ */
+
+@implementation VLCMediaListLayer
+@synthesize selectedIndex;
+@synthesize content;
+@synthesize controller;
+
++ (id)layer
+{
+ VLCMediaListLayer * me = [super layer];
+
+ me.layoutManager = [CAConstraintLayoutManager layoutManager];
+
+ [CATransaction commit];
+
+ me->selectedIndex = NSNotFound;
+ return me;
+}
+
++ (id)layerWithMediaArrayController:(VLCMediaArrayController *)aController
+{
+ VLCMediaListLayer * me = [VLCMediaListLayer layer];
+ me.controller = aController;
+
+ /* The following will trigger -observeValueForKeyPath: ofObject: change: context: */
+ [me.controller addObserver:me forKeyPath:@"arrangedObjects" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
+ [me.controller addObserver:me forKeyPath:@"selectionIndex" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
+ [me.controller addObserver:me forKeyPath:@"contentMediaList" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
+
+ return me;
+}
+
+- (void)dealloc
+{
+ /* Previously registered in +layerWithMediaArrayController: */
+ [self.controller removeObserver:self forKeyPath:@"arrangedObjects"];
+ [self.controller removeObserver:self forKeyPath:@"contentMediaList"];
+ [self.controller removeObserver:self forKeyPath:@"selectionIndex"];
+ [super dealloc];
+}
+@end
+
+/*****************************************************************************
+ * @implementation VLCMediaListLayer (Private)
+ */
+
+@implementation VLCMediaListLayer (Private)
++ (NSSet *)keyPathsForValuesAffectingSelectedLayer
+{
+ return [NSSet setWithObjects:@"selectedLayer", @"content", nil];
+}
+
+- (VLCMediaLayer *)selectedLayer
+{
+ VLCMedia * media = (self.selectedIndex != NSNotFound) ? [self.content objectAtIndex:self.selectedIndex ] : nil;
+ if( !media )
+ {
+ CATextLayer * layer = [CATextLayer layer];
+ CALayer * container = [CALayer layer];
+ container.layoutManager = [CAConstraintLayoutManager layoutManager];
+ if([self.controller.contentMediaList isReadOnly])
+ layer.string = @"Empty";
+ else if ([self.content count])
+ layer.string = @"Empty search.";
+ else
+ layer.string = @"Drag and Drop a movie or a music here.";
+ layer.alignmentMode = kCAAlignmentCenter;
+ layer.wrapped = YES;
+ [layer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]];
+ [layer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidX relativeTo:@"superlayer" attribute:kCAConstraintMidX]];
+ [layer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintWidth relativeTo:@"superlayer" attribute:kCAConstraintWidth]];
+ [container addSublayer:layer];
+ return (VLCMediaLayer *)container;
+ }
+
+ if( [selectedLayer isKindOfClass:[VLCMediaLayer class]] && [media compare:[selectedLayer media]] == NSOrderedSame )
+ return [[selectedLayer retain] autorelease];
+
+ return [VLCMediaLayer layerWithMedia:[self.content objectAtIndex:self.selectedIndex]];
+}
+
+- (VLCMediaLayer *)previousLayer
+{
+ if( self.selectedIndex == NSNotFound )
+ return nil;
+ VLCMedia * media = self.selectedIndex > 0 ? [self.content objectAtIndex:self.selectedIndex - 1] : nil;
+ if( !media )
+ return nil;
+
+ if( [previousLayer isKindOfClass:[VLCMediaLayer class]] && [media compare:[previousLayer media]] == NSOrderedSame )
+ return [[previousLayer retain] autorelease];
+
+ return [VLCMediaLayer layerWithMedia: media ];
+}
+
+- (VLCMediaLayer *)nextLayer
+{
+ if( self.selectedIndex == NSNotFound )
+ return nil;
+ VLCMedia * media = self.selectedIndex + 1 < [content count] ? [self.content objectAtIndex:self.selectedIndex + 1] : nil;
+ if( !media )
+ return nil;
+
+ if( [nextLayer isKindOfClass:[VLCMediaLayer class]] && [media compare:[nextLayer media]] == NSOrderedSame )
+ return [[nextLayer retain] autorelease];
+
+ return [VLCMediaLayer layerWithMedia: media ];
+}
+
+- (void)changeSelectedLayerToNextIndex
+{
+ if(!nextLayer)
+ {
+ /* Can't do anything */
+ return;
+ }
+ selectedIndex++;
+
+ /* Remove offscreen layer. Without actions */
+ if( previousLayer )
+ {
+ [CATransaction begin];
+ [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
+ [previousLayer removeFromSuperlayer];
+ [CATransaction commit];
+ }
+
+ [CATransaction begin];
+ if ( [[NSApp currentEvent] modifierFlags] & NSShiftKeyMask )
+ [CATransaction setValue:[NSNumber numberWithFloat:1.5] forKey:kCATransactionAnimationDuration];
+
+ [self setPreviousLayer: selectedLayer];
+ [self setSelectedLayer: nextLayer];
+ [self setNextLayer: [self nextLayer]];
+ [CATransaction commit];
+
+ /* Move the new nextLayer layer on screen. Without Actions */
+ [CATransaction begin];
+ [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
+ [self addSublayer: nextLayer];
+ [CATransaction commit];
+}
+
+- (void)changeSelectedLayerToPreviousIndex
+{
+ if(!previousLayer)
+ {
+ /* Can't do anything */
+ return;
+ }
+ selectedIndex--;
+
+ /* Remove offscreen layer. Without actions */
+ if( nextLayer )
+ {
+ [CATransaction begin];
+ [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
+ [nextLayer removeFromSuperlayer];
+ [CATransaction commit];
+ }
+
+ [CATransaction begin];
+ if ( [[NSApp currentEvent] modifierFlags] & NSShiftKeyMask )
+ [CATransaction setValue:[NSNumber numberWithFloat:1.5] forKey:kCATransactionAnimationDuration];
+
+ [self setNextLayer: selectedLayer];
+ [self setSelectedLayer: previousLayer];
+ [self setPreviousLayer: [self previousLayer]];
+ [CATransaction commit];
+
+ /* Move the new previous layer on screen. Without Actions */
+ [CATransaction begin];
+ [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions];
+ [self addSublayer:previousLayer];
+ [CATransaction commit];
+}
+
+- (void)gotoIndex:(NSUInteger)index;
+{
+ if( selectedIndex == index )
+ return;
+
+ if( selectedIndex > index )
+ {
+ /* It is ok to scroll five layers */
+ if( selectedIndex - index < 5 )
+ {
+ [self changeSelectedLayerToPreviousIndex];
+ return;
+ }
+ [self changeSelectedLayerToPreviousIndex];
+ [self changeSelectedLayerToPreviousIndex];
+ selectedIndex = index;
+ [self resetLayers];
+ }
+ else
+ {
+ if( index - selectedIndex < 5 )
+ {
+ [self changeSelectedLayerToNextIndex];
+ return;
+ }
+ [self changeSelectedLayerToNextIndex];
+ [self changeSelectedLayerToNextIndex];
+ selectedIndex = index;
+ [self resetLayers];
+ }
+}
+
+- (void)resetLayers
+{
+ VLCMediaLayer * layer;
+ [CATransaction begin];
+ layer = [self previousLayer];
+ if( previousLayer != layer )
+ {
+ if( previousLayer ) [self replaceSublayer:previousLayer with:layer];
+ else [self addSublayer:layer];
+ [self setPreviousLayer:layer];
+ }
+ layer = [self selectedLayer];
+ if( selectedLayer != layer )
+ {
+ if( selectedLayer ) [self replaceSublayer:selectedLayer with:layer];
+ else [self addSublayer:layer];
+ [self setSelectedLayer:layer];
+ }
+ layer = [self nextLayer];
+ if( nextLayer != layer )
+ {
+ if( nextLayer ) [self replaceSublayer:nextLayer with:layer];
+ else [self addSublayer:layer];
+ [self setNextLayer:layer];
+ }
+ [CATransaction commit];
+}
+
+
+- (void)setSelectedLayer:(VLCMediaLayer *)layer
+{
+ [selectedLayer autorelease];
+ if( !layer )
+ {
+ selectedLayer = nil;
+ return;
+ }
+ selectedLayer = [layer retain];
+ selectedLayer.frame = [self bounds];
+ [selectedLayer setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
+}
+
+- (void)setPreviousLayer:(VLCMediaLayer *)layer
+{
+ [previousLayer autorelease];
+ if( !layer )
+ {
+ previousLayer = nil;
+ return;
+ }
+ previousLayer = [layer retain];
+ CGRect frame = [self bounds];
+ frame.origin.x -= frame.size.width;
+ previousLayer.frame = frame;
+ [previousLayer setAutoresizingMask:kCALayerMaxXMargin|kCALayerHeightSizable];
+}
+
+- (void)setNextLayer:(VLCMediaLayer *)layer
+{
+ [nextLayer autorelease];
+ if( !layer )
+ {
+ nextLayer = nil;
+ return;
+ }
+ nextLayer = [layer retain];
+ CGRect frame = [self bounds];
+ frame.origin.x += frame.size.width;
+ nextLayer.frame = frame;
+ [nextLayer setAutoresizingMask:kCALayerMinXMargin|kCALayerHeightSizable];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+ if([keyPath isEqualToString:@"selectionIndex"])
+ {
+ if ( selectedIndex == NSNotFound || [object selectionIndex] == NSNotFound )
+ {
+ selectedIndex = [object selectionIndex];
+ if(selectedIndex == NSNotFound && [content count])
+ {
+ selectedIndex = 0;
+ }
+ [self resetLayers];
+ return;
+ }
+
+ [self gotoIndex: [object selectionIndex]];
+ return;
+ }
+ if([keyPath isEqualToString:@"arrangedObjects"] || [keyPath isEqualToString:@"contentMediaList"])
+ {
+ selectedIndex = [object selectionIndex];
+ if(selectedIndex == NSNotFound && [[object arrangedObjects] count])
+ {
+ selectedIndex = 0;
+ }
+ [content release];
+ content = [[object arrangedObjects] retain];
+ [self resetLayers];
+ return;
+ }
+ [self observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+}
+
+@end
}
@end
+@interface VLCSelectionIndexToDescriptionTransformer : NSValueTransformer {
+}
+@end
+
@end
+@implementation VLCSelectionIndexToDescriptionTransformer
+
++ (Class)transformedValueClass
+{
+ return [NSNumber class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+ return NO;
+}
+
+- (NSString *)transformedValue:(id)value
+{
+ if( ![value isKindOfClass:[NSNumber class]])
+ return @"";
+
+ return [value intValue] == NSNotFound ? @"" : [NSString stringWithFormat:@"%@ of ", value];
+}
+
+@end
+
buildPhases = (
);
dependencies = (
- 632F3CC60D318E3A003BBC56 /* PBXTargetDependency */,
+ 63E930B80D5F43FA006B31CD /* PBXTargetDependency */,
+ 63E930B60D5F43E9006B31CD /* PBXTargetDependency */,
);
name = "vlc-contrib-core-framework-app";
productName = "vlc-contrib-core-framework-app";
buildPhases = (
);
dependencies = (
- 632F3C260D316FAD003BBC56 /* PBXTargetDependency */,
+ 63E930BA0D5F4404006B31CD /* PBXTargetDependency */,
632F3C280D316FB5003BBC56 /* PBXTargetDependency */,
);
name = "vlc-framework-app";
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
- 632F3C380D31711C003BBC56 /* VLCKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 632F3C230D316F37003BBC56 /* VLCKit.framework */; };
632F3E260D326FF0003BBC56 /* pause.png in Resources */ = {isa = PBXBuildFile; fileRef = 632F3E250D326FF0003BBC56 /* pause.png */; };
633BD4BC0D2A90470012A314 /* VLCValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 633BD4AA0D2A90470012A314 /* VLCValueTransformer.m */; };
633BD4BD0D2A90470012A314 /* VLCMediaArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 633BD4AC0D2A90470012A314 /* VLCMediaArrayController.m */; };
633BD4C40D2A90470012A314 /* ImageAndTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 633BD4BA0D2A90470012A314 /* ImageAndTextCell.m */; };
633BD4DA0D2A90C80012A314 /* dialog-error.png in Resources */ = {isa = PBXBuildFile; fileRef = 633BD4D80D2A90C80012A314 /* dialog-error.png */; };
633BD4DB0D2A90C80012A314 /* applications-internet.png in Resources */ = {isa = PBXBuildFile; fileRef = 633BD4D90D2A90C80012A314 /* applications-internet.png */; };
+ 63541FA90D3BA1DB001F6433 /* VLCMediaLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 63541FA80D3BA1DB001F6433 /* VLCMediaLayer.m */; };
+ 635422050D3BE019001F6433 /* VLCMainWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 635422040D3BE019001F6433 /* VLCMainWindowController.m */; };
+ 635424930D3C1394001F6433 /* VLCMediaListLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 635424920D3C1394001F6433 /* VLCMediaListLayer.m */; };
63874B190D25960600F738AD /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 63874B170D25960600F738AD /* MainWindow.xib */; };
638B823B0D35294500128F2B /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 638B823A0D35294500128F2B /* QuickTime.framework */; };
638F47110D216C8F008E4912 /* type_playlist.png in Resources */ = {isa = PBXBuildFile; fileRef = 638F47100D216C8F008E4912 /* type_playlist.png */; };
63E768D80D3507EF00258089 /* fs_volume_slider_bar.png in Resources */ = {isa = PBXBuildFile; fileRef = 63E768BD0D3507EF00258089 /* fs_volume_slider_bar.png */; };
63E768D90D3507EF00258089 /* fs_volume_slider_knob_highlight.png in Resources */ = {isa = PBXBuildFile; fileRef = 63E768BE0D3507EF00258089 /* fs_volume_slider_knob_highlight.png */; };
63E76A530D35225700258089 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E76A520D35225700258089 /* Carbon.framework */; };
+ 63E930C60D5F4463006B31CD /* VLCKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63E930B20D5F430E006B31CD /* VLCKit.framework */; };
8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
- 632F3C220D316F37003BBC56 /* PBXContainerItemProxy */ = {
+ 632F3C270D316FB5003BBC56 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
- containerPortal = 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */;
- proxyType = 2;
- remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
- remoteInfo = VLCKit;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D1107260486CEB800E47090;
+ remoteInfo = VLC;
};
- 632F3C250D316FAD003BBC56 /* PBXContainerItemProxy */ = {
+ 63E930B10D5F430E006B31CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */;
- proxyType = 1;
- remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ proxyType = 2;
+ remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
remoteInfo = VLCKit;
};
- 632F3C270D316FB5003BBC56 /* PBXContainerItemProxy */ = {
+ 63E930B50D5F43E9006B31CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8D1107260486CEB800E47090;
remoteInfo = VLC;
};
- 632F3CC50D318E3A003BBC56 /* PBXContainerItemProxy */ = {
+ 63E930B70D5F43FA006B31CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 633BD6D20D2ADE040012A314;
remoteInfo = "vlc-contrib-core-framework";
};
+ 63E930B90D5F4404006B31CD /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
+ remoteInfo = VLCKit;
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
633BD4BB0D2A90470012A314 /* ImageAndTextCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ImageAndTextCell.h; path = Sources/ImageAndTextCell.h; sourceTree = "<group>"; };
633BD4D80D2A90C80012A314 /* dialog-error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "dialog-error.png"; path = "Icons/dialog-error.png"; sourceTree = "<group>"; };
633BD4D90D2A90C80012A314 /* applications-internet.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "applications-internet.png"; path = "Icons/applications-internet.png"; sourceTree = "<group>"; };
- 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = VLCKit.xcodeproj; path = ../Framework/VLCKit.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = VLCKit.xcodeproj; path = ../framework/VLCKit.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 63541FA70D3BA1DB001F6433 /* VLCMediaLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMediaLayer.h; path = Sources/VLCMediaLayer.h; sourceTree = "<group>"; };
+ 63541FA80D3BA1DB001F6433 /* VLCMediaLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMediaLayer.m; path = Sources/VLCMediaLayer.m; sourceTree = "<group>"; };
+ 635422030D3BE019001F6433 /* VLCMainWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMainWindowController.h; path = Sources/VLCMainWindowController.h; sourceTree = "<group>"; };
+ 635422040D3BE019001F6433 /* VLCMainWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMainWindowController.m; path = Sources/VLCMainWindowController.m; sourceTree = "<group>"; };
+ 635424910D3C1394001F6433 /* VLCMediaListLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMediaListLayer.h; path = Sources/VLCMediaListLayer.h; sourceTree = "<group>"; };
+ 635424920D3C1394001F6433 /* VLCMediaListLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VLCMediaListLayer.m; path = Sources/VLCMediaListLayer.m; sourceTree = "<group>"; };
63874B180D25960600F738AD /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainWindow.xib; sourceTree = "<group>"; };
638B823A0D35294500128F2B /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = "<absolute>"; };
638F47100D216C8F008E4912 /* type_playlist.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = type_playlist.png; path = ../../../modules/gui/qt4/pixmaps/type_playlist.png; sourceTree = SOURCE_ROOT; };
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 632F3C380D31711C003BBC56 /* VLCKit.framework in Frameworks */,
+ 63E930C60D5F4463006B31CD /* VLCKit.framework in Frameworks */,
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
63E380DF0D1C6FD800FD6958 /* QuartzCore.framework in Frameworks */,
63A742B30D2759C1002D41A0 /* ExceptionHandling.framework in Frameworks */,
name = Frameworks;
sourceTree = "<group>";
};
- 632F3C1B0D316F37003BBC56 /* Products */ = {
- isa = PBXGroup;
- children = (
- 632F3C230D316F37003BBC56 /* VLCKit.framework */,
- );
- name = Products;
- sourceTree = "<group>";
- };
633BD4620D2A8DF30012A314 /* Internals */ = {
isa = PBXGroup;
children = (
633BD4B30D2A90470012A314 /* VLCBrowsableVideoView.m */,
63E768810D3503E200258089 /* VLCFullScreenControllerWindow.h */,
63E768820D3503E200258089 /* VLCFullScreenControllerWindow.m */,
+ 63541FA70D3BA1DB001F6433 /* VLCMediaLayer.h */,
+ 63541FA80D3BA1DB001F6433 /* VLCMediaLayer.m */,
+ 635424910D3C1394001F6433 /* VLCMediaListLayer.h */,
+ 635424920D3C1394001F6433 /* VLCMediaListLayer.m */,
);
name = Video;
sourceTree = "<group>";
children = (
633BD4B00D2A90470012A314 /* VLCMainWindow.h */,
633BD4AD0D2A90470012A314 /* VLCMainWindow.m */,
+ 635422030D3BE019001F6433 /* VLCMainWindowController.h */,
+ 635422040D3BE019001F6433 /* VLCMainWindowController.m */,
);
name = "Window Management";
sourceTree = "<group>";
name = FullScreenControllerWindow;
sourceTree = "<group>";
};
+ 63E930AA0D5F430E006B31CD /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 63E930B20D5F430E006B31CD /* VLCKit.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
projectDirPath = "";
projectReferences = (
{
- ProductGroup = 632F3C1B0D316F37003BBC56 /* Products */;
+ ProductGroup = 63E930AA0D5F430E006B31CD /* Products */;
ProjectRef = 633BD69D0D2ACE520012A314 /* VLCKit.xcodeproj */;
},
);
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
- 632F3C230D316F37003BBC56 /* VLCKit.framework */ = {
+ 63E930B20D5F430E006B31CD /* VLCKit.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = VLCKit.framework;
- remoteRef = 632F3C220D316F37003BBC56 /* PBXContainerItemProxy */;
+ remoteRef = 63E930B10D5F430E006B31CD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "if test \"$SYMROOT\" == \"$PROJECT_DIR/build\"\nthen\n\tVLCFRAMEWORK=\"$SRCROOT/../Framework/build/$CONFIGURATION/VLCKit.framework\"\nelse\n\tVLCFRAMEWORK=\"$SYMROOT/$CONFIGURATION/VLCKit.framework\"\nfi\n/Developer/Library/PrivateFrameworks/DevToolsCore.framewo../../../extras/package/macosx/Resources/pbxcp -exclude .DS_Store -exclude CVS -exclude .svn -resolve-src-symlinks $VLCFRAMEWORK $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH\n\n\n";
+ shellScript = "if test \"$SYMROOT\" == \"$PROJECT_DIR/build\"\nthen\n\tVLCFRAMEWORK=\"$SRCROOT/../Framework/build/$CONFIGURATION/VLCKit.framework\"\nelse\n\tVLCFRAMEWORK=\"$SYMROOT/$CONFIGURATION/VLCKit.framework\"\nfi\n/Developer/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp -exclude .DS_Store -exclude CVS -exclude .svn -resolve-src-symlinks $VLCFRAMEWORK $BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH\n\n\n";
};
/* End PBXShellScriptBuildPhase section */
633BD4C30D2A90470012A314 /* VLCAppAdditions.m in Sources */,
633BD4C40D2A90470012A314 /* ImageAndTextCell.m in Sources */,
63E768830D3503E200258089 /* VLCFullScreenControllerWindow.m in Sources */,
+ 63541FA90D3BA1DB001F6433 /* VLCMediaLayer.m in Sources */,
+ 635422050D3BE019001F6433 /* VLCMainWindowController.m in Sources */,
+ 635424930D3C1394001F6433 /* VLCMediaListLayer.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
- 632F3C260D316FAD003BBC56 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- name = VLCKit;
- targetProxy = 632F3C250D316FAD003BBC56 /* PBXContainerItemProxy */;
- };
632F3C280D316FB5003BBC56 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8D1107260486CEB800E47090 /* VLC */;
targetProxy = 632F3C270D316FB5003BBC56 /* PBXContainerItemProxy */;
};
- 632F3CC60D318E3A003BBC56 /* PBXTargetDependency */ = {
+ 63E930B60D5F43E9006B31CD /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D1107260486CEB800E47090 /* VLC */;
+ targetProxy = 63E930B50D5F43E9006B31CD /* PBXContainerItemProxy */;
+ };
+ 63E930B80D5F43FA006B31CD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "vlc-contrib-core-framework";
- targetProxy = 632F3CC50D318E3A003BBC56 /* PBXContainerItemProxy */;
+ targetProxy = 63E930B70D5F43FA006B31CD /* PBXContainerItemProxy */;
+ };
+ 63E930BA0D5F4404006B31CD /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = VLCKit;
+ targetProxy = 63E930B90D5F4404006B31CD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */