Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-1.1
Commits
36868ee9
Commit
36868ee9
authored
Jan 14, 2008
by
Damien Fouilleul
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eyetv: latest version of EyeTV capture plugin, needs lotta testing
parent
5266ede1
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
838 additions
and
667 deletions
+838
-667
extras/MacOSX/eyetvplugin/eyetvplugin.c
extras/MacOSX/eyetvplugin/eyetvplugin.c
+480
-629
extras/MacOSX/eyetvplugin/eyetvplugin.h
extras/MacOSX/eyetvplugin/eyetvplugin.h
+0
-3
extras/MacOSX/eyetvplugin/eyetvplugin.xcodeproj/project.pbxproj
.../MacOSX/eyetvplugin/eyetvplugin.xcodeproj/project.pbxproj
+0
-1
modules/access/Modules.am
modules/access/Modules.am
+6
-1
modules/access/eyetv.m
modules/access/eyetv.m
+315
-0
modules/gui/macosx/eyetv.m
modules/gui/macosx/eyetv.m
+8
-17
modules/gui/macosx/open.m
modules/gui/macosx/open.m
+29
-16
No files found.
extras/MacOSX/eyetvplugin/eyetvplugin.c
View file @
36868ee9
/*****************************************************************************
* eyetvplugin.c: Plug-In for the EyeTV software to connect to VLC
*****************************************************************************
* Copyright (C) 2006-2007 the VideoLAN team
* $Id$
*
* Authors: 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.
*****************************************************************************/
#include "eyetvplugin.h"
#define MAX_PIDS 256
#define MAX_ACTIVE_PIDS 256
#define MAX_DEVICES 16
#define VLC_NOTIFICATION_OBJECT "VLCEyeTVSupport"
#pragma push
#pragma pack(1)
/* Structure for TS-Packets */
typedef
struct
{
unsigned
long
sync_byte
:
8
,
transport_error_indicator
:
1
,
payload_unit_start_indicator
:
1
,
transport_priority
:
1
,
PID
:
13
,
transport_scrambling_control
:
2
,
adaptation_field_control
:
2
,
continuity_counter
:
4
;
unsigned
char
data
[
188
-
4
];
}
TransportStreamPacket
;
#pragma pop
/* Structure to hold Information on devices */
typedef
struct
{
EyeTVPluginDeviceID
deviceID
;
EyeTVPluginDeviceType
deviceType
;
long
headendID
;
long
transponderID
;
long
serviceID
;
long
pidsCount
;
long
pids
[
MAX_PIDS
];
EyeTVPluginPIDInfo
activePIDs
[
MAX_ACTIVE_PIDS
];
long
activePIDsCount
;
}
DeviceInfo
;
/* Structure to hold global data to communicate with EyeTV */
typedef
struct
{
EyeTVPluginCallbackProc
callback
;
long
deviceCount
;
DeviceInfo
devices
[
MAX_DEVICES
];
long
long
packetCount
;
}
VLCEyeTVPluginGlobals_t
;
/* 2nd structure to store our own global data which isn't shared with EyeTV
* a bit empty at the moment, but it will get larger as development progresses */
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 -
/* initialise the plug-in */
static
long
VLCEyeTVPluginInitialize
(
VLCEyeTVPluginGlobals_t
**
globals
,
long
apiVersion
,
EyeTVPluginCallbackProc
callback
)
{
printf
(
"VLC media player Plug-In: Initialize
\n
"
);
long
result
=
0
;
/* init our own storage */
extern
VLCEyeTVPluginOwnGlobals_t
*
nativeGlobals
;
nativeGlobals
=
malloc
(
sizeof
(
VLCEyeTVPluginOwnGlobals_t
)
);
/* notify a potential VLC instance about our initialisation */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"PluginInit"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
/* init our notification support */
CFNotificationCenterAddObserver
(
CFNotificationCenterGetDistributedCenter
(),
/* observer */
NULL
,
/* callBack */
VLCEyeTVPluginGlobalNotificationReceived
,
/* name, NULL==all */
NULL
,
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
CFNotificationSuspensionBehaviorDeliverImmediately
);
*
globals
=
(
VLCEyeTVPluginGlobals_t
*
)
calloc
(
1
,
sizeof
(
VLCEyeTVPluginGlobals_t
)
);
(
*
globals
)
->
callback
=
callback
;
return
result
;
}
/* we will be terminated soon, clean up */
static
long
VLCEyeTVPluginTerminate
(
VLCEyeTVPluginGlobals_t
*
globals
)
{
extern
VLCEyeTVPluginOwnGlobals_t
*
nativeGlobals
;
printf
(
"VLC media player Plug-In: Terminate
\n
"
);
long
result
=
0
;
/* notify a potential VLC instance about our termination */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"PluginQuit"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
/* remove us from the global notification centre */
CFNotificationCenterRemoveEveryObserver
(
CFNotificationCenterGetDistributedCenter
(),
(
void
*
)
VLCEyeTVPluginGlobalNotificationReceived
);
/* invalidate and free msg port */
if
(
nativeGlobals
->
messagePortToVLC
)
{
CFMessagePortInvalidate
(
nativeGlobals
->
messagePortToVLC
);
free
(
nativeGlobals
->
messagePortToVLC
);
printf
(
"msgport invalidated and freed
\n
"
);
}
else
printf
(
"no msgport to free
\n
"
);
if
(
globals
)
{
free
(
globals
);
}
if
(
nativeGlobals
)
free
(
nativeGlobals
);
return
result
;
}
/* called when EyeTV asks various stuff about us */
static
long
VLCEyeTVPluginGetInformation
(
VLCEyeTVPluginGlobals_t
*
globals
,
long
*
outAPIVersion
,
char
*
outName
,
char
*
outDescription
)
{
printf
(
"VLC media player Plug-In: GetInfo
\n
"
);
long
result
=
0
;
if
(
globals
)
{
if
(
outAPIVersion
)
{
*
outAPIVersion
=
EYETV_PLUGIN_API_VERSION
;
}
if
(
outName
)
{
char
*
name
=
"VLC media player Plug-In"
;
strcpy
(
&
outName
[
0
],
name
);
}
if
(
outDescription
)
{
char
*
desc
=
"This Plug-In connects EyeTV to the VLC media player for streaming purposes."
;
strcpy
(
&
outDescription
[
0
],
desc
);
}
}
return
result
;
}
/* called if we received a global notification */
void
VLCEyeTVPluginGlobalNotificationReceived
(
CFNotificationCenterRef
center
,
void
*
observer
,
CFStringRef
name
,
const
void
*
object
,
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 */
if
(
CFStringCompare
(
name
,
CFSTR
(
"VLCOSXGUIInit"
),
0
)
==
kCFCompareEqualTo
)
{
/* we're here */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"PluginInit"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
if
(
nativeGlobals
&&
(
nativeGlobals
->
i_deviceCount
>
0
)
)
{
/* at least one device is apparently connected */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"DeviceAdded"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
}
}
/* VLC wants us to start sending data */
if
(
CFStringCompare
(
name
,
CFSTR
(
"VLCAccessStartDataSending"
),
0
)
==
kCFCompareEqualTo
)
{
nativeGlobals
->
messagePortToVLC
=
CFMessagePortCreateRemote
(
kCFAllocatorDefault
,
CFSTR
(
"VLCEyeTVMsgPort"
)
);
if
(
nativeGlobals
->
messagePortToVLC
==
NULL
)
printf
(
"getting messagePortToVLC failed!
\n
"
);
else
{
nativeGlobals
->
b_msgPortOpen
=
TRUE
;
printf
(
"msg port opened / data sending switched on
\n
"
);
}
}
/* VLC wants us to stop sending data */
if
(
CFStringCompare
(
name
,
CFSTR
(
"VLCAccessStopDataSending"
),
0
)
==
kCFCompareEqualTo
)
{
nativeGlobals
->
b_msgPortOpen
=
FALSE
;
printf
(
"data sending switched off
\n
"
);
}
}
/* called if a device is added */
static
long
VLCEyeTVPluginDeviceAdded
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
,
EyeTVPluginDeviceType
deviceType
)
{
printf
(
"VLC media player Plug-In: Device with type %i and ID %i added
\n
"
,
(
int
)
deviceType
,
(
int
)
deviceID
);
long
result
=
0
;
DeviceInfo
*
deviceInfo
;
extern
VLCEyeTVPluginOwnGlobals_t
*
nativeGlobals
;
if
(
globals
)
{
if
(
globals
->
deviceCount
<
MAX_DEVICES
)
{
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 */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"DeviceAdded"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
}
}
return
result
;
}
/* called if a device is removed */
static
long
VLCEyeTVPluginDeviceRemoved
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
)
{
printf
(
"VLC media player Plug-In: DeviceRemoved
\n
"
);
extern
VLCEyeTVPluginOwnGlobals_t
*
nativeGlobals
;
long
result
=
0
;
int
i
;
if
(
globals
)
{
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 */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"DeviceRemoved"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
}
}
}
return
result
;
}
/* 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
* 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
)
{
long
result
=
0
;
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
);
if
(
deviceInfo
)
{
/* alloc the buffer if wanted */
if
(
nativeGlobals
->
b_msgPortOpen
==
TRUE
)
theMutableRef
=
CFDataCreateMutable
(
kCFAllocatorDefault
,
(
188
)
);
for
(
i
=
0
;
i
<
packetsCount
;
i
++
)
{
packet
=
(
TransportStreamPacket
*
)
packets
[
i
];
isNewPID
=
1
;
/* search for PID */
for
(
j
=
0
;
j
<
deviceInfo
->
pidsCount
;
j
++
)
{
if
(
packet
->
PID
==
deviceInfo
->
pids
[
j
]
)
{
isNewPID
=
0
;
break
;
}
}
/* add new PIDs to the DeviceInfo */
if
(
isNewPID
)
{
printf
(
"VLC media player Plug-In: SamplePacketsArrived, newPID = %6d
\n
"
,
packet
->
PID
);
if
(
deviceInfo
->
pidsCount
<
MAX_PIDS
)
{
deviceInfo
->
pids
[
deviceInfo
->
pidsCount
++
]
=
packet
->
PID
;
}
}
else
{
/* forward data to VLC if wanted */
/* FIXME: we only receive ARD for now */
if
(
nativeGlobals
->
b_msgPortOpen
==
TRUE
&&
(
packet
->
PID
==
1401
||
packet
->
PID
==
1402
||
packet
->
PID
==
1400
||
packet
->
PID
==
1404
||
packet
->
PID
==
3070
||
packet
->
PID
==
3072
||
packet
->
PID
==
3074
||
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
)
CFDataIncreaseLength
(
theMutableRef
,
188
);
/* add missing header */
memcpy
(
p_bufferForSending
,
packet
,
4
);
CFDataAppendBytes
(
theMutableRef
,
p_bufferForSending
,
sizeof
(
p_bufferForSending
)
);
free
(
p_bufferForSending
);
p_bufferForSending
=
malloc
(
4
);
/* add payload */
CFDataAppendBytes
(
theMutableRef
,
packet
->
data
,
sizeof
(
packet
->
data
)
);
b_nonSendData
=
TRUE
;
}
}
globals
->
packetCount
++
;
if
(
globals
->
packetCount
%
10000
==
0
)
printf
(
"-> %lld Packets received so far...
\n
"
,
globals
->
packetCount
);
}
if
(
nativeGlobals
->
b_msgPortOpen
==
TRUE
)
{
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
)
printf
(
"transport error while sending!
\n
"
);
else
{
//printf( "success, freeing resources\n" );
free
(
theMutableRef
);
theMutableRef
=
CFDataCreateMutable
(
kCFAllocatorDefault
,
(
188
)
);
}
}
}
}
else
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,
*
* - *globals : The plug-in Globals
* - deviceID : Identifies the active Device
* - headendID : The HeadendID, for e300 it's the orbital position of the satelite in
* tenth degrees east
* - transponderID : The Frequency in kHz
* - serviceID : original ServiceID from the DVB-Stream (e300, e400)
* - pidList : List of active PIDs
*
* Whenever a service changes, this function is called. Service-related plug-in data should be updated here.
*/
static
long
VLCEyeTVPluginServiceChanged
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
,
long
headendID
,
long
transponderID
,
long
serviceID
,
EyeTVPluginPIDInfo
*
pidList
,
long
pidsCount
)
{
long
result
=
0
;
int
i
;
printf
(
"
\n
VLC media player Plug-In: ServiceChanged:
\n
"
);
printf
(
"=====================================
\n
"
);
if
(
globals
)
{
DeviceInfo
*
deviceInfo
=
GetDeviceInfo
(
globals
,
deviceID
);
if
(
deviceInfo
)
{
deviceInfo
->
headendID
=
headendID
;
printf
(
"HeadendID: %ld, "
,
headendID
);
deviceInfo
->
transponderID
=
transponderID
;
printf
(
"TransponderID: %ld, "
,
transponderID
);
deviceInfo
->
serviceID
=
serviceID
;
printf
(
"ServiceID: %ld
\n\n
"
,
serviceID
);
deviceInfo
->
activePIDsCount
=
pidsCount
;
for
(
i
=
0
;
i
<
pidsCount
;
i
++
)
{
deviceInfo
->
activePIDs
[
i
]
=
pidList
[
i
];
printf
(
"Active PID: %ld, type: %ld
\n
"
,
pidList
[
i
].
pid
,
pidList
[
i
].
pidType
);
}
deviceInfo
->
pidsCount
=
0
;
}
}
printf
(
"=====================================
\n
"
);
/* notify a potential VLC instance about the service change */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"ServiceChanged"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
return
result
;
}
#pragma mark -
/* EyeTVPluginDispatcher,
*
* - selector : See 'EyeTVPluginDefs.h'
* - *refCon : The RefCon to the plug-in-related Data
* - deviceID : Identifies the Device
* - params : Parameters for functioncall
*
* This function is a part of the interface for the communication with EyeTV. If something happens,
* EyeTV thinks, we should know of, it calls this function with the corresponding selector. */
#pragma export on
long
EyeTVPluginDispatcher
(
EyeTVPluginParams
*
params
)
{
long
result
=
0
;
switch
(
params
->
selector
)
{
case
kEyeTVPluginSelector_Initialize
:
result
=
VLCEyeTVPluginInitialize
((
VLCEyeTVPluginGlobals_t
**
)
params
->
refCon
,
params
->
initialize
.
apiVersion
,
params
->
initialize
.
callback
);
break
;
case
kEyeTVPluginSelector_Terminate
:
result
=
VLCEyeTVPluginTerminate
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
);
break
;
case
kEyeTVPluginSelector_GetInfo
:
result
=
VLCEyeTVPluginGetInformation
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
info
.
pluginAPIVersion
,
params
->
info
.
pluginName
,
params
->
info
.
description
);
break
;
case
kEyeTVPluginSelector_DeviceAdded
:
result
=
VLCEyeTVPluginDeviceAdded
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
,
params
->
deviceAdded
.
deviceType
);
break
;
case
kEyeTVPluginSelector_DeviceRemoved
:
result
=
VLCEyeTVPluginDeviceRemoved
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
);
break
;
case
kEyeTVPluginSelector_PacketsArrived
:
result
=
VLCEyeTVPluginPacketsArrived
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
,
params
->
packetsArrived
.
packets
,
params
->
packetsArrived
.
packetCount
);
break
;
case
kEyeTVPluginSelector_ServiceChanged
:
result
=
VLCEyeTVPluginServiceChanged
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
,
params
->
serviceChanged
.
headendID
,
params
->
serviceChanged
.
transponderID
,
params
->
serviceChanged
.
serviceID
,
params
->
serviceChanged
.
pidList
,
params
->
serviceChanged
.
pidCount
);
break
;
}
return
result
;
}
/*****************************************************************************
* eyetvplugin.c: Plug-In for the EyeTV software to connect to VLC
*****************************************************************************
* Copyright (C) 2006-2007 the VideoLAN team
* $Id$
*
* Authors: 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.
*****************************************************************************/
#include "eyetvplugin.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#define MAX_PIDS 256
#define MAX_ACTIVE_PIDS 256
#define MAX_DEVICES 16
#define VLC_NOTIFICATION_OBJECT "VLCEyeTVSupport"
#pragma push
#pragma pack(1)
typedef
struct
{
uint32_t
sync_byte
:
8
,
transport_error_indicator
:
1
,
payload_unit_start_indicator
:
1
,
transport_priority
:
1
,
PID
:
13
,
transport_scrambling_control
:
2
,
adaptation_field_control
:
2
,
continuity_counter
:
4
;
}
TransportStreamHeader
;
/* Structure for TS-Packets */
typedef
struct
{
TransportStreamHeader
header
;
uint8_t
payload
[
184
];
}
TransportStreamPacket
;
#pragma pop
/* Structure to hold global data to communicate with EyeTV */
typedef
struct
{
EyeTVPluginCallbackProc
callback
;
/* Structure to hold current active service */
EyeTVPluginDeviceID
activeDeviceID
;
long
activePIDsCount
;
EyeTVPluginPIDInfo
activePIDs
[
MAX_ACTIVE_PIDS
];
long
seenPIDs
[
MAX_ACTIVE_PIDS
];
}
VLCEyeTVPluginGlobals_t
;
static
int
i_deviceCount
;
static
int
vlcSock
;
#pragma mark -
/* initialise the plug-in */
static
long
VLCEyeTVPluginInitialize
(
VLCEyeTVPluginGlobals_t
**
globals
,
long
apiVersion
,
EyeTVPluginCallbackProc
callback
)
{
printf
(
"VLC media player Plug-In: Initialize
\n
"
);
long
result
=
0
;
/* init our own storage */
i_deviceCount
=
0
;
vlcSock
=
-
1
;
/* notify a potential VLC instance about our initialisation */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"PluginInit"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
/* init our notification support */
CFNotificationCenterAddObserver
(
CFNotificationCenterGetDistributedCenter
(),
/* observer */
NULL
,
/* callBack */
VLCEyeTVPluginGlobalNotificationReceived
,
/* name, NULL==all */
NULL
,
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
CFNotificationSuspensionBehaviorDeliverImmediately
);
*
globals
=
(
VLCEyeTVPluginGlobals_t
*
)
calloc
(
1
,
sizeof
(
VLCEyeTVPluginGlobals_t
)
);
(
*
globals
)
->
callback
=
callback
;
return
result
;
}
/* we will be terminated soon, clean up */
static
long
VLCEyeTVPluginTerminate
(
VLCEyeTVPluginGlobals_t
*
globals
)
{
long
result
=
0
;
printf
(
"VLC media player Plug-In: Terminate
\n
"
);
/* notify a potential VLC instance about our termination */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"PluginQuit"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
/* remove us from the global notification centre */
CFNotificationCenterRemoveEveryObserver
(
CFNotificationCenterGetDistributedCenter
(),
(
void
*
)
VLCEyeTVPluginGlobalNotificationReceived
);
/* close data connection */
if
(
vlcSock
!=
-
1
)
{
close
(
vlcSock
);
vlcSock
=
-
1
;
}
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
);
}
return
result
;
}
/* called when EyeTV asks various stuff about us */
static
long
VLCEyeTVPluginGetInformation
(
VLCEyeTVPluginGlobals_t
*
globals
,
long
*
outAPIVersion
,
char
*
outName
,
char
*
outDescription
)
{
printf
(
"VLC media player Plug-In: GetInfo
\n
"
);
long
result
=
0
;
if
(
globals
)
{
if
(
outAPIVersion
)
{
*
outAPIVersion
=
EYETV_PLUGIN_API_VERSION
;
}
if
(
outName
)
{
strcpy
(
outName
,
"VLC media player Plug-In"
);
}
if
(
outDescription
)
{
strcpy
(
outDescription
,
"This Plug-In connects EyeTV to the VLC media player for streaming purposes."
);
}
}
return
result
;
}
/* called if we received a global notification */
void
VLCEyeTVPluginGlobalNotificationReceived
(
CFNotificationCenterRef
center
,
void
*
observer
,
CFStringRef
name
,
const
void
*
object
,
CFDictionaryRef
userInfo
)
{
/* 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
)
{
/* we're here */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"PluginInit"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
if
(
i_deviceCount
>
0
)
{
/* at least one device is apparently connected */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"DeviceAdded"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
}
}
/* VLC wants us to start sending data */
if
(
CFStringCompare
(
name
,
CFSTR
(
"VLCAccessStartDataSending"
),
0
)
==
kCFCompareEqualTo
)
{
if
(
vlcSock
==
-
1
)
{
int
peerSock
;
/* set-up data socket */
peerSock
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
);
if
(
peerSock
!=
-
1
)
{
struct
sockaddr_un
peerAddr
;
/* 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 */
if
(
CFStringCompare
(
name
,
CFSTR
(
"VLCAccessStopDataSending"
),
0
)
==
kCFCompareEqualTo
)
{
if
(
vlcSock
!=
-
1
)
{
close
(
vlcSock
);
vlcSock
=
-
1
;
printf
(
"data sending switched off
\n
"
);
}
}
}
/* called if a device is added */
static
long
VLCEyeTVPluginDeviceAdded
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
,
EyeTVPluginDeviceType
deviceType
)
{
printf
(
"VLC media player Plug-In: Device with type %i and ID %i added
\n
"
,
(
int
)
deviceType
,
(
int
)
deviceID
);
long
result
=
0
;
if
(
globals
)
{
++
i_deviceCount
;
if
(
1
==
i_deviceCount
)
{
/* notify a potential VLC instance about the addition */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"DeviceAdded"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
}
}
return
result
;
}
/* called if a device is removed */
static
long
VLCEyeTVPluginDeviceRemoved
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
)
{
printf
(
"VLC media player Plug-In: DeviceRemoved
\n
"
);
long
result
=
0
;
--
i_deviceCount
;
if
(
0
==
i_deviceCount
)
{
/* notify a potential VLC instance about the removal */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"DeviceRemoved"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
}
if
(
(
vlcSock
!=
-
1
)
&&
(
deviceID
==
globals
->
activeDeviceID
)
)
{
close
(
vlcSock
);
vlcSock
=
-
1
;
printf
(
"data sending switched off
\n
"
);
}
return
result
;
}
/* 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
* finished. Therefore all in this method should be as fast as possible. */
static
long
VLCEyeTVPluginPacketsArrived
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
,
long
**
packets
,
long
packetsCount
)
{
if
(
globals
)
{
/* check if data connection is active */
if
(
vlcSock
!=
-
1
)
{
if
(
deviceID
==
globals
->
activeDeviceID
)
{
long
pidCount
=
globals
->
activePIDsCount
;
if
(
pidCount
)
{
while
(
packetsCount
)
{
/* apply PID filtering, only PIDs in active service for device are sent through */
long
pid
=
(
ntohl
(
**
packets
)
&
0x001FFF00L
)
>>
8
;
long
i
;
for
(
i
=
0
;
i
<
pidCount
;
++
i
)
{
if
(
globals
->
activePIDs
[
i
].
pid
==
pid
)
{
ssize_t
sent
=
write
(
vlcSock
,
*
packets
,
sizeof
(
TransportStreamPacket
));
if
(
sent
!=
sizeof
(
TransportStreamPacket
)
)
{
if
(
sent
==
-
1
)
printf
(
"data sending failed (errno=%d)
\n
"
,
errno
);
else
printf
(
"data sending incomplete (sent=%d)
\n
"
,
sent
);
close
(
vlcSock
);
vlcSock
=
-
1
;
return
0
;
}
++
(
globals
->
seenPIDs
[
i
]);
#if 0
if( i > 0 )
{
/* if we assume that consecutive packets should have the same PID, it would therefore
speed up filtering to reorder activePIDs list based on pid occurrences */
EyeTVPluginPIDInfo swap = globals->activePIDs[i];
memmove(globals->activePIDs+1, globals->activePIDs, sizeof(EyeTVPluginPIDInfo)*i);
globals->activePIDs[0] = swap;
}
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
;
}
}
if
(
i
==
pidCount
)
printf
(
"unexpected PID %ld
\n
"
,
pid
);
}
--
packetsCount
;
++
packets
;
}
}
}
}
return
0
;
}
/* VLCEyeTVPluginServiceChanged,
*
* - *globals : The plug-in Globals
* - deviceID : Identifies the active Device
* - headendID : The HeadendID, for e300 it's the orbital position of the satelite in
* tenth degrees east
* - transponderID : The Frequency in kHz
* - serviceID : original ServiceID from the DVB-Stream (e300, e400)
* - pidList : List of active PIDs
*
* Whenever a service changes, this function is called. Service-related plug-in data should be updated here.
*/
static
long
VLCEyeTVPluginServiceChanged
(
VLCEyeTVPluginGlobals_t
*
globals
,
EyeTVPluginDeviceID
deviceID
,
long
headendID
,
long
transponderID
,
long
serviceID
,
EyeTVPluginPIDInfo
*
pidList
,
long
pidsCount
)
{
long
result
=
0
;
int
i
;
printf
(
"
\n
VLC media player Plug-In: ServiceChanged:
\n
"
);
printf
(
"=====================================
\n
"
);
if
(
globals
)
{
printf
(
"DeviceID: %ld, "
,
deviceID
);
printf
(
"HeadendID: %ld, "
,
headendID
);
printf
(
"TransponderID: %ld, "
,
transponderID
);
printf
(
"ServiceID: %ld
\n\n
"
,
serviceID
);
globals
->
activeDeviceID
=
deviceID
;
globals
->
activePIDsCount
=
pidsCount
;
for
(
i
=
0
;
i
<
pidsCount
;
i
++
)
{
globals
->
activePIDs
[
i
]
=
pidList
[
i
];
globals
->
seenPIDs
[
i
]
=
0
;
printf
(
"Active PID: %ld, type: %ld
\n
"
,
pidList
[
i
].
pid
,
pidList
[
i
].
pidType
);
}
}
printf
(
"=====================================
\n
"
);
/* notify a potential VLC instance about the service change */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"ServiceChanged"
),
CFSTR
(
VLC_NOTIFICATION_OBJECT
),
/*userInfo*/
NULL
,
TRUE
);
return
result
;
}
#pragma mark -
/* EyeTVPluginDispatcher,
*
* - selector : See 'EyeTVPluginDefs.h'
* - *refCon : The RefCon to the plug-in-related Data
* - deviceID : Identifies the Device
* - params : Parameters for functioncall
*
* This function is a part of the interface for the communication with EyeTV. If something happens,
* EyeTV thinks, we should know of, it calls this function with the corresponding selector. */
#pragma export on
long
EyeTVPluginDispatcher
(
EyeTVPluginParams
*
params
)
{
long
result
=
0
;
switch
(
params
->
selector
)
{
case
kEyeTVPluginSelector_Initialize
:
result
=
VLCEyeTVPluginInitialize
((
VLCEyeTVPluginGlobals_t
**
)
params
->
refCon
,
params
->
initialize
.
apiVersion
,
params
->
initialize
.
callback
);
break
;
case
kEyeTVPluginSelector_Terminate
:
result
=
VLCEyeTVPluginTerminate
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
);
break
;
case
kEyeTVPluginSelector_GetInfo
:
result
=
VLCEyeTVPluginGetInformation
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
info
.
pluginAPIVersion
,
params
->
info
.
pluginName
,
params
->
info
.
description
);
break
;
case
kEyeTVPluginSelector_DeviceAdded
:
result
=
VLCEyeTVPluginDeviceAdded
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
,
params
->
deviceAdded
.
deviceType
);
break
;
case
kEyeTVPluginSelector_DeviceRemoved
:
result
=
VLCEyeTVPluginDeviceRemoved
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
);
break
;
case
kEyeTVPluginSelector_PacketsArrived
:
result
=
VLCEyeTVPluginPacketsArrived
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
,
params
->
packetsArrived
.
packets
,
params
->
packetsArrived
.
packetCount
);
break
;
case
kEyeTVPluginSelector_ServiceChanged
:
result
=
VLCEyeTVPluginServiceChanged
((
VLCEyeTVPluginGlobals_t
*
)
params
->
refCon
,
params
->
deviceID
,
params
->
serviceChanged
.
headendID
,
params
->
serviceChanged
.
transponderID
,
params
->
serviceChanged
.
serviceID
,
params
->
serviceChanged
.
pidList
,
params
->
serviceChanged
.
pidCount
);
break
;
}
return
result
;
}
extras/MacOSX/eyetvplugin/eyetvplugin.h
View file @
36868ee9
...
...
@@ -22,9 +22,6 @@
*****************************************************************************/
#include "EyeTVPluginDefs.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
void
VLCEyeTVPluginGlobalNotificationReceived
(
CFNotificationCenterRef
center
,
...
...
extras/MacOSX/eyetvplugin/eyetvplugin.xcodeproj/project.pbxproj
View file @
36868ee9
...
...
@@ -122,7 +122,6 @@
mainGroup
=
089C166AFE841209C02AAC07
/* VLC EyeTV Plug-In */
;
projectDirPath
=
""
;
projectRoot
=
""
;
shouldCheckCompatibility
=
1
;
targets
=
(
8D57630D048677EA00EA77CD
/* VLC EyeTV Plug-In */
,
);
...
...
modules/access/Modules.am
View file @
36868ee9
# 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_directory = directory.c
SOURCES_access_dv = dv.c
...
...
@@ -7,7 +12,7 @@ SOURCES_access_http = http.c
SOURCES_access_ftp = ftp.c
SOURCES_access_smb = smb.c
SOURCES_access_gnomevfs = gnomevfs.c
SOURCES_access_eyetv = eyetv.
c
SOURCES_access_eyetv = eyetv.
m
SOURCES_dvdnav = dvdnav.c
SOURCES_dvdread = dvdread.c
SOURCES_dc1394 = dc1394.c
...
...
modules/access/eyetv.
c
→
modules/access/eyetv.
m
View file @
36868ee9
...
...
@@ -2,7 +2,7 @@
* eyetv.c : Access module to connect to our plugin running within EyeTV
*****************************************************************************
* 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>
*
...
...
@@ -28,7 +28,14 @@
#include <vlc/vlc.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:
* watch for PluginQuit or DeviceRemoved to stop output to VLC's core then */
...
...
@@ -39,12 +46,19 @@
static
int
Open
(
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
();
set_shortname
(
"EyeTV"
);
set_description
(
_
(
"EyeTV access module"
)
);
set_category
(
CAT_INPUT
);
set_subcategory
(
SUBCAT_INPUT_ACCESS
);
add_integer
(
"eyetv-channel"
,
0
,
NULL
,
CHANNEL_TEXT
,
CHANNEL_LONGTEXT
,
VLC_FALSE
);
set_capability
(
"access2"
,
0
);
add_shortcut
(
"eyetv"
);
set_callbacks
(
Open
,
Close
);
...
...
@@ -53,29 +67,71 @@ 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
;
int
eyetvSock
;
};
CFDataRef
dataFromEyetv
;
int
lastPacketId
;
int
lastForwardedPacketId
;
static
ssize_t
Read
(
access_t
*
,
uint8_t
*
,
size_t
);
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
...
...
@@ -84,77 +140,92 @@ 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
))
;
struct
sockaddr_un
publicAddr
,
peerAddr
;
int
publicSock
;
vlc_value_t
val
;
/* 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
)
);
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"
);
/* 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
)
selectChannel
(
p_this
,
val
.
i_int
);
/* socket */
memset
(
&
publicAddr
,
0
,
sizeof
(
publicAddr
));
publicAddr
.
sun_family
=
AF_UNIX
;
strncpy
(
publicAddr
.
sun_path
,
"/tmp/.vlc-eyetv-bridge"
,
sizeof
(
publicAddr
.
sun_path
)
-
1
);
/* remove previous public path if it wasn't cleanly removed */
if
(
(
0
!=
unlink
(
publicAddr
.
sun_path
))
&&
(
ENOENT
!=
errno
)
)
{
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
);
msg_Err
(
p_access
,
"local socket path is not usable (errno=%d)"
,
errno
);
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
)
)
publicSock
=
socket
(
AF_UNIX
,
SOCK_STREAM
,
0
);
if
(
publicSock
==
-
1
)
{
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
);
msg_Err
(
p_access
,
"create local socket failed (errno=%d)"
,
errno
);
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 );
if
(
bind
(
publicSock
,
(
struct
sockaddr
*
)
&
publicAddr
,
sizeof
(
struct
sockaddr_un
))
==
-
1
)
{
msg_Err
(
p_access
,
"bind local socket failed (errno=%d)"
,
errno
);
close
(
publicSock
);
free
(
p_sys
);
return
VLC_EGENERIC
;
}
/* 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 start sending */
CFNotificationCenterPostNotification
(
CFNotificationCenterGetDistributedCenter
(),
CFSTR
(
"VLCAccessStartDataSending"
),
CFSTR
(
"VLCEyeTVSupport"
),
/*userInfo*/
NULL
,
TRUE
);
msg_Dbg
(
p_access
,
"plugin notified"
);
peerSock
=
accept
(
publicSock
,
(
struct
sockaddr
*
)
&
peerAddr
,
&
peerSockLen
);
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
;
}
...
...
@@ -176,107 +247,33 @@ static void Close( vlc_object_t *p_this )
TRUE
);
msg_Dbg
(
p_access
,
"plugin notified"
);
close
(
p_sys
->
eyetvSock
);
/* stop receiver thread */
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"
);
/* 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
ssize_t
Read
(
access_t
*
p_access
,
uint8_t
*
p_buffer
,
size_t
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
)
int
i_read
;
if
(
p_access
->
info
.
b_eof
)
return
0
;
return
i_len
;
i_read
=
net_Read
(
p_access
,
p_sys
->
eyetvSock
,
NULL
,
p_buffer
,
i_len
,
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_read
;
}
/*****************************************************************************
...
...
modules/gui/macosx/eyetv.m
View file @
36868ee9
...
...
@@ -132,8 +132,6 @@ static VLCEyeTVController *_o_sharedInstance = nil;
script
=
[[
NSAppleScript
alloc
]
initWithSource
:
@"tell application
\"
EyeTV
\"\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
"
"end tell"
];
msg_Dbg
(
VLCIntf
,
"telling eyetv to switch 1 channel up"
);
...
...
@@ -143,8 +141,6 @@ static VLCEyeTVController *_o_sharedInstance = nil;
script
=
[[
NSAppleScript
alloc
]
initWithSource
:
@"tell application
\"
EyeTV
\"\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
"
"end tell"
];
msg_Dbg
(
VLCIntf
,
"telling eyetv to switch 1 channel down"
);
...
...
@@ -172,25 +168,21 @@ static VLCEyeTVController *_o_sharedInstance = nil;
case
-
2
:
// Composite
script
=
[[
NSAppleScript
alloc
]
initWithSource
:
@"tell application
\"
EyeTV
\"\n
"
" input_change input source composite video input"
" volume_change level 0
\n
"
" tell application
\"
System Events
\"
to set visible of process
\"
EyeTV
\"
to false
\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"
" volume_change level 0
\n
"
" tell application
\"
System Events
\"
to set visible of process
\"
EyeTV
\"
to false
\n
"
" input_change input source S video input
\n
"
" show player_window
\n
"
"end tell"
];
break
;
case
0
:
//
Tuner
case
0
:
//
Last
script
=
[[
NSAppleScript
alloc
]
initWithSource
:
@"tell application
\"
EyeTV
\"\n
"
" input_change input source tuner input"
" volume_change level 0
\n
"
" tell application
\"
System Events
\"
to set visible of process
\"
EyeTV
\"
to false
\n
"
" show player_window
\n
"
"end tell"
];
break
;
default:
...
...
@@ -198,9 +190,8 @@ static VLCEyeTVController *_o_sharedInstance = nil;
{
NSString
*
channel_change
=
[
NSString
stringWithFormat
:
@"tell application
\"
EyeTV
\"\n
"
@" channel_change channel number %d
\n
"
" volume_change level 0
\n
"
" tell application
\"
System Events
\"
to set visible of process
\"
EyeTV
\"
to false
\n
"
" channel_change channel number %d
\n
"
" show player_window
\n
"
"end tell"
,
theChannelNum
];
script
=
[[
NSAppleScript
alloc
]
initWithSource
:
channel_change
];
}
...
...
modules/gui/macosx/open.m
View file @
36868ee9
...
...
@@ -83,7 +83,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class )
p_list
=
[
NSMutableArray
arrayWithCapacity
:
1
];
next_media
=
IOIteratorNext
(
media_iterator
);
if
(
next_media
!=
nil
)
if
(
next_media
)
{
char
psz_buf
[
0x32
];
size_t
dev_path_length
;
...
...
@@ -116,7 +116,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class )
IOObjectRelease
(
next_media
);
}
while
(
(
next_media
=
IOIteratorNext
(
media_iterator
)
)
!=
nil
);
}
while
(
(
next_media
=
IOIteratorNext
(
media_iterator
)
)
);
}
IOObjectRelease
(
media_iterator
);
...
...
@@ -237,11 +237,14 @@ static VLCOpen *_o_sharedMainInstance = nil;
/* wake up with the correct EyeTV GUI */
if
(
[[[
VLCMain
sharedInstance
]
getEyeTVController
]
isEyeTVrunning
]
==
YES
)
[
o_eyetv_tabView
selectTabViewItemWithIdentifier
:
@"nodevice"
];
else
if
(
[[[
VLCMain
sharedInstance
]
getEyeTVController
]
isDeviceConnected
]
==
YES
)
{
[
o_eyetv_tabView
selectTabViewItemWithIdentifier
:
@"eyetvup"
];
[
self
setupChannelInfo
];
if
(
[[[
VLCMain
sharedInstance
]
getEyeTVController
]
isDeviceConnected
]
==
YES
)
{
[
o_eyetv_tabView
selectTabViewItemWithIdentifier
:
@"eyetvup"
];
[
self
setupChannelInfo
];
}
else
[
o_eyetv_tabView
selectTabViewItemWithIdentifier
:
@"nodevice"
];
}
else
[
o_eyetv_tabView
selectTabViewItemWithIdentifier
:
@"noeyetv"
];
...
...
@@ -411,6 +414,10 @@ static VLCOpen *_o_sharedMainInstance = nil;
{
[
self
openNetInfoChanged
:
nil
];
}
else
if
(
[
o_label
isEqualToString
:
_NS
(
"EyeTV"
)]
)
{
[
o_mrl
setStringValue
:
@"eyetv://"
];
}
}
-
(
void
)
openFileGeneric
...
...
@@ -797,12 +804,23 @@ static VLCOpen *_o_sharedMainInstance = nil;
-
(
IBAction
)
eyetvSwitchChannel
:(
id
)
sender
{
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
)
[
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
)
[[[
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
msg_Err
(
VLCIntf
,
"eyetvSwitchChannel sent by unknown object"
);
}
...
...
@@ -865,9 +883,6 @@ static VLCOpen *_o_sharedMainInstance = nil;
if
(
channels
)
{
NSString
*
channel
;
[[[
o_eyetv_channels_pop
menu
]
addItemWithTitle
:
_NS
(
"Tuner"
)
action:
nil
keyEquivalent:
@""
]
setTag
:
x
++
];
[[
o_eyetv_channels_pop
menu
]
addItem
:
[
NSMenuItem
separatorItem
]];
while
(
channel
=
[
channels
nextObject
]
)
{
...
...
@@ -875,7 +890,7 @@ static VLCOpen *_o_sharedMainInstance = nil;
* additionally, we save a bit of time */
[[[
o_eyetv_channels_pop
menu
]
addItemWithTitle
:
channel
action:
nil
keyEquivalent:
@""
]
setTag
:
x
++
];
keyEquivalent:
@""
]
setTag
:
++
x
];
}
/* make Tuner the default */
[
o_eyetv_channels_pop
selectItemWithTag
:[[[
VLCMain
sharedInstance
]
getEyeTVController
]
currentChannel
]];
...
...
@@ -884,8 +899,6 @@ static VLCOpen *_o_sharedMainInstance = nil;
/* clean up GUI */
[
o_eyetv_chn_bgbar
setHidden
:
YES
];
[
o_eyetv_chn_status_txt
setHidden
:
YES
];
[
o_mrl
setStringValue
:
@"eyetv:"
];
}
-
(
IBAction
)
subsChanged
:(
id
)
sender
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment