-/*****************************************************************************\r
-* eyetv.m: small class to control the notification parts of the EyeTV plugin\r
-*****************************************************************************\r
-* Copyright (C) 2006-2007 the VideoLAN team\r
-* $Id$\r
-*\r
-* Authors: Felix Kühne <fkuehne at videolan dot org>\r
-*\r
-* This program is free software; you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation; either version 2 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* This program is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with this program; if not, write to the Free Software\r
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.\r
-*****************************************************************************/\r
-\r
+/*****************************************************************************
+* eyetv.m: small class to control the notification parts of the EyeTV plugin
+*****************************************************************************
+* Copyright (C) 2006-2011 the VideoLAN team
+* $Id$
+*
+* Authors: Felix Kühne <fkuehne at videolan dot org>
+* Damien Fouilleul <damienf 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 "eyetv.h"
-/* for apple event interaction [carbon] */\r
-#import <ApplicationServices/ApplicationServices.h> \r
+/* for apple event interaction [carbon] */
+//#import <Foundation/NSAppleScript>
/* for various VLC core related calls */
-#import "intf.h"\r
-\r
-@implementation VLCEyeTVController\r
-\r
-static VLCEyeTVController *_o_sharedInstance = nil;\r
-\r
-+ (VLCEyeTVController *)sharedInstance\r
-{\r
- return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];\r
-}\r
-\r
-- (id)init \r
-{\r
- if (_o_sharedInstance) {\r
- [self dealloc];\r
- } else {\r
- _o_sharedInstance = [super init];\r
-\r
- [[NSDistributedNotificationCenter defaultCenter]
- addObserver: self\r
- selector: @selector(globalNotificationReceived:)\r
- name: NULL\r
- object: @"VLCEyeTVSupport"\r
- suspensionBehavior: NSNotificationSuspensionBehaviorDeliverImmediately];\r
- }\r
- \r
- return _o_sharedInstance;\r
-}\r
-\r
-- (void)globalNotificationReceived: (NSNotification *)theNotification\r
-{\r
- msg_Dbg( VLCIntf, "notification received in VLC with name %s and object %s",
- [[theNotification name] UTF8String], [[theNotification object] UTF8String] );\r
-\r
- /* update our info on the used device */\r
- if( [[theNotification name] isEqualToString: @"DeviceAdded"] )\r
- b_deviceConnected = YES;\r
- if( [[theNotification name] isEqualToString: @"DeviceRemoved"] )\r
- b_deviceConnected = NO;\r
-\r
- /* is eyetv running? */\r
- if( [[theNotification name] isEqualToString: @"PluginInit"] )\r
- b_eyeTVactive = YES;\r
- if( [[theNotification name] isEqualToString: @"PluginQuit"] )\r
- b_eyeTVactive = NO;\r
-}\r
-\r
-- (BOOL)isEyeTVrunning\r
-{\r
- return b_eyeTVactive;\r
-}\r
-\r
-- (BOOL)isDeviceConnected\r
-{\r
- return b_deviceConnected;\r
-}\r
-\r
-\r
-- (void)launchEyeTV\r
-{\r
- OSStatus stat;\r
- FSRef eyetvPath;\r
-\r
- stat = LSFindApplicationForInfo ( 'EyTV',\r
- CFSTR("com.elgato.eyetv"),\r
- NULL,\r
- &eyetvPath,\r
- NULL );\r
- if( stat != noErr )\r
- msg_Err( VLCIntf, "finding EyeTV failed with error code %i", (int)stat );\r
- \r
- stat = LSOpenFSRef( &eyetvPath, NULL );\r
- if( stat != noErr )\r
- msg_Err( VLCIntf, "opening EyeTV failed with error code %i", (int)stat );\r
- \r
-}\r
-\r
-- (void)switchChannelUp:(BOOL)b_yesOrNo\r
-{\r
- OSErr err;\r
- AppleEvent ourAE = {typeNull, nil};\r
- AEBuildError theBuildError;\r
- const OSType eyetvSignature = 'EyTV'; /* carbon FOURCC style */\r
- OSType eyetvCommand;\r
- \r
- if( b_yesOrNo == YES )\r
- {\r
- eyetvCommand = 'Chup'; /* same style */\r
- msg_Dbg( VLCIntf, "telling eyetv to switch 1 channel up" );\r
- }\r
- else\r
- {\r
- eyetvCommand = 'Chdn'; /* same style again */\r
- msg_Dbg( VLCIntf, "telling eyetv to switch 1 channel down" );\r
- }\r
- \r
- err = AEBuildAppleEvent(\r
- /* EyeTV script suite */ eyetvSignature,\r
- /* command */ eyetvCommand,\r
- /* signature type */ typeApplSignature,\r
- /* signature */ &eyetvSignature,\r
- /* signature size */ sizeof(eyetvSignature),\r
- /* basic return id */ kAutoGenerateReturnID,\r
- /* generic transaction id */ kAnyTransactionID,\r
- /* to-be-created AE */ &ourAE,\r
- /* get some possible errors */ &theBuildError, \r
- /* got no params for now */ "" );\r
- if( err != aeBuildSyntaxNoErr )\r
- {\r
- msg_Err( VLCIntf, "Error %i encountered while trying to the build the AE to launch eyetv.\n" \\r
- "additionally, the following info was returned: AEBuildErrorCode:%i at pos:%i", \r
- (int)err, theBuildError.fError, theBuildError.fErrorPos);\r
- return;\r
- }\r
- else\r
- msg_Dbg( VLCIntf, "AE created successfully, trying to send now" );\r
- \r
- err = AESendMessage(\r
- /* our AE */ &ourAE,\r
- /* no need for a response-AE */ NULL,\r
- /* we neither want a response nor user interaction */ kAENoReply | kAENeverInteract,\r
- /* we don't need a special time-out */ kAEDefaultTimeout );\r
- if( err != noErr )\r
- msg_Err( VLCIntf, "Error %i encountered while trying to tell EyeTV to switch channel", (int)err );\r
- \r
- err = AEDisposeDesc(&ourAE);\r
-}\r
-\r
-- (void)selectChannel: (int)theChannelNum\r
-{\r
-}\r
-\r
-- (int)getNumberOfChannels\r
-{\r
- return 2;\r
-}\r
-\r
-- (NSString *)getNameOfChannel: (int)theChannelNum\r
-{\r
- return @"dummy name";\r
-}\r
-\r
-@end\r
+#import "intf.h"
+
+@implementation VLCEyeTVController
+
+static VLCEyeTVController *_o_sharedInstance = nil;
+
++ (VLCEyeTVController *)sharedInstance
+{
+ return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
+}
+
+- (id)init
+{
+ if (_o_sharedInstance) {
+ [self dealloc];
+ } else {
+ _o_sharedInstance = [super init];
+
+ [[NSDistributedNotificationCenter defaultCenter]
+ addObserver: self
+ selector: @selector(globalNotificationReceived:)
+ name: NULL
+ object: @"VLCEyeTVSupport"
+ suspensionBehavior: NSNotificationSuspensionBehaviorDeliverImmediately];
+ }
+
+ return _o_sharedInstance;
+}
+
+- (void)globalNotificationReceived: (NSNotification *)theNotification
+{
+ /* update our info on the used device */
+ if( [[theNotification name] isEqualToString: @"DeviceAdded"] )
+ b_deviceConnected = YES;
+ if( [[theNotification name] isEqualToString: @"DeviceRemoved"] )
+ b_deviceConnected = NO;
+
+ /* is eyetv running? */
+ if( [[theNotification name] isEqualToString: @"PluginInit"] )
+ b_eyeTVactive = YES;
+ if( [[theNotification name] isEqualToString: @"PluginQuit"] )
+ b_eyeTVactive = NO;
+}
+
+- (BOOL)isEyeTVrunning
+{
+ return b_eyeTVactive;
+}
+
+- (BOOL)isDeviceConnected
+{
+ return b_deviceConnected;
+}
+
+
+- (void)launchEyeTV
+{
+ NSAppleScript *script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\"\n"
+ "launch with server mode\n"
+ "end tell"];
+ NSDictionary *errorDict;
+ NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&errorDict];
+ if( nil == descriptor )
+ {
+ NSString *errorString = [errorDict objectForKey:NSAppleScriptErrorMessage];
+ NSLog( @"opening EyeTV failed with error status '%@'", errorString );
+ }
+ [script release];
+}
+
+- (int)currentChannel
+{
+ int currentChannel = 0;
+ NSAppleScript *script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\" to get current channel"];
+ NSDictionary *errorDict;
+ NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&errorDict];
+ if( nil == descriptor )
+ {
+ NSString *errorString = [errorDict objectForKey:NSAppleScriptErrorMessage];
+ NSLog( @"EyeTV channel inventory failed with error status '%@'", errorString );
+ }
+ else
+ {
+ currentChannel = (int)[descriptor int32Value];
+ }
+ [script release];
+ return currentChannel;
+}
+
+- (int)switchChannelUp:(BOOL)b_yesOrNo
+{
+ int currentChannel = 0;
+ NSAppleScript *script;
+ NSDictionary *errorDict;
+ NSAppleEventDescriptor *descriptor;
+
+ if( b_yesOrNo == YES )
+ {
+ script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\"\n"
+ "channel_up\n"
+ "get current channel\n"
+ "end tell"];
+ NSLog( @"telling eyetv to switch 1 channel up" );
+ }
+ else
+ {
+ script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\"\n"
+ "channel_down\n"
+ "get current channel\n"
+ "end tell"];
+ NSLog( @"telling eyetv to switch 1 channel down" );
+ }
+
+ descriptor = [script executeAndReturnError:&errorDict];
+ if( nil == descriptor )
+ {
+ NSString *errorString = [errorDict objectForKey:NSAppleScriptErrorMessage];
+ NSLog( @"EyeTV channel change failed with error status '%@'", errorString );
+ }
+ else
+ {
+ currentChannel = (int)[descriptor int32Value];
+ }
+ [script release];
+ return currentChannel;
+}
+
+- (void)selectChannel: (int)theChannelNum
+{
+ NSAppleScript *script;
+ switch( theChannelNum )
+ {
+ case -2: // Composite
+ script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\"\n"
+ " input_change input source composite video input\n"
+ " show player_window\n"
+ "end tell"];
+ break;
+ case -1: // S-Video
+ script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\"\n"
+ " input_change input source S video input\n"
+ " show player_window\n"
+ "end tell"];
+ break;
+ case 0: // Last
+ script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\"\n"
+ " show player_window\n"
+ "end tell"];
+ break;
+ default:
+ if( theChannelNum > 0 )
+ {
+ NSString *channel_change = [NSString stringWithFormat:
+ @"tell application \"EyeTV\"\n"
+ " channel_change channel number %d\n"
+ " show player_window\n"
+ "end tell", theChannelNum];
+ script = [[NSAppleScript alloc] initWithSource:channel_change];
+ }
+ else
+ return;
+ }
+ NSDictionary *errorDict;
+ NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&errorDict];
+ if( nil == descriptor )
+ {
+ NSString *errorString = [errorDict objectForKey:NSAppleScriptErrorMessage];
+ NSLog( @"EyeTV source change failed with error status '%@'", errorString );
+ }
+ [script release];
+}
+
+- (NSEnumerator *)allChannels
+{
+ NSEnumerator *channels = nil;
+ NSAppleScript *script = [[NSAppleScript alloc] initWithSource:
+ @"tell application \"EyeTV\" to get name of every channel"];
+ NSDictionary *errorDict;
+ NSAppleEventDescriptor *descriptor = [script executeAndReturnError:&errorDict];
+ if( nil == descriptor )
+ {
+ NSString *errorString = [errorDict objectForKey:NSAppleScriptErrorMessage];
+ NSLog( @"EyeTV channel inventory failed with error status '%@'", errorString );
+ }
+ else
+ {
+ int count = [descriptor numberOfItems];
+ int x=0;
+ NSMutableArray *channelArray = [NSMutableArray arrayWithCapacity:count];
+ while( x++ < count ) {
+ [channelArray addObject:[[descriptor descriptorAtIndex:x] stringValue]];
+ }
+ channels = [channelArray objectEnumerator];
+ }
+ [script release];
+ return channels;
+}
+
+@end