Commit 1be7b761 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Fix line breaks

parent 8fd6167a
/*****************************************************************************
* 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;
}
/*****************************************************************************
* 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: