-/*****************************************************************************\r
- * eyetv.c : Access module to connect to our plugin running within EyeTV\r
- *****************************************************************************\r
- * Copyright (C) 2006-2007 the VideoLAN team\r
- * $Id$\r
- *\r
- * Author: 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
-/*****************************************************************************\r
- * Preamble\r
- *****************************************************************************/\r
-#include <stdlib.h>\r
-\r
-#include <vlc/vlc.h>\r
-#include <vlc_access.h>\r
-\r
-#include <CoreFoundation/CoreFoundation.h>\r
-\r
-/* TODO:\r
- * watch for PluginQuit or DeviceRemoved to stop output to VLC's core then */\r
-\r
-/*****************************************************************************\r
- * Module descriptior\r
- *****************************************************************************/\r
-static int Open ( vlc_object_t * );\r
-static void Close( vlc_object_t * );\r
-\r
-vlc_module_begin();\r
- set_shortname( "EyeTV" );\r
- set_description( _("EyeTV access module") );\r
- set_category( CAT_INPUT );\r
- set_subcategory( SUBCAT_INPUT_ACCESS );\r
-\r
- set_capability( "access2", 0 );\r
- add_shortcut( "eyetv" );\r
- set_callbacks( Open, Close );\r
-vlc_module_end();\r
-\r
-/*****************************************************************************\r
- * Access: local prototypes\r
- *****************************************************************************/\r
-typedef struct\r
-{\r
- VLC_COMMON_MEMBERS\r
- \r
- vlc_mutex_t lock;\r
- vlc_cond_t wait;\r
- \r
- CFMessagePortRef inputMessagePortFromEyeTV;\r
-} eyetv_thread_t;\r
-\r
-struct access_sys_t\r
-{\r
- eyetv_thread_t *p_thread;\r
-};\r
-\r
-CFDataRef dataFromEyetv;\r
-int lastPacketId;\r
-int lastForwardedPacketId;\r
-\r
-static int Read( access_t *, uint8_t *, int );\r
-static int Control( access_t *, int, va_list );\r
-static void Thread( vlc_object_t * );\r
-CFDataRef msgPortCallback( CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info );\r
-\r
-/*****************************************************************************\r
- * Open: sets up the module and its threads\r
- *****************************************************************************/\r
-static int Open( vlc_object_t *p_this )\r
-{\r
- access_t *p_access = (access_t *)p_this;\r
- access_sys_t *p_sys;\r
- eyetv_thread_t *p_thread;\r
- CFMessagePortContext context;\r
- memset(&context, 0, sizeof(context)); \r
- \r
- /* Init p_access */\r
- access_InitFields( p_access ); \\r
- ACCESS_SET_CALLBACKS( Read, NULL, Control, NULL ); \\r
- MALLOC_ERR( p_access->p_sys, access_sys_t ); \\r
- p_sys = p_access->p_sys; memset( p_sys, 0, sizeof( access_sys_t ) );\r
-\r
- msg_Dbg( p_access, "coming up" );\r
-\r
- /* create receiving thread which will keep the message port alive without blocking */\r
- p_sys->p_thread = p_thread = vlc_object_create( p_access, sizeof( eyetv_thread_t ) );\r
- vlc_object_attach( p_thread, p_this );\r
- vlc_mutex_init( p_access, &p_thread->lock );\r
- vlc_cond_init( p_access, &p_thread->wait );\r
- msg_Dbg( p_access, "thread created, msg port following now" );\r
- \r
- /* set up our own msg port\r
- * we may give the msgport such a generic name, because EyeTV may only run\r
- * once per entire machine, so we can't interfere with other instances.\r
- * we just trust the user no to launch multiple VLC instances trying to \r
- * access EyeTV at the same time. If this happens, the latest launched\r
- * instance will win. */\r
- p_sys->p_thread->inputMessagePortFromEyeTV = CFMessagePortCreateLocal( kCFAllocatorDefault,\r
- CFSTR("VLCEyeTVMsgPort"),\r
- &msgPortCallback,\r
- &context,\r
- /* no info to free */ NULL );\r
- if( p_sys->p_thread->inputMessagePortFromEyeTV == NULL )\r
- {\r
- msg_Err( p_access, "opening local msg port failed" );\r
- free( p_sys->p_thread->inputMessagePortFromEyeTV );\r
- vlc_mutex_destroy( &p_thread->lock );\r
- vlc_cond_destroy( &p_thread->wait );\r
- vlc_object_detach( p_thread );\r
- vlc_object_destroy( p_thread );\r
- free( p_sys );\r
- return VLC_EGENERIC;\r
- }\r
- else\r
- msg_Dbg( p_access, "remote msg port opened" );\r
- \r
- /* let the thread run */\r
- if( vlc_thread_create( p_thread, "EyeTV Receiver Thread", Thread,\r
- VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )\r
- {\r
- msg_Err( p_access, "couldn't launch eyetv receiver thread" );\r
- vlc_mutex_destroy( &p_thread->lock );\r
- vlc_cond_destroy( &p_thread->wait );\r
- vlc_object_detach( p_thread );\r
- vlc_object_destroy( p_thread );\r
- free( p_sys );\r
- return VLC_EGENERIC;\r
- }\r
-\r
- msg_Dbg( p_access, "receiver thread created and launched" );\r
- \r
- /* tell the EyeTV plugin to open up its msg port and start sending */\r
- CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),\r
- CFSTR("VLCAccessStartDataSending"), \r
- CFSTR("VLCEyeTVSupport"), \r
- /*userInfo*/ NULL, \r
- TRUE );\r
- \r
- msg_Dbg( p_access, "plugin notified" );\r
- \r
- /* we don't need such a high priority */\r
- //vlc_thread_set_priority( p_access, VLC_THREAD_PRIORITY_LOW );\r
- \r
- return VLC_SUCCESS;\r
-}\r
-\r
-/*****************************************************************************\r
- * Close: closes msg-port, free resources\r
- *****************************************************************************/\r
-static void Close( vlc_object_t *p_this )\r
-{\r
- access_t *p_access = (access_t *)p_this;\r
- access_sys_t *p_sys = p_access->p_sys;\r
- \r
- msg_Dbg( p_access, "closing" );\r
- \r
- /* tell the EyeTV plugin to close its msg port and stop sending */\r
- CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),\r
- CFSTR("VLCAccessStopDataSending"), \r
- CFSTR("VLCEyeTVSupport"), \r
- /*userInfo*/ NULL, \r
- TRUE );\r
- \r
- msg_Dbg( p_access, "plugin notified" );\r
- \r
- /* stop receiver thread */\r
- p_sys->p_thread->b_die = VLC_TRUE;\r
- vlc_mutex_lock( &p_sys->p_thread->lock );\r
- vlc_cond_signal( &p_sys->p_thread->wait );\r
- vlc_mutex_unlock( &p_sys->p_thread->lock );\r
- vlc_thread_join( p_sys->p_thread );\r
- \r
- /* close msg port */\r
- CFMessagePortInvalidate( p_sys->p_thread->inputMessagePortFromEyeTV );\r
- free( p_sys->p_thread->inputMessagePortFromEyeTV );\r
- msg_Dbg( p_access, "msg port closed and freed" );\r
- \r
- /* free thread */\r
- vlc_mutex_destroy( &p_sys->p_thread->lock );\r
- vlc_cond_destroy( &p_sys->p_thread->wait );\r
- vlc_object_detach( p_sys->p_thread );\r
- vlc_object_destroy( p_sys->p_thread );\r
- \r
- free( p_sys );\r
-}\r
-\r
-static void Thread( vlc_object_t *p_this )\r
-{\r
- eyetv_thread_t *p_thread= (eyetv_thread_t*)p_this;\r
- CFRunLoopSourceRef runLoopSource;\r
- \r
- /* create our run loop source for the port and attach it to our current loop */\r
- runLoopSource = CFMessagePortCreateRunLoopSource( kCFAllocatorDefault,\r
- p_thread->inputMessagePortFromEyeTV,\r
- 0 );\r
- CFRunLoopAddSource( CFRunLoopGetCurrent(),\r
- runLoopSource,\r
- kCFRunLoopDefaultMode );\r
- \r
- CFRunLoopRun();\r
-}\r
-\r
-\r
-/*****************************************************************************\r
-* msgPortCallback: receives data from the EyeTV plugin\r
-*****************************************************************************/\r
-CFDataRef msgPortCallback( CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info )\r
-{\r
- extern CFDataRef dataFromEyetv;\r
- extern int lastPacketId;\r
- \r
- /* copy callback data to module data */\r
- dataFromEyetv = CFDataCreateCopy( kCFAllocatorDefault, data );\r
-#if 0\r
- printf( "packet %i contained %i bytes, forwarding %i bytes\n",\r
- (int)msgid,\r
- (int)CFDataGetLength( data ),\r
- (int)CFDataGetLength( dataFromEyetv ) );\r
-#endif\r
-\r
- lastPacketId = msgid;\r
- \r
- return NULL; /* we've got nothing to return */\r
-}\r
-\r
-/*****************************************************************************\r
-* Read: forwarding data from EyeTV plugin which was received above\r
-*****************************************************************************/\r
-static int Read( access_t *p_access, uint8_t *p_buffer, int i_len )\r
-{\r
- access_sys_t *p_sys = p_access->p_sys;\r
- extern CFDataRef dataFromEyetv;\r
- extern int lastPacketId;\r
- extern int lastForwardedPacketId;\r
- \r
- /* wait for a new buffer before forwarding */\r
- while( lastPacketId == lastForwardedPacketId && !p_access->b_die )\r
- {\r
- msleep( INPUT_ERROR_SLEEP );\r
- }\r
- \r
- /* read data here, copy it to p_buffer, fill i_len with respective length\r
- * and return info with i_read; i_read = 0 == EOF */\r
- if( dataFromEyetv )\r
- {\r
- CFDataGetBytes( dataFromEyetv,\r
- CFRangeMake( 0, CFDataGetLength( dataFromEyetv ) ),\r
- (uint8_t *)p_buffer );\r
- i_len = (int)CFDataGetLength( dataFromEyetv );\r
-#if 0\r
- msg_Dbg( p_access, "%i bytes with id %i received in read function, pushing to core",\r
- (int)CFDataGetLength( dataFromEyetv ), lastPacketId );\r
-#endif\r
- lastForwardedPacketId = lastPacketId;\r
- if( i_len == 0)\r
- {\r
- msg_Err( p_access, "you looosed!" );\r
- return 0;\r
- }\r
- }\r
- \r
- if( p_access->b_die )\r
- return 0;\r
- \r
- return i_len;\r
-}\r
-\r
-/*****************************************************************************\r
- * Control:\r
- *****************************************************************************/\r
-static int Control( access_t *p_access, int i_query, va_list args )\r
-{/*\r
- vlc_bool_t *pb_bool;\r
- int *pi_int;\r
- int64_t *pi_64;\r
- \r
- switch( i_query )\r
- {\r
- * *\r
- case ACCESS_SET_PAUSE_STATE:\r
- * Nothing to do *\r
- break;\r
-\r
- case ACCESS_CAN_SEEK:\r
- case ACCESS_CAN_FASTSEEK:\r
- case ACCESS_CAN_PAUSE:\r
- case ACCESS_CAN_CONTROL_PACE:\r
- case ACCESS_GET_MTU:\r
- case ACCESS_GET_PTS_DELAY: \r
- case ACCESS_GET_TITLE_INFO:\r
- case ACCESS_SET_TITLE:\r
- case ACCESS_SET_SEEKPOINT:\r
- case ACCESS_SET_PRIVATE_ID_STATE:\r
- return VLC_EGENERIC;\r
- \r
- default:\r
- msg_Warn( p_access, "unimplemented query in control" );\r
- return VLC_EGENERIC;\r
- \r
- }\r
- return VLC_SUCCESS;*/\r
- return VLC_EGENERIC;\r
-}\r
+/*****************************************************************************
+ * eyetv.c : Access module to connect to our plugin running within EyeTV
+ *****************************************************************************
+ * Copyright (C) 2006-2007 the VideoLAN team
+ * $Id$
+ *
+ * Author: 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+
+#include <vlc/vlc.h>
+#include <vlc_access.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+/* TODO:
+ * watch for PluginQuit or DeviceRemoved to stop output to VLC's core then */
+
+/*****************************************************************************
+ * Module descriptior
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+
+vlc_module_begin();
+ set_shortname( "EyeTV" );
+ set_description( _("EyeTV access module") );
+ set_category( CAT_INPUT );
+ set_subcategory( SUBCAT_INPUT_ACCESS );
+
+ set_capability( "access2", 0 );
+ add_shortcut( "eyetv" );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * Access: local prototypes
+ *****************************************************************************/
+typedef struct
+{
+ VLC_COMMON_MEMBERS
+
+ vlc_mutex_t lock;
+ vlc_cond_t wait;
+
+ CFMessagePortRef inputMessagePortFromEyeTV;
+} eyetv_thread_t;
+
+struct access_sys_t
+{
+ eyetv_thread_t *p_thread;
+};
+
+CFDataRef dataFromEyetv;
+int lastPacketId;
+int lastForwardedPacketId;
+
+static int Read( access_t *, uint8_t *, int );
+static int Control( access_t *, int, va_list );
+static void Thread( vlc_object_t * );
+CFDataRef msgPortCallback( CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info );
+
+/*****************************************************************************
+ * Open: sets up the module and its threads
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ access_t *p_access = (access_t *)p_this;
+ access_sys_t *p_sys;
+ eyetv_thread_t *p_thread;
+ CFMessagePortContext context;
+ memset(&context, 0, sizeof(context));
+
+ /* Init p_access */
+ access_InitFields( p_access ); \
+ ACCESS_SET_CALLBACKS( Read, NULL, Control, NULL ); \
+ MALLOC_ERR( p_access->p_sys, access_sys_t ); \
+ p_sys = p_access->p_sys; memset( p_sys, 0, sizeof( access_sys_t ) );
+
+ msg_Dbg( p_access, "coming up" );
+
+ /* create receiving thread which will keep the message port alive without blocking */
+ p_sys->p_thread = p_thread = vlc_object_create( p_access, sizeof( eyetv_thread_t ) );
+ vlc_object_attach( p_thread, p_this );
+ vlc_mutex_init( p_access, &p_thread->lock );
+ vlc_cond_init( p_access, &p_thread->wait );
+ msg_Dbg( p_access, "thread created, msg port following now" );
+
+ /* set up our own msg port
+ * we may give the msgport such a generic name, because EyeTV may only run
+ * once per entire machine, so we can't interfere with other instances.
+ * we just trust the user no to launch multiple VLC instances trying to
+ * access EyeTV at the same time. If this happens, the latest launched
+ * instance will win. */
+ p_sys->p_thread->inputMessagePortFromEyeTV = CFMessagePortCreateLocal( kCFAllocatorDefault,
+ CFSTR("VLCEyeTVMsgPort"),
+ &msgPortCallback,
+ &context,
+ /* no info to free */ NULL );
+ if( p_sys->p_thread->inputMessagePortFromEyeTV == NULL )
+ {
+ msg_Err( p_access, "opening local msg port failed" );
+ free( p_sys->p_thread->inputMessagePortFromEyeTV );
+ vlc_mutex_destroy( &p_thread->lock );
+ vlc_cond_destroy( &p_thread->wait );
+ vlc_object_detach( p_thread );
+ vlc_object_destroy( p_thread );
+ free( p_sys );
+ return VLC_EGENERIC;
+ }
+ else
+ msg_Dbg( p_access, "remote msg port opened" );
+
+ /* let the thread run */
+ if( vlc_thread_create( p_thread, "EyeTV Receiver Thread", Thread,
+ VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
+ {
+ msg_Err( p_access, "couldn't launch eyetv receiver thread" );
+ vlc_mutex_destroy( &p_thread->lock );
+ vlc_cond_destroy( &p_thread->wait );
+ vlc_object_detach( p_thread );
+ vlc_object_destroy( p_thread );
+ free( p_sys );
+ return VLC_EGENERIC;
+ }
+
+ msg_Dbg( p_access, "receiver thread created and launched" );
+
+ /* tell the EyeTV plugin to open up its msg port and start sending */
+ CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),
+ CFSTR("VLCAccessStartDataSending"),
+ CFSTR("VLCEyeTVSupport"),
+ /*userInfo*/ NULL,
+ TRUE );
+
+ msg_Dbg( p_access, "plugin notified" );
+
+ /* we don't need such a high priority */
+ //vlc_thread_set_priority( p_access, VLC_THREAD_PRIORITY_LOW );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close: closes msg-port, free resources
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ access_t *p_access = (access_t *)p_this;
+ access_sys_t *p_sys = p_access->p_sys;
+
+ msg_Dbg( p_access, "closing" );
+
+ /* tell the EyeTV plugin to close its msg port and stop sending */
+ CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),
+ CFSTR("VLCAccessStopDataSending"),
+ CFSTR("VLCEyeTVSupport"),
+ /*userInfo*/ NULL,
+ TRUE );
+
+ msg_Dbg( p_access, "plugin notified" );
+
+ /* stop receiver thread */
+ p_sys->p_thread->b_die = VLC_TRUE;
+ vlc_mutex_lock( &p_sys->p_thread->lock );
+ vlc_cond_signal( &p_sys->p_thread->wait );
+ vlc_mutex_unlock( &p_sys->p_thread->lock );
+ vlc_thread_join( p_sys->p_thread );
+
+ /* close msg port */
+ CFMessagePortInvalidate( p_sys->p_thread->inputMessagePortFromEyeTV );
+ free( p_sys->p_thread->inputMessagePortFromEyeTV );
+ msg_Dbg( p_access, "msg port closed and freed" );
+
+ /* free thread */
+ vlc_mutex_destroy( &p_sys->p_thread->lock );
+ vlc_cond_destroy( &p_sys->p_thread->wait );
+ vlc_object_detach( p_sys->p_thread );
+ vlc_object_destroy( p_sys->p_thread );
+
+ free( p_sys );
+}
+
+static void Thread( vlc_object_t *p_this )
+{
+ eyetv_thread_t *p_thread= (eyetv_thread_t*)p_this;
+ CFRunLoopSourceRef runLoopSource;
+
+ /* create our run loop source for the port and attach it to our current loop */
+ runLoopSource = CFMessagePortCreateRunLoopSource( kCFAllocatorDefault,
+ p_thread->inputMessagePortFromEyeTV,
+ 0 );
+ CFRunLoopAddSource( CFRunLoopGetCurrent(),
+ runLoopSource,
+ kCFRunLoopDefaultMode );
+
+ CFRunLoopRun();
+}
+
+
+/*****************************************************************************
+* msgPortCallback: receives data from the EyeTV plugin
+*****************************************************************************/
+CFDataRef msgPortCallback( CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info )
+{
+ extern CFDataRef dataFromEyetv;
+ extern int lastPacketId;
+
+ /* copy callback data to module data */
+ dataFromEyetv = CFDataCreateCopy( kCFAllocatorDefault, data );
+#if 0
+ printf( "packet %i contained %i bytes, forwarding %i bytes\n",
+ (int)msgid,
+ (int)CFDataGetLength( data ),
+ (int)CFDataGetLength( dataFromEyetv ) );
+#endif
+
+ lastPacketId = msgid;
+
+ return NULL; /* we've got nothing to return */
+}
+
+/*****************************************************************************
+* Read: forwarding data from EyeTV plugin which was received above
+*****************************************************************************/
+static int Read( access_t *p_access, uint8_t *p_buffer, int i_len )
+{
+ access_sys_t *p_sys = p_access->p_sys;
+ extern CFDataRef dataFromEyetv;
+ extern int lastPacketId;
+ extern int lastForwardedPacketId;
+
+ /* wait for a new buffer before forwarding */
+ while( lastPacketId == lastForwardedPacketId && !p_access->b_die )
+ {
+ msleep( INPUT_ERROR_SLEEP );
+ }
+
+ /* read data here, copy it to p_buffer, fill i_len with respective length
+ * and return info with i_read; i_read = 0 == EOF */
+ if( dataFromEyetv )
+ {
+ CFDataGetBytes( dataFromEyetv,
+ CFRangeMake( 0, CFDataGetLength( dataFromEyetv ) ),
+ (uint8_t *)p_buffer );
+ i_len = (int)CFDataGetLength( dataFromEyetv );
+#if 0
+ msg_Dbg( p_access, "%i bytes with id %i received in read function, pushing to core",
+ (int)CFDataGetLength( dataFromEyetv ), lastPacketId );
+#endif
+ lastForwardedPacketId = lastPacketId;
+ if( i_len == 0)
+ {
+ msg_Err( p_access, "you looosed!" );
+ return 0;
+ }
+ }
+
+ if( p_access->b_die )
+ return 0;
+
+ return i_len;
+}
+
+/*****************************************************************************
+ * Control:
+ *****************************************************************************/
+static int Control( access_t *p_access, int i_query, va_list args )
+{/*
+ vlc_bool_t *pb_bool;
+ int *pi_int;
+ int64_t *pi_64;
+
+ switch( i_query )
+ {
+ * *
+ case ACCESS_SET_PAUSE_STATE:
+ * Nothing to do *
+ break;
+
+ case ACCESS_CAN_SEEK:
+ case ACCESS_CAN_FASTSEEK:
+ case ACCESS_CAN_PAUSE:
+ case ACCESS_CAN_CONTROL_PACE:
+ case ACCESS_GET_MTU:
+ case ACCESS_GET_PTS_DELAY:
+ case ACCESS_GET_TITLE_INFO:
+ case ACCESS_SET_TITLE:
+ case ACCESS_SET_SEEKPOINT:
+ case ACCESS_SET_PRIVATE_ID_STATE:
+ return VLC_EGENERIC;
+
+ default:
+ msg_Warn( p_access, "unimplemented query in control" );
+ return VLC_EGENERIC;
+
+ }
+ return VLC_SUCCESS;*/
+ return VLC_EGENERIC;
+}