Commit 36868ee9 authored by Damien Fouilleul's avatar Damien Fouilleul

eyetv: latest version of EyeTV capture plugin, needs lotta testing

parent 5266ede1
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
#include "eyetvplugin.h" #include "eyetvplugin.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define MAX_PIDS 256 #define MAX_PIDS 256
#define MAX_ACTIVE_PIDS 256 #define MAX_ACTIVE_PIDS 256
#define MAX_DEVICES 16 #define MAX_DEVICES 16
...@@ -31,11 +36,9 @@ ...@@ -31,11 +36,9 @@
#pragma push #pragma push
#pragma pack(1) #pragma pack(1)
/* Structure for TS-Packets */
typedef struct typedef struct
{ {
unsigned long sync_byte : 8, uint32_t sync_byte : 8,
transport_error_indicator : 1, transport_error_indicator : 1,
payload_unit_start_indicator : 1, payload_unit_start_indicator : 1,
transport_priority : 1, transport_priority : 1,
...@@ -43,73 +46,32 @@ typedef struct ...@@ -43,73 +46,32 @@ typedef struct
transport_scrambling_control : 2, transport_scrambling_control : 2,
adaptation_field_control : 2, adaptation_field_control : 2,
continuity_counter : 4; continuity_counter : 4;
} TransportStreamHeader;
unsigned char data[188-4]; /* Structure for TS-Packets */
} TransportStreamPacket;
#pragma pop
/* Structure to hold Information on devices */
typedef struct typedef struct
{ {
EyeTVPluginDeviceID deviceID; TransportStreamHeader header;
EyeTVPluginDeviceType deviceType; uint8_t payload[184];
long headendID;
long transponderID;
long serviceID;
long pidsCount;
long pids[MAX_PIDS];
EyeTVPluginPIDInfo activePIDs[MAX_ACTIVE_PIDS]; } TransportStreamPacket;
long activePIDsCount;
} DeviceInfo; #pragma pop
/* Structure to hold global data to communicate with EyeTV */ /* Structure to hold global data to communicate with EyeTV */
typedef struct typedef struct
{ {
EyeTVPluginCallbackProc callback; EyeTVPluginCallbackProc callback;
long deviceCount; /* Structure to hold current active service */
DeviceInfo devices[MAX_DEVICES]; EyeTVPluginDeviceID activeDeviceID;
long long packetCount; long activePIDsCount;
EyeTVPluginPIDInfo activePIDs[MAX_ACTIVE_PIDS];
long seenPIDs[MAX_ACTIVE_PIDS];
} VLCEyeTVPluginGlobals_t; } VLCEyeTVPluginGlobals_t;
/* 2nd structure to store our own global data which isn't shared with EyeTV static int i_deviceCount;
* a bit empty at the moment, but it will get larger as development progresses */ static int vlcSock;
typedef struct
{
int i_deviceCount;
CFMessagePortRef messagePortToVLC;
bool b_msgPortOpen;
} VLCEyeTVPluginOwnGlobals_t;
VLCEyeTVPluginOwnGlobals_t *nativeGlobals;
/* return the DeviceInfo with ID deviceID */
static DeviceInfo *GetDeviceInfo(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID)
{
int i;
if( globals )
{
for( i=0; i<globals->deviceCount; i++)
{
if( globals->devices[i].deviceID == deviceID )
{
return &globals->devices[i];
}
}
}
return NULL;
}
#pragma mark - #pragma mark -
...@@ -120,8 +82,8 @@ static long VLCEyeTVPluginInitialize(VLCEyeTVPluginGlobals_t** globals, long api ...@@ -120,8 +82,8 @@ static long VLCEyeTVPluginInitialize(VLCEyeTVPluginGlobals_t** globals, long api
long result = 0; long result = 0;
/* init our own storage */ /* init our own storage */
extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals; i_deviceCount = 0;
nativeGlobals = malloc( sizeof( VLCEyeTVPluginOwnGlobals_t ) ); vlcSock = -1;
/* notify a potential VLC instance about our initialisation */ /* notify a potential VLC instance about our initialisation */
CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(), CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),
...@@ -147,12 +109,10 @@ static long VLCEyeTVPluginInitialize(VLCEyeTVPluginGlobals_t** globals, long api ...@@ -147,12 +109,10 @@ static long VLCEyeTVPluginInitialize(VLCEyeTVPluginGlobals_t** globals, long api
/* we will be terminated soon, clean up */ /* we will be terminated soon, clean up */
static long VLCEyeTVPluginTerminate(VLCEyeTVPluginGlobals_t *globals) static long VLCEyeTVPluginTerminate(VLCEyeTVPluginGlobals_t *globals)
{ {
extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals; long result = 0;
printf("VLC media player Plug-In: Terminate\n"); printf("VLC media player Plug-In: Terminate\n");
long result = 0;
/* notify a potential VLC instance about our termination */ /* notify a potential VLC instance about our termination */
CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (), CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),
CFSTR("PluginQuit"), CFSTR("PluginQuit"),
...@@ -164,24 +124,23 @@ static long VLCEyeTVPluginTerminate(VLCEyeTVPluginGlobals_t *globals) ...@@ -164,24 +124,23 @@ static long VLCEyeTVPluginTerminate(VLCEyeTVPluginGlobals_t *globals)
CFNotificationCenterRemoveEveryObserver( CFNotificationCenterGetDistributedCenter(), CFNotificationCenterRemoveEveryObserver( CFNotificationCenterGetDistributedCenter(),
(void *)VLCEyeTVPluginGlobalNotificationReceived ); (void *)VLCEyeTVPluginGlobalNotificationReceived );
/* invalidate and free msg port */ /* close data connection */
if( nativeGlobals->messagePortToVLC ) if( vlcSock != -1 )
{ {
CFMessagePortInvalidate( nativeGlobals->messagePortToVLC ); close( vlcSock );
free( nativeGlobals->messagePortToVLC ); vlcSock = -1;
printf( "msgport invalidated and freed\n" );
} }
else
printf( "no msgport to free\n" );
if( globals ) if( globals )
{ {
long i;
for( i=0; i<globals->activePIDsCount; ++i )
{
printf("activePID: %ld, count=%ld\n", globals->activePIDs[i].pid, globals->seenPIDs[i] );
}
free( globals ); free( globals );
} }
if( nativeGlobals )
free( nativeGlobals );
return result; return result;
} }
...@@ -200,14 +159,12 @@ static long VLCEyeTVPluginGetInformation(VLCEyeTVPluginGlobals_t *globals, long* ...@@ -200,14 +159,12 @@ static long VLCEyeTVPluginGetInformation(VLCEyeTVPluginGlobals_t *globals, long*
if( outName ) if( outName )
{ {
char* name = "VLC media player Plug-In"; strcpy( outName, "VLC media player Plug-In");
strcpy( &outName[0], name);
} }
if( outDescription ) if( outDescription )
{ {
char* desc = "This Plug-In connects EyeTV to the VLC media player for streaming purposes."; strcpy( outDescription, "This Plug-In connects EyeTV to the VLC media player for streaming purposes.");
strcpy( &outDescription[0], desc);
} }
} }
...@@ -221,27 +178,6 @@ void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center, ...@@ -221,27 +178,6 @@ void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center,
const void *object, const void *object,
CFDictionaryRef userInfo ) CFDictionaryRef userInfo )
{ {
CFIndex maxlen;
char *theName, *theObject;
extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;
maxlen = CFStringGetMaximumSizeForEncoding( CFStringGetLength( name ),
kCFStringEncodingUTF8) + 1;
theName = malloc(maxlen);
CFStringGetCString( name,
theName,
maxlen,
kCFStringEncodingUTF8);
maxlen = CFStringGetMaximumSizeForEncoding( CFStringGetLength( name ),
kCFStringEncodingUTF8) + 1;
theObject = malloc(maxlen);
CFStringGetCString( object,
theObject,
maxlen,
kCFStringEncodingUTF8);
printf( "notication received with name: %s and object: %s\n", theName, theObject );
/* when VLC launches after us, we need to inform it about our existance and the current state of available devices */ /* when VLC launches after us, we need to inform it about our existance and the current state of available devices */
if( CFStringCompare( name, CFSTR( "VLCOSXGUIInit" ), 0) == kCFCompareEqualTo ) if( CFStringCompare( name, CFSTR( "VLCOSXGUIInit" ), 0) == kCFCompareEqualTo )
{ {
...@@ -251,7 +187,7 @@ void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center, ...@@ -251,7 +187,7 @@ void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center,
CFSTR(VLC_NOTIFICATION_OBJECT), CFSTR(VLC_NOTIFICATION_OBJECT),
/*userInfo*/ NULL, /*userInfo*/ NULL,
TRUE ); TRUE );
if( nativeGlobals && ( nativeGlobals->i_deviceCount > 0 ) ) if( i_deviceCount > 0 )
{ {
/* at least one device is apparently connected */ /* at least one device is apparently connected */
CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (), CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),
...@@ -265,23 +201,45 @@ void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center, ...@@ -265,23 +201,45 @@ void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center,
/* VLC wants us to start sending data */ /* VLC wants us to start sending data */
if( CFStringCompare( name, CFSTR( "VLCAccessStartDataSending" ), 0) == kCFCompareEqualTo ) if( CFStringCompare( name, CFSTR( "VLCAccessStartDataSending" ), 0) == kCFCompareEqualTo )
{ {
nativeGlobals->messagePortToVLC = CFMessagePortCreateRemote( kCFAllocatorDefault, if( vlcSock == -1 )
CFSTR("VLCEyeTVMsgPort") ); {
if( nativeGlobals->messagePortToVLC == NULL ) int peerSock;
printf( "getting messagePortToVLC failed!\n" );
else /* set-up data socket */
peerSock = socket(AF_UNIX, SOCK_STREAM, 0);
if( peerSock != -1 )
{ {
nativeGlobals->b_msgPortOpen = TRUE; struct sockaddr_un peerAddr;
printf( "msg port opened / data sending switched on\n" ); /* set-up connection address */
memset(&peerAddr, 0, sizeof(peerAddr));
peerAddr.sun_family = AF_UNIX;
strncpy(peerAddr.sun_path, "/tmp/.vlc-eyetv-bridge", sizeof(peerAddr.sun_path)-1);
/* connect */
printf("data connect in progess...\n");
if( connect(peerSock, (struct sockaddr *)&peerAddr, sizeof(struct sockaddr_un)) != -1 )
{
printf("data sending switched on\n");
vlcSock = peerSock;
}
else
printf("connect data socket failed (errno=%d)\n", errno );
}
else
printf("create data socket failed (errno=%d)\n", errno );
} }
} }
/* VLC wants us to stop sending data */ /* VLC wants us to stop sending data */
if( CFStringCompare( name, CFSTR( "VLCAccessStopDataSending" ), 0) == kCFCompareEqualTo ) if( CFStringCompare( name, CFSTR( "VLCAccessStopDataSending" ), 0) == kCFCompareEqualTo )
{ {
nativeGlobals->b_msgPortOpen = FALSE; if( vlcSock != -1 )
{
close( vlcSock );
vlcSock = -1;
printf( "data sending switched off\n" ); printf( "data sending switched off\n" );
} }
}
} }
/* called if a device is added */ /* called if a device is added */
...@@ -290,25 +248,12 @@ static long VLCEyeTVPluginDeviceAdded(VLCEyeTVPluginGlobals_t *globals, EyeTVPlu ...@@ -290,25 +248,12 @@ static long VLCEyeTVPluginDeviceAdded(VLCEyeTVPluginGlobals_t *globals, EyeTVPlu
printf("VLC media player Plug-In: Device with type %i and ID %i added\n", (int)deviceType, (int)deviceID); printf("VLC media player Plug-In: Device with type %i and ID %i added\n", (int)deviceType, (int)deviceID);
long result = 0; long result = 0;
DeviceInfo *deviceInfo;
extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;
if( globals ) if( globals )
{ {
if( globals->deviceCount < MAX_DEVICES ) ++i_deviceCount;
if( 1 == i_deviceCount )
{ {
deviceInfo = &( globals->devices[globals->deviceCount] );
memset(deviceInfo, 0, sizeof(DeviceInfo));
deviceInfo->deviceID = deviceID;
deviceInfo->deviceType = deviceType;
globals->deviceCount++;
if( nativeGlobals )
nativeGlobals->i_deviceCount = globals->deviceCount;
/* notify a potential VLC instance about the addition */ /* notify a potential VLC instance about the addition */
CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(), CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),
CFSTR("DeviceAdded"), CFSTR("DeviceAdded"),
...@@ -317,7 +262,6 @@ static long VLCEyeTVPluginDeviceAdded(VLCEyeTVPluginGlobals_t *globals, EyeTVPlu ...@@ -317,7 +262,6 @@ static long VLCEyeTVPluginDeviceAdded(VLCEyeTVPluginGlobals_t *globals, EyeTVPlu
TRUE ); TRUE );
} }
} }
return result; return result;
} }
...@@ -326,26 +270,11 @@ static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVP ...@@ -326,26 +270,11 @@ static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVP
{ {
printf("VLC media player Plug-In: DeviceRemoved\n"); printf("VLC media player Plug-In: DeviceRemoved\n");
extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;
long result = 0; long result = 0;
int i;
if( globals ) --i_deviceCount;
{ if( 0 == i_deviceCount )
for( i = 0; i < globals->deviceCount; i++ )
{ {
if ( globals->devices[i].deviceID == deviceID )
{
globals->deviceCount--;
if( i<globals->deviceCount )
{
globals->devices[i] = globals->devices[globals->deviceCount];
}
if( nativeGlobals )
nativeGlobals->i_deviceCount = globals->deviceCount;
/* notify a potential VLC instance about the removal */ /* notify a potential VLC instance about the removal */
CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(), CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),
CFSTR("DeviceRemoved"), CFSTR("DeviceRemoved"),
...@@ -353,7 +282,11 @@ static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVP ...@@ -353,7 +282,11 @@ static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVP
/*userInfo*/ NULL, /*userInfo*/ NULL,
TRUE ); TRUE );
} }
} if( (vlcSock != -1) && (deviceID == globals->activeDeviceID) )
{
close(vlcSock);
vlcSock = -1;
printf( "data sending switched off\n" );
} }
return result; return result;
...@@ -362,147 +295,74 @@ static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVP ...@@ -362,147 +295,74 @@ static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVP
/* This function is called, whenever packets are received by EyeTV. For reasons of performance, /* This function is called, whenever packets are received by EyeTV. For reasons of performance,
* the data is the original data, not a copy. That means, EyeTV waits until this method is * the data is the original data, not a copy. That means, EyeTV waits until this method is
* finished. Therefore all in this method should be as fast as possible. */ * finished. Therefore all in this method should be as fast as possible. */
int i=0;
static long VLCEyeTVPluginPacketsArrived(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID, long **packets, long packetsCount) static long VLCEyeTVPluginPacketsArrived(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID, long **packets, long packetsCount)
{ {
long result = 0; if( globals )
int i, j, isNewPID;
TransportStreamPacket *packet;
extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;
SInt32 i_returnValue;
CFMutableDataRef theMutableRef;
uint8_t *p_bufferForSending = malloc(4);
bool b_nonSendData;
int i_lastSentPacket;
if( globals && nativeGlobals )
{ {
DeviceInfo *deviceInfo = GetDeviceInfo(globals, deviceID); /* check if data connection is active */
if( vlcSock != -1 )
if( deviceInfo )
{ {
/* alloc the buffer if wanted */ if( deviceID == globals->activeDeviceID )
if( nativeGlobals->b_msgPortOpen == TRUE )
theMutableRef = CFDataCreateMutable( kCFAllocatorDefault, (188) );
for( i = 0; i < packetsCount; i++ )
{ {
packet = ( TransportStreamPacket* )packets[i]; long pidCount = globals->activePIDsCount;
isNewPID = 1; if( pidCount )
/* search for PID */
for( j = 0; j < deviceInfo->pidsCount; j++ )
{ {
if( packet->PID == deviceInfo->pids[j] ) while( packetsCount )
{ {
isNewPID = 0; /* apply PID filtering, only PIDs in active service for device are sent through */
break; long pid = (ntohl(**packets) & 0x001FFF00L)>>8;
} long i;
} for( i=0; i<pidCount; ++i )
/* add new PIDs to the DeviceInfo */
if( isNewPID )
{ {
printf ("VLC media player Plug-In: SamplePacketsArrived, newPID = %6d\n", packet->PID); if( globals->activePIDs[i].pid == pid )
if( deviceInfo->pidsCount < MAX_PIDS )
{ {
deviceInfo->pids[deviceInfo->pidsCount++] = packet->PID; ssize_t sent = write(vlcSock, *packets, sizeof(TransportStreamPacket));
} if( sent != sizeof(TransportStreamPacket) )
}
else
{ {
/* forward data to VLC if wanted */ if( sent == -1 )
/* FIXME: we only receive ARD for now */ printf("data sending failed (errno=%d)\n", errno);
if( nativeGlobals->b_msgPortOpen == TRUE && ( else
packet->PID == 1401 || printf("data sending incomplete (sent=%d)\n", sent);
packet->PID == 1402 || close(vlcSock);
packet->PID == 1400 || vlcSock = -1;
packet->PID == 1404 || return 0;
packet->PID == 3070 || }
packet->PID == 3072 || ++(globals->seenPIDs[i]);
packet->PID == 3074 || #if 0
packet->PID == 5074 ||
packet->PID == 0 ||
packet->PID == 17 ||
packet->PID == 19 ||
packet->PID == 20 ) )
{
/* in a good world, this wouldn't be necessary */
if( theMutableRef == NULL )
theMutableRef = CFDataCreateMutable( kCFAllocatorDefault, (188) );
/* collect data to send larger packets */
/* enlarge buffer if necessary */
if( i > 0 ) if( i > 0 )
CFDataIncreaseLength( theMutableRef, 188 ); {
/* if we assume that consecutive packets should have the same PID, it would therefore
/* add missing header */ speed up filtering to reorder activePIDs list based on pid occurrences */
memcpy( p_bufferForSending, packet, 4 ); EyeTVPluginPIDInfo swap = globals->activePIDs[i];
CFDataAppendBytes( theMutableRef, p_bufferForSending, sizeof(p_bufferForSending) ); memmove(globals->activePIDs+1, globals->activePIDs, sizeof(EyeTVPluginPIDInfo)*i);
globals->activePIDs[0] = swap;
free( p_bufferForSending ); }
p_bufferForSending = malloc(4);
/* add payload */
CFDataAppendBytes( theMutableRef, packet->data, sizeof(packet->data) );
b_nonSendData = TRUE;
if( pid && filterPidInfo.pidType != kEyeTVPIDType_PMT )
{
/* to save on CPU, prevent EyeTV from mirroring that program by blocking video & audio packets
by changing PID to NULL PID */
#if defined(WORDS_BIGENDIAN)
**packets |= 0x001FFF00L;
#else
**packets |= 0x00FFF800L;
#endif
} }
#endif
/* done filtering on this packet, move on to next packet */
break;
} }
globals->packetCount++;
if( globals->packetCount%10000 == 0 )
printf("-> %lld Packets received so far...\n",globals->packetCount);
} }
if( i == pidCount )
if( nativeGlobals->b_msgPortOpen == TRUE ) printf("unexpected PID %ld\n", pid);
{
printf( "sending %i bytes of data\n", CFDataGetLength( theMutableRef ) );
i_returnValue = CFMessagePortSendRequest( nativeGlobals->messagePortToVLC,
/* arbitrary int val */ globals->packetCount,
/* the data */ theMutableRef,
/* no timeout for sending */ 0,
/* no timeout for resp */ 0,
/* no resp. wanted */ NULL,
NULL );
b_nonSendData = FALSE;
i_lastSentPacket = globals->packetCount;
if( i_returnValue == kCFMessagePortSendTimeout )
printf( "time out while sending\n" );
else if( i_returnValue == kCFMessagePortReceiveTimeout )
printf( "time out while waiting for resp\n" );
else if( i_returnValue == kCFMessagePortIsInvalid )
{
/* suppress any further attemps */
printf( "message port is invalid!\n" );
nativeGlobals->b_msgPortOpen = FALSE;
} }
else if( i_returnValue == kCFMessagePortTransportError ) --packetsCount;
printf( "transport error while sending!\n" ); ++packets;
else
{
//printf( "success, freeing resources\n" );
free( theMutableRef );
theMutableRef = CFDataCreateMutable( kCFAllocatorDefault, (188) );
} }
} }
} }
} }
else return 0;
printf( "warning: either globals or nativeGlobals are NIL in VLCEyeTVPluginPacketsArrived" );
/* clean up before leaving function */
//if( nativeGlobals->b_msgPortOpen == TRUE )
// free( theMutableRef );
free( p_bufferForSending );
return result;
} }
/* VLCEyeTVPluginServiceChanged, /* VLCEyeTVPluginServiceChanged,
...@@ -533,29 +393,20 @@ static long VLCEyeTVPluginServiceChanged(VLCEyeTVPluginGlobals_t *globals, ...@@ -533,29 +393,20 @@ static long VLCEyeTVPluginServiceChanged(VLCEyeTVPluginGlobals_t *globals,
if( globals ) if( globals )
{ {
DeviceInfo *deviceInfo = GetDeviceInfo( globals, deviceID ); printf("DeviceID: %ld, ", deviceID);
if( deviceInfo )
{
deviceInfo->headendID = headendID;
printf("HeadendID: %ld, ", headendID); printf("HeadendID: %ld, ", headendID);
deviceInfo->transponderID = transponderID;
printf("TransponderID: %ld, ", transponderID); printf("TransponderID: %ld, ", transponderID);
deviceInfo->serviceID = serviceID;
printf("ServiceID: %ld\n\n", serviceID); printf("ServiceID: %ld\n\n", serviceID);
deviceInfo->activePIDsCount = pidsCount; globals->activeDeviceID = deviceID;
globals->activePIDsCount = pidsCount;
for( i = 0; i < pidsCount; i++ ) for( i = 0; i < pidsCount; i++ )
{ {
deviceInfo->activePIDs[i] = pidList[i]; globals->activePIDs[i] = pidList[i];
globals->seenPIDs[i] = 0;
printf("Active PID: %ld, type: %ld\n", pidList[i].pid, pidList[i].pidType); printf("Active PID: %ld, type: %ld\n", pidList[i].pid, pidList[i].pidType);
} }
deviceInfo->pidsCount = 0;
}
} }
printf( "=====================================\n"); printf( "=====================================\n");
......
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
*****************************************************************************/ *****************************************************************************/
#include "EyeTVPluginDefs.h" #include "EyeTVPluginDefs.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center, void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center,
......
...@@ -122,7 +122,6 @@ ...@@ -122,7 +122,6 @@
mainGroup = 089C166AFE841209C02AAC07 /* VLC EyeTV Plug-In */; mainGroup = 089C166AFE841209C02AAC07 /* VLC EyeTV Plug-In */;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
shouldCheckCompatibility = 1;
targets = ( targets = (
8D57630D048677EA00EA77CD /* VLC EyeTV Plug-In */, 8D57630D048677EA00EA77CD /* VLC EyeTV Plug-In */,
); );
......
# Automake forgets to add a proper tag to libtool with Objective-C files.
# Moreocer Libtool should default tag to CC when none is specified but
# obviously does not. Here is a fix for that.
LIBTOOL=@LIBTOOL@ --tag=CC
SOURCES_access_file = file.c SOURCES_access_file = file.c
SOURCES_access_directory = directory.c SOURCES_access_directory = directory.c
SOURCES_access_dv = dv.c SOURCES_access_dv = dv.c
...@@ -7,7 +12,7 @@ SOURCES_access_http = http.c ...@@ -7,7 +12,7 @@ SOURCES_access_http = http.c
SOURCES_access_ftp = ftp.c SOURCES_access_ftp = ftp.c
SOURCES_access_smb = smb.c SOURCES_access_smb = smb.c
SOURCES_access_gnomevfs = gnomevfs.c SOURCES_access_gnomevfs = gnomevfs.c
SOURCES_access_eyetv = eyetv.c SOURCES_access_eyetv = eyetv.m
SOURCES_dvdnav = dvdnav.c SOURCES_dvdnav = dvdnav.c
SOURCES_dvdread = dvdread.c SOURCES_dvdread = dvdread.c
SOURCES_dc1394 = dc1394.c SOURCES_dc1394 = dc1394.c
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* eyetv.c : Access module to connect to our plugin running within EyeTV * eyetv.c : Access module to connect to our plugin running within EyeTV
***************************************************************************** *****************************************************************************
* Copyright (C) 2006-2007 the VideoLAN team * Copyright (C) 2006-2007 the VideoLAN team
* $Id$ * $Id: eyetv.c 23509 2007-12-09 17:39:28Z courmisch $
* *
* Author: Felix Kühne <fkuehne at videolan dot org> * Author: Felix Kühne <fkuehne at videolan dot org>
* *
...@@ -28,7 +28,14 @@ ...@@ -28,7 +28,14 @@
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc_access.h> #include <vlc_access.h>
#include <CoreFoundation/CoreFoundation.h> #include <vlc_network.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#import <Foundation/Foundation.h>
/* TODO: /* TODO:
* watch for PluginQuit or DeviceRemoved to stop output to VLC's core then */ * watch for PluginQuit or DeviceRemoved to stop output to VLC's core then */
...@@ -39,12 +46,19 @@ ...@@ -39,12 +46,19 @@
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close( vlc_object_t * ); static void Close( vlc_object_t * );
#define CHANNEL_TEXT N_("Channel number")
#define CHANNEL_LONGTEXT N_( \
"EyeTV program number, or use 0 for last channel, " \
"-1 for S-Video input, -2 for Composite input" )
vlc_module_begin(); vlc_module_begin();
set_shortname( "EyeTV" ); set_shortname( "EyeTV" );
set_description( _("EyeTV access module") ); set_description( _("EyeTV access module") );
set_category( CAT_INPUT ); set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_ACCESS ); set_subcategory( SUBCAT_INPUT_ACCESS );
add_integer( "eyetv-channel", 0, NULL,
CHANNEL_TEXT, CHANNEL_LONGTEXT, VLC_FALSE );
set_capability( "access2", 0 ); set_capability( "access2", 0 );
add_shortcut( "eyetv" ); add_shortcut( "eyetv" );
set_callbacks( Open, Close ); set_callbacks( Open, Close );
...@@ -53,29 +67,71 @@ vlc_module_end(); ...@@ -53,29 +67,71 @@ vlc_module_end();
/***************************************************************************** /*****************************************************************************
* Access: local prototypes * 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 struct access_sys_t
{ {
eyetv_thread_t *p_thread; int eyetvSock;
}; };
CFDataRef dataFromEyetv;
int lastPacketId;
int lastForwardedPacketId;
static ssize_t Read( access_t *, uint8_t *, size_t ); static ssize_t Read( access_t *, uint8_t *, size_t );
static int Control( access_t *, int, va_list ); static int Control( access_t *, int, va_list );
static void Thread( vlc_object_t * );
CFDataRef msgPortCallback( CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info ); static void selectChannel( vlc_object_t *p_this, int theChannelNum )
{
NSAppleScript *script;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
switch( theChannelNum )
{
case -2: // Composite
script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n"
" input_change input source composite video input\n"
" volume_change level 0\n"
" show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell"];
break;
case -1: // S-Video
script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n"
" input_change input source S video input\n"
" volume_change level 0\n"
" show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell"];
break;
case 0: // Last
script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n"
" volume_change level 0\n"
" show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell"];
break;
default:
if( theChannelNum > 0 )
{
NSString *channel_change = [NSString stringWithFormat:
@"tell application \"EyeTV\"\n"
" channel_change channel number %d\n"
" volume_change level 0\n"
" show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\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];
msg_Err( p_this, "EyeTV source change failed with error status '%s'", [errorString UTF8String] );
}
[script release];
[pool release];
}
/***************************************************************************** /*****************************************************************************
* Open: sets up the module and its threads * Open: sets up the module and its threads
...@@ -84,9 +140,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -84,9 +140,11 @@ static int Open( vlc_object_t *p_this )
{ {
access_t *p_access = (access_t *)p_this; access_t *p_access = (access_t *)p_this;
access_sys_t *p_sys; access_sys_t *p_sys;
eyetv_thread_t *p_thread;
CFMessagePortContext context; struct sockaddr_un publicAddr, peerAddr;
memset(&context, 0, sizeof(context)); int publicSock;
vlc_value_t val;
/* Init p_access */ /* Init p_access */
access_InitFields( p_access ); \ access_InitFields( p_access ); \
...@@ -94,56 +152,55 @@ static int Open( vlc_object_t *p_this ) ...@@ -94,56 +152,55 @@ static int Open( vlc_object_t *p_this )
MALLOC_ERR( p_access->p_sys, access_sys_t ); \ MALLOC_ERR( p_access->p_sys, access_sys_t ); \
p_sys = p_access->p_sys; memset( p_sys, 0, sizeof( access_sys_t ) ); p_sys = p_access->p_sys; memset( p_sys, 0, sizeof( access_sys_t ) );
var_Create( p_access, "eyetv-channel", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_access, "eyetv-channel", &val);
msg_Dbg( p_access, "coming up" ); msg_Dbg( p_access, "coming up" );
/* create receiving thread which will keep the message port alive without blocking */ selectChannel(p_this, val.i_int);
p_sys->p_thread = p_thread = vlc_object_create( p_access, sizeof( eyetv_thread_t ) );
vlc_object_attach( p_thread, p_this ); /* socket */
vlc_mutex_init( p_access, &p_thread->lock ); memset(&publicAddr, 0, sizeof(publicAddr));
vlc_cond_init( p_access, &p_thread->wait ); publicAddr.sun_family = AF_UNIX;
msg_Dbg( p_access, "thread created, msg port following now" ); strncpy(publicAddr.sun_path, "/tmp/.vlc-eyetv-bridge", sizeof(publicAddr.sun_path)-1);
/* remove previous public path if it wasn't cleanly removed */
/* set up our own msg port if( (0 != unlink(publicAddr.sun_path)) && (ENOENT != errno) )
* 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" ); msg_Err( p_access, "local socket path is not usable (errno=%d)", errno );
free( p_sys->p_thread->inputMessagePortFromEyeTV ); free( p_sys );
vlc_mutex_destroy( &p_thread->lock ); return VLC_EGENERIC;
vlc_cond_destroy( &p_thread->wait ); }
vlc_object_detach( p_thread );
vlc_object_destroy( p_thread ); publicSock = socket(AF_UNIX, SOCK_STREAM, 0);
if( publicSock == -1 )
{
msg_Err( p_access, "create local socket failed (errno=%d)", errno );
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
else
msg_Dbg( p_access, "remote msg port opened" );
/* let the thread run */ if( bind(publicSock, (struct sockaddr *)&publicAddr, sizeof(struct sockaddr_un)) == -1 )
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" ); msg_Err( p_access, "bind local socket failed (errno=%d)", errno );
vlc_mutex_destroy( &p_thread->lock ); close( publicSock );
vlc_cond_destroy( &p_thread->wait );
vlc_object_detach( p_thread );
vlc_object_destroy( p_thread );
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
msg_Dbg( p_access, "receiver thread created and launched" ); /* we are not expecting more than one connection */
if( listen(publicSock, 1) == -1 )
{
msg_Err( p_access, "cannot accept connection (errno=%d)", errno );
close( publicSock );
free( p_sys );
return VLC_EGENERIC;
}
else
{
socklen_t peerSockLen = sizeof(struct sockaddr_un);
int peerSock;
/* tell the EyeTV plugin to open up its msg port and start sending */ /* tell the EyeTV plugin to open start sending */
CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (), CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),
CFSTR("VLCAccessStartDataSending"), CFSTR("VLCAccessStartDataSending"),
CFSTR("VLCEyeTVSupport"), CFSTR("VLCEyeTVSupport"),
...@@ -152,9 +209,23 @@ static int Open( vlc_object_t *p_this ) ...@@ -152,9 +209,23 @@ static int Open( vlc_object_t *p_this )
msg_Dbg( p_access, "plugin notified" ); msg_Dbg( p_access, "plugin notified" );
/* we don't need such a high priority */ peerSock = accept(publicSock, (struct sockaddr *)&peerAddr, &peerSockLen);
//vlc_thread_set_priority( p_access, VLC_THREAD_PRIORITY_LOW ); if( peerSock == -1 )
{
msg_Err( p_access, "cannot wait for connection (errno=%d)", errno );
close( publicSock );
free( p_sys );
return VLC_EGENERIC;
}
msg_Dbg( p_access, "plugin connected" );
p_sys->eyetvSock = peerSock;
/* remove public access */
close(publicSock);
unlink(publicAddr.sun_path);
}
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -177,106 +248,32 @@ static void Close( vlc_object_t *p_this ) ...@@ -177,106 +248,32 @@ static void Close( vlc_object_t *p_this )
msg_Dbg( p_access, "plugin notified" ); msg_Dbg( p_access, "plugin notified" );
/* stop receiver thread */ close(p_sys->eyetvSock);
vlc_object_kill( p_sys->p_thread );
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" ); 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 ); 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 * Read: forwarding data from EyeTV plugin which was received above
*****************************************************************************/ *****************************************************************************/
static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len ) static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
{ {
access_sys_t *p_sys = p_access->p_sys; access_sys_t *p_sys = p_access->p_sys;
extern CFDataRef dataFromEyetv; int i_read;
extern int lastPacketId;
extern int lastForwardedPacketId;
/* wait for a new buffer before forwarding */ if( p_access->info.b_eof )
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; return 0;
}
}
if( p_access->b_die ) i_read = net_Read( p_access, p_sys->eyetvSock, NULL, p_buffer, i_len,
return 0; VLC_FALSE );
if( i_read == 0 )
p_access->info.b_eof = VLC_TRUE;
else if( i_read > 0 )
p_access->info.i_pos += i_read;
return i_len; return i_read;
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -132,8 +132,6 @@ static VLCEyeTVController *_o_sharedInstance = nil; ...@@ -132,8 +132,6 @@ static VLCEyeTVController *_o_sharedInstance = nil;
script = [[NSAppleScript alloc] initWithSource: script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n" @"tell application \"EyeTV\"\n"
"channel_up\n" "channel_up\n"
"volume_change level 0\n"
"tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"get current channel\n" "get current channel\n"
"end tell"]; "end tell"];
msg_Dbg( VLCIntf, "telling eyetv to switch 1 channel up" ); msg_Dbg( VLCIntf, "telling eyetv to switch 1 channel up" );
...@@ -143,8 +141,6 @@ static VLCEyeTVController *_o_sharedInstance = nil; ...@@ -143,8 +141,6 @@ static VLCEyeTVController *_o_sharedInstance = nil;
script = [[NSAppleScript alloc] initWithSource: script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n" @"tell application \"EyeTV\"\n"
"channel_down\n" "channel_down\n"
"volume_change level 0\n"
"tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"get current channel\n" "get current channel\n"
"end tell"]; "end tell"];
msg_Dbg( VLCIntf, "telling eyetv to switch 1 channel down" ); msg_Dbg( VLCIntf, "telling eyetv to switch 1 channel down" );
...@@ -172,25 +168,21 @@ static VLCEyeTVController *_o_sharedInstance = nil; ...@@ -172,25 +168,21 @@ static VLCEyeTVController *_o_sharedInstance = nil;
case -2: // Composite case -2: // Composite
script = [[NSAppleScript alloc] initWithSource: script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n" @"tell application \"EyeTV\"\n"
" input_change input source composite video input" " input_change input source composite video input\n"
" volume_change level 0\n" " show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell"]; "end tell"];
break; break;
case -1: // S-Video case -1: // S-Video
script = [[NSAppleScript alloc] initWithSource: script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n" @"tell application \"EyeTV\"\n"
" input_change input source S video input" " input_change input source S video input\n"
" volume_change level 0\n" " show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell"]; "end tell"];
break; break;
case 0: // Tuner case 0: // Last
script = [[NSAppleScript alloc] initWithSource: script = [[NSAppleScript alloc] initWithSource:
@"tell application \"EyeTV\"\n" @"tell application \"EyeTV\"\n"
" input_change input source tuner input" " show player_window\n"
" volume_change level 0\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell"]; "end tell"];
break; break;
default: default:
...@@ -198,9 +190,8 @@ static VLCEyeTVController *_o_sharedInstance = nil; ...@@ -198,9 +190,8 @@ static VLCEyeTVController *_o_sharedInstance = nil;
{ {
NSString *channel_change = [NSString stringWithFormat: NSString *channel_change = [NSString stringWithFormat:
@"tell application \"EyeTV\"\n" @"tell application \"EyeTV\"\n"
@" channel_change channel number %d\n" " channel_change channel number %d\n"
" volume_change level 0\n" " show player_window\n"
" tell application \"System Events\" to set visible of process \"EyeTV\" to false\n"
"end tell", theChannelNum]; "end tell", theChannelNum];
script = [[NSAppleScript alloc] initWithSource:channel_change]; script = [[NSAppleScript alloc] initWithSource:channel_change];
} }
......
...@@ -83,7 +83,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class ) ...@@ -83,7 +83,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class )
p_list = [NSMutableArray arrayWithCapacity: 1]; p_list = [NSMutableArray arrayWithCapacity: 1];
next_media = IOIteratorNext( media_iterator ); next_media = IOIteratorNext( media_iterator );
if( next_media != nil ) if( next_media )
{ {
char psz_buf[0x32]; char psz_buf[0x32];
size_t dev_path_length; size_t dev_path_length;
...@@ -116,7 +116,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class ) ...@@ -116,7 +116,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class )
IOObjectRelease( next_media ); IOObjectRelease( next_media );
} while( ( next_media = IOIteratorNext( media_iterator ) ) != nil ); } while( ( next_media = IOIteratorNext( media_iterator ) ) );
} }
IOObjectRelease( media_iterator ); IOObjectRelease( media_iterator );
...@@ -237,12 +237,15 @@ static VLCOpen *_o_sharedMainInstance = nil; ...@@ -237,12 +237,15 @@ static VLCOpen *_o_sharedMainInstance = nil;
/* wake up with the correct EyeTV GUI */ /* wake up with the correct EyeTV GUI */
if( [[[VLCMain sharedInstance] getEyeTVController] isEyeTVrunning] == YES ) if( [[[VLCMain sharedInstance] getEyeTVController] isEyeTVrunning] == YES )
[o_eyetv_tabView selectTabViewItemWithIdentifier:@"nodevice"]; {
else if( [[[VLCMain sharedInstance] getEyeTVController] isDeviceConnected] == YES ) if( [[[VLCMain sharedInstance] getEyeTVController] isDeviceConnected] == YES )
{ {
[o_eyetv_tabView selectTabViewItemWithIdentifier:@"eyetvup"]; [o_eyetv_tabView selectTabViewItemWithIdentifier:@"eyetvup"];
[self setupChannelInfo]; [self setupChannelInfo];
} }
else
[o_eyetv_tabView selectTabViewItemWithIdentifier:@"nodevice"];
}
else else
[o_eyetv_tabView selectTabViewItemWithIdentifier:@"noeyetv"]; [o_eyetv_tabView selectTabViewItemWithIdentifier:@"noeyetv"];
...@@ -411,6 +414,10 @@ static VLCOpen *_o_sharedMainInstance = nil; ...@@ -411,6 +414,10 @@ static VLCOpen *_o_sharedMainInstance = nil;
{ {
[self openNetInfoChanged: nil]; [self openNetInfoChanged: nil];
} }
else if( [o_label isEqualToString: _NS("EyeTV")] )
{
[o_mrl setStringValue: @"eyetv://"];
}
} }
- (void)openFileGeneric - (void)openFileGeneric
...@@ -797,12 +804,23 @@ static VLCOpen *_o_sharedMainInstance = nil; ...@@ -797,12 +804,23 @@ static VLCOpen *_o_sharedMainInstance = nil;
- (IBAction)eyetvSwitchChannel:(id)sender - (IBAction)eyetvSwitchChannel:(id)sender
{ {
if( sender == o_eyetv_nextProgram_btn ) if( sender == o_eyetv_nextProgram_btn )
[o_eyetv_channels_pop selectItemWithTag:[[[VLCMain sharedInstance] getEyeTVController] switchChannelUp: YES]]; {
int chanNum = [[[VLCMain sharedInstance] getEyeTVController] switchChannelUp: YES];
[o_eyetv_channels_pop selectItemWithTag:chanNum];
[o_mrl setStringValue: [NSString stringWithFormat:@"eyetv:// :eyetv-channel=%d", chanNum]];
}
else if( sender == o_eyetv_previousProgram_btn ) else if( sender == o_eyetv_previousProgram_btn )
[o_eyetv_channels_pop selectItemWithTag:[[[VLCMain sharedInstance] getEyeTVController] switchChannelUp: NO]]; {
int chanNum = [[[VLCMain sharedInstance] getEyeTVController] switchChannelUp: NO];
[o_eyetv_channels_pop selectItemWithTag:chanNum];
[o_mrl setStringValue: [NSString stringWithFormat:@"eyetv:// :eyetv-channel=%d", chanNum]];
}
else if( sender == o_eyetv_channels_pop ) else if( sender == o_eyetv_channels_pop )
[[[VLCMain sharedInstance] getEyeTVController] selectChannel: {
[[sender selectedItem] tag]]; int chanNum = [[sender selectedItem] tag];
[[[VLCMain sharedInstance] getEyeTVController] selectChannel:chanNum];
[o_mrl setStringValue: [NSString stringWithFormat:@"eyetv:// :eyetv-channel=%d", chanNum]];
}
else else
msg_Err( VLCIntf, "eyetvSwitchChannel sent by unknown object" ); msg_Err( VLCIntf, "eyetvSwitchChannel sent by unknown object" );
} }
...@@ -865,9 +883,6 @@ static VLCOpen *_o_sharedMainInstance = nil; ...@@ -865,9 +883,6 @@ static VLCOpen *_o_sharedMainInstance = nil;
if( channels ) if( channels )
{ {
NSString *channel; NSString *channel;
[[[o_eyetv_channels_pop menu] addItemWithTitle: _NS("Tuner")
action: nil
keyEquivalent: @""] setTag:x++];
[[o_eyetv_channels_pop menu] addItem: [NSMenuItem separatorItem]]; [[o_eyetv_channels_pop menu] addItem: [NSMenuItem separatorItem]];
while( channel = [channels nextObject] ) while( channel = [channels nextObject] )
{ {
...@@ -875,7 +890,7 @@ static VLCOpen *_o_sharedMainInstance = nil; ...@@ -875,7 +890,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
* additionally, we save a bit of time */ * additionally, we save a bit of time */
[[[o_eyetv_channels_pop menu] addItemWithTitle: channel [[[o_eyetv_channels_pop menu] addItemWithTitle: channel
action: nil action: nil
keyEquivalent: @""] setTag:x++]; keyEquivalent: @""] setTag:++x];
} }
/* make Tuner the default */ /* make Tuner the default */
[o_eyetv_channels_pop selectItemWithTag:[[[VLCMain sharedInstance] getEyeTVController] currentChannel]]; [o_eyetv_channels_pop selectItemWithTag:[[[VLCMain sharedInstance] getEyeTVController] currentChannel]];
...@@ -884,8 +899,6 @@ static VLCOpen *_o_sharedMainInstance = nil; ...@@ -884,8 +899,6 @@ static VLCOpen *_o_sharedMainInstance = nil;
/* clean up GUI */ /* clean up GUI */
[o_eyetv_chn_bgbar setHidden: YES]; [o_eyetv_chn_bgbar setHidden: YES];
[o_eyetv_chn_status_txt setHidden: YES]; [o_eyetv_chn_status_txt setHidden: YES];
[o_mrl setStringValue: @"eyetv:"];
} }
- (IBAction)subsChanged:(id)sender - (IBAction)subsChanged:(id)sender
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment