* forward-port of all eyetv relates sources in my branch
[vlc.git] / extras / MacOSX / eyetvplugin / eyetvplugin.c
1 /*****************************************************************************\r
2 * eyetvplugin.c: Plug-In for the EyeTV software to connect to VLC\r
3 *****************************************************************************\r
4 * Copyright (C) 2006-2007 the VideoLAN team\r
5 * $Id$\r
6 *\r
7 * Authors: Felix K├╝hne <fkuehne at videolan dot org>\r
8 *\r
9 * This program is free software; you can redistribute it and/or modify\r
10 * it under the terms of the GNU General Public License as published by\r
11 * the Free Software Foundation; either version 2 of the License, or\r
12 * (at your option) any later version.\r
13 *\r
14 * This program is distributed in the hope that it will be useful,\r
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17 * GNU General Public License for more details.\r
18 *\r
19 * You should have received a copy of the GNU General Public License\r
20 * along with this program; if not, write to the Free Software\r
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.\r
22 *****************************************************************************/\r
23 \r
24 #include "eyetvplugin.h"\r
25 \r
26 #define MAX_PIDS                        256\r
27 #define MAX_ACTIVE_PIDS         256\r
28 #define MAX_DEVICES                     16\r
29 #define VLC_NOTIFICATION_OBJECT "VLCEyeTVSupport"\r
30 \r
31 #pragma push\r
32 #pragma pack(1)\r
33 \r
34 \r
35 /* Structure for TS-Packets */\r
36 typedef struct \r
37 {\r
38         unsigned long                   sync_byte : 8,\r
39                                                         transport_error_indicator : 1,\r
40                                                         payload_unit_start_indicator : 1,\r
41                                                         transport_priority : 1,\r
42                                                         PID : 13,\r
43                                                         transport_scrambling_control : 2,\r
44                                                         adaptation_field_control : 2,\r
45                                                         continuity_counter : 4;\r
46 \r
47         unsigned char                   data[188-4];\r
48 \r
49 } TransportStreamPacket;\r
50 \r
51 #pragma pop\r
52 \r
53 \r
54 /* Structure to hold Information on devices */\r
55 typedef struct\r
56 {\r
57         EyeTVPluginDeviceID                     deviceID;\r
58         EyeTVPluginDeviceType           deviceType;\r
59 \r
60         long                                            headendID;\r
61         long                                            transponderID;\r
62         long                                            serviceID;\r
63 \r
64         long                                            pidsCount;\r
65         long                                            pids[MAX_PIDS];\r
66 \r
67         EyeTVPluginPIDInfo                      activePIDs[MAX_ACTIVE_PIDS];\r
68         long                                            activePIDsCount;\r
69 \r
70 } DeviceInfo;\r
71 \r
72 \r
73 /* Structure to hold global data to communicate with EyeTV */\r
74 typedef struct \r
75 {\r
76         EyeTVPluginCallbackProc                 callback;\r
77         long                                                    deviceCount;\r
78         DeviceInfo                                              devices[MAX_DEVICES];\r
79         long long                                               packetCount;\r
80 \r
81 } VLCEyeTVPluginGlobals_t;\r
82 \r
83 /* 2nd structure to store our own global data which isn't shared with EyeTV\r
84  * a bit empty at the moment, but it will get larger as development progresses */\r
85 typedef struct\r
86 {\r
87     int                     i_deviceCount;\r
88     CFMessagePortRef        messagePortToVLC;\r
89     bool                    b_msgPortOpen;\r
90 } VLCEyeTVPluginOwnGlobals_t;\r
91 \r
92 VLCEyeTVPluginOwnGlobals_t *nativeGlobals;\r
93 \r
94 \r
95 /* return the DeviceInfo with ID deviceID */\r
96 static DeviceInfo *GetDeviceInfo(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID)\r
97 {\r
98         int i;\r
99         \r
100         if( globals ) \r
101         {\r
102                 for( i=0; i<globals->deviceCount; i++) \r
103                 {\r
104                         if( globals->devices[i].deviceID == deviceID ) \r
105                         {\r
106                                 return &globals->devices[i];\r
107                         }\r
108                 }\r
109         }\r
110 \r
111         return NULL;\r
112 }\r
113 \r
114 #pragma mark -\r
115 \r
116 /* initialise the plug-in */\r
117 static long VLCEyeTVPluginInitialize(VLCEyeTVPluginGlobals_t** globals, long apiVersion, EyeTVPluginCallbackProc callback)\r
118 {\r
119         printf("VLC media player Plug-In: Initialize\n");\r
120         long result = 0;\r
121     \r
122     /* init our own storage */\r
123     extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;\r
124     nativeGlobals = malloc( sizeof( VLCEyeTVPluginOwnGlobals_t ) );\r
125     \r
126     /* notify a potential VLC instance about our initialisation */\r
127     CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),\r
128                                           CFSTR("PluginInit"), \r
129                                           CFSTR(VLC_NOTIFICATION_OBJECT), \r
130                                           /*userInfo*/ NULL, \r
131                                           TRUE );\r
132     \r
133     /* init our notification support */\r
134     CFNotificationCenterAddObserver( CFNotificationCenterGetDistributedCenter(),\r
135                                      /* observer */ NULL, \r
136                                      /* callBack */ VLCEyeTVPluginGlobalNotificationReceived,\r
137                                      /* name, NULL==all */ NULL,\r
138                                      CFSTR(VLC_NOTIFICATION_OBJECT), \r
139                                      CFNotificationSuspensionBehaviorDeliverImmediately );\r
140         \r
141         *globals = (VLCEyeTVPluginGlobals_t *) calloc(1, sizeof( VLCEyeTVPluginGlobals_t ) );\r
142         ( *globals )->callback = callback;\r
143                 \r
144         return result;\r
145 }\r
146 \r
147 /* we will be terminated soon, clean up */\r
148 static long VLCEyeTVPluginTerminate(VLCEyeTVPluginGlobals_t *globals)\r
149 {\r
150     extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;\r
151     \r
152         printf("VLC media player Plug-In: Terminate\n");\r
153         \r
154         long result = 0;\r
155         \r
156     /* notify a potential VLC instance about our termination */\r
157     CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),\r
158                                           CFSTR("PluginQuit"), \r
159                                           CFSTR(VLC_NOTIFICATION_OBJECT), \r
160                                           /*userInfo*/ NULL, \r
161                                           TRUE );\r
162     \r
163     /* remove us from the global notification centre */\r
164     CFNotificationCenterRemoveEveryObserver( CFNotificationCenterGetDistributedCenter(),\r
165                                              (void *)VLCEyeTVPluginGlobalNotificationReceived );\r
166     \r
167     /* invalidate and free msg port */\r
168     if( nativeGlobals->messagePortToVLC )\r
169     {\r
170         CFMessagePortInvalidate( nativeGlobals->messagePortToVLC );\r
171         free( nativeGlobals->messagePortToVLC );\r
172         printf( "msgport invalidated and freed\n" );\r
173     }\r
174     else\r
175         printf( "no msgport to free\n" );\r
176     \r
177         if( globals ) \r
178         {\r
179                 free( globals );\r
180         }\r
181 \r
182     if( nativeGlobals )\r
183         free( nativeGlobals );\r
184     \r
185         return result;\r
186 }\r
187 \r
188 /* called when EyeTV asks various stuff about us */\r
189 static long VLCEyeTVPluginGetInformation(VLCEyeTVPluginGlobals_t *globals, long* outAPIVersion, char* outName, char *outDescription)\r
190 {\r
191         printf("VLC media player Plug-In: GetInfo\n");\r
192         long result = 0;\r
193         \r
194         if( globals ) \r
195         {\r
196                 if( outAPIVersion )\r
197                 {\r
198                         *outAPIVersion = EYETV_PLUGIN_API_VERSION;\r
199                 }\r
200                 \r
201                 if( outName )\r
202                 {\r
203                         char* name = "VLC media player Plug-In";\r
204                         strcpy( &outName[0], name);\r
205                 }\r
206                 \r
207                 if( outDescription )\r
208                 {\r
209                         char* desc = "This Plug-In connects EyeTV to the VLC media player for streaming purposes.";\r
210                         strcpy( &outDescription[0], desc);\r
211                 }\r
212         }\r
213         \r
214         return result;\r
215 }\r
216 \r
217 /* called if we received a global notification */\r
218 void VLCEyeTVPluginGlobalNotificationReceived( CFNotificationCenterRef center, \r
219                                               void *observer, \r
220                                               CFStringRef name, \r
221                                               const void *object, \r
222                                               CFDictionaryRef userInfo )\r
223 {\r
224     CFIndex maxlen;\r
225     char *theName, *theObject;\r
226     extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;\r
227 \r
228     maxlen = CFStringGetMaximumSizeForEncoding( CFStringGetLength( name ),\r
229                                                 kCFStringEncodingUTF8) + 1;\r
230     theName = malloc(maxlen);\r
231     CFStringGetCString( name, \r
232                         theName, \r
233                         maxlen,\r
234                         kCFStringEncodingUTF8);\r
235     \r
236     maxlen = CFStringGetMaximumSizeForEncoding( CFStringGetLength( name ),\r
237                                                 kCFStringEncodingUTF8) + 1;\r
238     theObject = malloc(maxlen);\r
239     CFStringGetCString( object, \r
240                         theObject, \r
241                         maxlen,\r
242                         kCFStringEncodingUTF8);\r
243     printf( "notication received with name: %s and object: %s\n", theName, theObject );\r
244     \r
245     /* when VLC launches after us, we need to inform it about our existance and the current state of available devices */\r
246     if( CFStringCompare( name, CFSTR( "VLCOSXGUIInit" ), 0) == kCFCompareEqualTo )\r
247     {\r
248         /* we're here */\r
249         CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),\r
250                                               CFSTR("PluginInit"), \r
251                                               CFSTR(VLC_NOTIFICATION_OBJECT), \r
252                                               /*userInfo*/ NULL, \r
253                                               TRUE );\r
254         if( nativeGlobals && ( nativeGlobals->i_deviceCount > 0 ) )\r
255         {\r
256             /* at least one device is apparently connected */\r
257             CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter (),\r
258                                                   CFSTR("DeviceAdded"), \r
259                                                   CFSTR(VLC_NOTIFICATION_OBJECT), \r
260                                                   /*userInfo*/ NULL, \r
261                                                   TRUE );\r
262         }\r
263     }\r
264     \r
265     /* VLC wants us to start sending data */\r
266     if( CFStringCompare( name, CFSTR( "VLCAccessStartDataSending" ), 0) == kCFCompareEqualTo )\r
267     {\r
268         nativeGlobals->messagePortToVLC = CFMessagePortCreateRemote( kCFAllocatorDefault,\r
269                                                                      CFSTR("VLCEyeTVMsgPort") );\r
270         if( nativeGlobals->messagePortToVLC == NULL )\r
271             printf( "getting messagePortToVLC failed!\n" );\r
272         else\r
273         {\r
274             nativeGlobals->b_msgPortOpen = TRUE;\r
275             printf( "msg port opened / data sending switched on\n" );\r
276         }\r
277     }\r
278     \r
279     /* VLC wants us to stop sending data */\r
280     if( CFStringCompare( name, CFSTR( "VLCAccessStopDataSending" ), 0) == kCFCompareEqualTo )\r
281     {\r
282         nativeGlobals->b_msgPortOpen = FALSE;\r
283         printf( "data sending switched off\n" );\r
284     }\r
285 }\r
286 \r
287 /* called if a device is added */\r
288 static long VLCEyeTVPluginDeviceAdded(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID, EyeTVPluginDeviceType deviceType)\r
289 {\r
290         printf("VLC media player Plug-In: Device with type %i and ID %i added\n", (int)deviceType, (int)deviceID);\r
291     \r
292         long result = 0;\r
293         DeviceInfo *deviceInfo;\r
294     extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;\r
295     \r
296         \r
297         if( globals ) \r
298         {\r
299                 if( globals->deviceCount < MAX_DEVICES ) \r
300                 {\r
301                         deviceInfo = &( globals->devices[globals->deviceCount] );\r
302                         memset(deviceInfo, 0, sizeof(DeviceInfo));\r
303                         \r
304                         deviceInfo->deviceID = deviceID;\r
305                         deviceInfo->deviceType = deviceType;\r
306 \r
307                         globals->deviceCount++;\r
308 \r
309             if( nativeGlobals )\r
310                 nativeGlobals->i_deviceCount = globals->deviceCount;\r
311 \r
312             /* notify a potential VLC instance about the addition */\r
313             CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),\r
314                                                   CFSTR("DeviceAdded"), \r
315                                                   CFSTR(VLC_NOTIFICATION_OBJECT), \r
316                                                   /*userInfo*/ NULL, \r
317                                                   TRUE );\r
318                 }\r
319         }\r
320 \r
321         return result;\r
322 }\r
323 \r
324 /* called if a device is removed */\r
325 static long VLCEyeTVPluginDeviceRemoved(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID)\r
326 {\r
327         printf("VLC media player Plug-In: DeviceRemoved\n");\r
328     \r
329     extern VLCEyeTVPluginOwnGlobals_t *nativeGlobals;\r
330         long result = 0;\r
331         int i;\r
332         \r
333         if( globals ) \r
334         {\r
335                 for( i = 0; i < globals->deviceCount; i++ )\r
336                 {\r
337                         if ( globals->devices[i].deviceID == deviceID ) \r
338                         {\r
339                                 globals->deviceCount--;\r
340 \r
341                                 if( i<globals->deviceCount )\r
342                                 {\r
343                                         globals->devices[i] = globals->devices[globals->deviceCount];\r
344                                 }\r
345                 \r
346                 if( nativeGlobals )\r
347                     nativeGlobals->i_deviceCount = globals->deviceCount;\r
348                 \r
349                 /* notify a potential VLC instance about the removal */\r
350                 CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),\r
351                                                       CFSTR("DeviceRemoved"), \r
352                                                       CFSTR(VLC_NOTIFICATION_OBJECT), \r
353                                                       /*userInfo*/ NULL, \r
354                                                       TRUE );\r
355                         }\r
356                 }\r
357         }\r
358         \r
359         return result;\r
360 }\r
361 \r
362 /* This function is called, whenever packets are received by EyeTV. For reasons of performance,\r
363  * the data is the original data, not a copy. That means, EyeTV waits until this method is \r
364  * finished. Therefore all in this method should be as fast as possible. */\r
365 int i=0;\r
366 static long VLCEyeTVPluginPacketsArrived(VLCEyeTVPluginGlobals_t *globals, EyeTVPluginDeviceID deviceID, long **packets, long packetsCount)\r
367 {\r
368         long                                result = 0;\r
369         int                                 i, j, isNewPID;\r
370         TransportStreamPacket               *packet;\r
371     extern VLCEyeTVPluginOwnGlobals_t   *nativeGlobals;\r
372     SInt32                              i_returnValue;\r
373     CFMutableDataRef                    theMutableRef;\r
374     uint8_t                             *p_bufferForSending = malloc(4);\r
375     bool                                b_nonSendData;\r
376     int                                 i_lastSentPacket;\r
377     \r
378     if( globals && nativeGlobals ) \r
379         {\r
380                 DeviceInfo *deviceInfo = GetDeviceInfo(globals, deviceID);\r
381 \r
382                 if( deviceInfo ) \r
383                 {\r
384             /* alloc the buffer if wanted */\r
385             if( nativeGlobals->b_msgPortOpen == TRUE )\r
386                 theMutableRef = CFDataCreateMutable( kCFAllocatorDefault, (188) );\r
387             \r
388             for( i = 0; i < packetsCount; i++ ) \r
389                         {\r
390                                 packet = ( TransportStreamPacket* )packets[i];\r
391                                 isNewPID = 1;\r
392                                 \r
393                                 /* search for PID */\r
394                                 for( j = 0; j < deviceInfo->pidsCount; j++ ) \r
395                                 {\r
396                                         if( packet->PID == deviceInfo->pids[j] ) \r
397                                         {\r
398                                                 isNewPID = 0;\r
399                                                 break;\r
400                                         }\r
401                                 }\r
402                 \r
403                                 /* add new PIDs to the DeviceInfo */\r
404                                 if( isNewPID ) \r
405                                 {\r
406                                         printf ("VLC media player Plug-In: SamplePacketsArrived, newPID = %6d\n", packet->PID);\r
407                                         \r
408                                         if( deviceInfo->pidsCount < MAX_PIDS ) \r
409                                         {\r
410                                                 deviceInfo->pids[deviceInfo->pidsCount++] = packet->PID;\r
411                                         }\r
412                                 }\r
413                                 else\r
414                 {\r
415                     /* forward data to VLC if wanted */\r
416                     /* FIXME: we only receive ARD for now */\r
417                     if( nativeGlobals->b_msgPortOpen == TRUE && (\r
418                         packet->PID == 1401 ||\r
419                         packet->PID == 1402 ||\r
420                         packet->PID == 1400 ||\r
421                         packet->PID == 1404 ||\r
422                         packet->PID == 3070 ||\r
423                         packet->PID == 3072 ||\r
424                         packet->PID == 3074 ||\r
425                         packet->PID == 5074 ||\r
426                         packet->PID == 0 ||\r
427                         packet->PID == 17 ||\r
428                         packet->PID == 19 ||\r
429                         packet->PID == 20 ) )\r
430                     {\r
431                         /* in a good world, this wouldn't be necessary */\r
432                         if( theMutableRef == NULL )\r
433                             theMutableRef = CFDataCreateMutable( kCFAllocatorDefault, (188) );\r
434                             \r
435                         /* collect data to send larger packets */\r
436                         \r
437                         /* enlarge buffer if necessary */\r
438                         if( i > 0 )\r
439                             CFDataIncreaseLength( theMutableRef, 188 );\r
440                         \r
441                         /* add missing header */\r
442                         memcpy( p_bufferForSending, packet, 4 );\r
443                         CFDataAppendBytes( theMutableRef, p_bufferForSending, sizeof(p_bufferForSending) );\r
444 \r
445                         free( p_bufferForSending );\r
446                         p_bufferForSending = malloc(4);\r
447                         \r
448                         /* add payload */\r
449                         CFDataAppendBytes( theMutableRef, packet->data, sizeof(packet->data) );\r
450                         \r
451                         b_nonSendData = TRUE;\r
452                         \r
453                     }\r
454                 }\r
455                 \r
456                 globals->packetCount++;\r
457                 \r
458                 if( globals->packetCount%10000 == 0 ) \r
459                     printf("->  %lld Packets received so far...\n",globals->packetCount);\r
460             }\r
461 \r
462             if( nativeGlobals->b_msgPortOpen == TRUE )\r
463             {\r
464                 printf( "sending %i bytes of data\n", CFDataGetLength( theMutableRef ) );\r
465                 i_returnValue = CFMessagePortSendRequest( nativeGlobals->messagePortToVLC,\r
466                                                           /* arbitrary int val */ globals->packetCount,\r
467                                                           /* the data */ theMutableRef,\r
468                                                           /* no timeout for sending */ 0,\r
469                                                           /* no timeout for resp */ 0,\r
470                                                           /* no resp. wanted */ NULL,\r
471                                                           NULL );\r
472                 b_nonSendData = FALSE;\r
473                 i_lastSentPacket = globals->packetCount;\r
474                 if( i_returnValue == kCFMessagePortSendTimeout )\r
475                     printf( "time out while sending\n" );\r
476                 else if( i_returnValue == kCFMessagePortReceiveTimeout )\r
477                     printf( "time out while waiting for resp\n" );\r
478                 else if( i_returnValue == kCFMessagePortIsInvalid )\r
479                 {\r
480                     /* suppress any further attemps */ \r
481                     printf( "message port is invalid!\n" );\r
482                     nativeGlobals->b_msgPortOpen = FALSE;\r
483                 }\r
484                 else if( i_returnValue == kCFMessagePortTransportError ) \r
485                     printf( "transport error while sending!\n" );\r
486                 else\r
487                 {\r
488                     //printf( "success, freeing resources\n" );\r
489                     free( theMutableRef );\r
490                     theMutableRef = CFDataCreateMutable( kCFAllocatorDefault, (188) );\r
491                 }\r
492             }\r
493 \r
494         }\r
495         }\r
496     else\r
497         printf( "warning: either globals or nativeGlobals are NIL in VLCEyeTVPluginPacketsArrived" );\r
498 \r
499     /* clean up before leaving function */\r
500     //if( nativeGlobals->b_msgPortOpen == TRUE )\r
501      //   free( theMutableRef );\r
502     \r
503     free( p_bufferForSending );\r
504     \r
505         return result;\r
506 }\r
507 \r
508 /*      VLCEyeTVPluginServiceChanged,\r
509  *\r
510  *      - *globals              : The plug-in Globals\r
511  *      - deviceID              : Identifies the active Device\r
512  *   - headendID                : The HeadendID, for e300 it's the orbital position of the satelite in \r
513  *                                        tenth degrees east\r
514  *   - transponderID : The Frequency in kHz\r
515  *   - serviceID                : original ServiceID from the DVB-Stream (e300, e400)\r
516  *      - pidList               : List of active PIDs   \r
517  *\r
518  *      Whenever a service changes, this function is called. Service-related plug-in data should be updated here.\r
519  */\r
520 static long VLCEyeTVPluginServiceChanged(VLCEyeTVPluginGlobals_t *globals, \r
521                                                                                         EyeTVPluginDeviceID deviceID, \r
522                                                                                         long headendID, \r
523                                                                                         long transponderID, \r
524                                                                                         long serviceID, \r
525                                                                                         EyeTVPluginPIDInfo *pidList, \r
526                                                                                         long pidsCount)\r
527 {\r
528         long result = 0;\r
529         int     i;\r
530         \r
531         printf("\nVLC media player Plug-In: ServiceChanged:\n");\r
532         printf(  "=====================================\n");\r
533         \r
534         if( globals ) \r
535         {\r
536                 DeviceInfo *deviceInfo = GetDeviceInfo( globals, deviceID );\r
537                 if( deviceInfo ) \r
538                 {\r
539                         deviceInfo->headendID = headendID;\r
540                         printf("HeadendID: %ld, ", headendID);\r
541                         \r
542                         deviceInfo->transponderID = transponderID;\r
543                         printf("TransponderID: %ld, ", transponderID);\r
544                         \r
545                         deviceInfo->serviceID = serviceID;\r
546                         printf("ServiceID: %ld\n\n", serviceID);\r
547                         \r
548                         deviceInfo->activePIDsCount = pidsCount;\r
549 \r
550                         for( i = 0; i < pidsCount; i++ )\r
551                         {\r
552                                 deviceInfo->activePIDs[i] = pidList[i];\r
553                                 printf("Active PID: %ld, type: %ld\n", pidList[i].pid, pidList[i].pidType);\r
554                         }\r
555 \r
556                         deviceInfo->pidsCount = 0;\r
557                         \r
558                 }\r
559         }\r
560         printf(  "=====================================\n");\r
561         \r
562     /* notify a potential VLC instance about the service change */\r
563     CFNotificationCenterPostNotification( CFNotificationCenterGetDistributedCenter(),\r
564                                           CFSTR("ServiceChanged"), \r
565                                           CFSTR(VLC_NOTIFICATION_OBJECT), \r
566                                           /*userInfo*/ NULL, \r
567                                           TRUE );\r
568     \r
569     return result;\r
570 }\r
571 \r
572 \r
573 #pragma mark -\r
574 /* EyeTVPluginDispatcher,\r
575  *\r
576  *      - selector : See 'EyeTVPluginDefs.h'\r
577  *      - *refCon :  The RefCon to the plug-in-related Data\r
578  *      - deviceID : Identifies the Device\r
579  *      - params : Parameters for functioncall\r
580  *\r
581  * This function is a part of the interface for the communication with EyeTV. If something happens,\r
582  * EyeTV thinks, we should know of, it calls this function with the corresponding selector. */\r
583 \r
584 #pragma export on\r
585 \r
586 long EyeTVPluginDispatcher( EyeTVPluginParams* params )\r
587 {\r
588         long result = 0;\r
589 \r
590         switch( params->selector ) \r
591         {\r
592                 case kEyeTVPluginSelector_Initialize:\r
593                         result = VLCEyeTVPluginInitialize((VLCEyeTVPluginGlobals_t**)params->refCon, \r
594                                                                         params->initialize.apiVersion, params->initialize.callback);\r
595                         break;\r
596                         \r
597                 case kEyeTVPluginSelector_Terminate:\r
598                         result = VLCEyeTVPluginTerminate((VLCEyeTVPluginGlobals_t*)params->refCon);\r
599                         break;\r
600 \r
601                 case kEyeTVPluginSelector_GetInfo:\r
602                         result = VLCEyeTVPluginGetInformation((VLCEyeTVPluginGlobals_t*)params->refCon, \r
603                                                                         params->info.pluginAPIVersion, params->info.pluginName, params->info.description);\r
604                         break;\r
605 \r
606                 case kEyeTVPluginSelector_DeviceAdded:\r
607                         result = VLCEyeTVPluginDeviceAdded((VLCEyeTVPluginGlobals_t*)params->refCon, \r
608                                                                         params->deviceID, params->deviceAdded.deviceType);\r
609                         break;\r
610                 \r
611                 case kEyeTVPluginSelector_DeviceRemoved:\r
612                         result = VLCEyeTVPluginDeviceRemoved((VLCEyeTVPluginGlobals_t*)params->refCon, params->deviceID);\r
613                         break;\r
614 \r
615                 case kEyeTVPluginSelector_PacketsArrived:\r
616                         result = VLCEyeTVPluginPacketsArrived((VLCEyeTVPluginGlobals_t*)params->refCon, params->deviceID, \r
617                                                                         params->packetsArrived.packets, params->packetsArrived.packetCount);\r
618                         break;\r
619 \r
620                 case kEyeTVPluginSelector_ServiceChanged:\r
621                         result = VLCEyeTVPluginServiceChanged((VLCEyeTVPluginGlobals_t*)params->refCon, \r
622                                                                         params->deviceID, params->serviceChanged.headendID, \r
623                                                                         params->serviceChanged.transponderID, params->serviceChanged.serviceID, \r
624                                                                         params->serviceChanged.pidList, params->serviceChanged.pidCount);\r
625                         break;\r
626         }\r
627 \r
628         return result;\r
629 }\r