d3drm: Implement IDirect3DRMMesh_AddGroup.
[wine] / dlls / wineqtdecoder / qtdatahandler.c
1 /*
2  * QuickTime Data Handler
3  *
4  * Copyright 2011 Aric Stewart for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #define ULONG CoreFoundation_ULONG
24 #define HRESULT CoreFoundation_HRESULT
25
26 #define LoadResource __carbon_LoadResource
27 #define CompareString __carbon_CompareString
28 #define GetCurrentThread __carbon_GetCurrentThread
29 #define GetCurrentProcess __carbon_GetCurrentProcess
30 #define AnimatePalette __carbon_AnimatePalette
31 #define EqualRgn __carbon_EqualRgn
32 #define FillRgn __carbon_FillRgn
33 #define FrameRgn __carbon_FrameRgn
34 #define GetPixel __carbon_GetPixel
35 #define InvertRgn __carbon_InvertRgn
36 #define LineTo __carbon_LineTo
37 #define OffsetRgn __carbon_OffsetRgn
38 #define PaintRgn __carbon_PaintRgn
39 #define Polygon __carbon_Polygon
40 #define ResizePalette __carbon_ResizePalette
41 #define SetRectRgn __carbon_SetRectRgn
42
43 #define CheckMenuItem __carbon_CheckMenuItem
44 #define DeleteMenu __carbon_DeleteMenu
45 #define DrawMenuBar __carbon_DrawMenuBar
46 #define EnableMenuItem __carbon_EnableMenuItem
47 #define EqualRect __carbon_EqualRect
48 #define FillRect __carbon_FillRect
49 #define FrameRect __carbon_FrameRect
50 #define GetCursor __carbon_GetCursor
51 #define GetMenu __carbon_GetMenu
52 #define InvertRect __carbon_InvertRect
53 #define IsWindowVisible __carbon_IsWindowVisible
54 #define MoveWindow __carbon_MoveWindow
55 #define OffsetRect __carbon_OffsetRect
56 #define PtInRect __carbon_PtInRect
57 #define SetCursor __carbon_SetCursor
58 #define SetRect __carbon_SetRect
59 #define ShowCursor __carbon_ShowCursor
60 #define ShowWindow __carbon_ShowWindow
61 #define UnionRect __carbon_UnionRect
62
63 #include <QuickTime/QuickTimeComponents.h>
64
65 #undef LoadResource
66 #undef CompareString
67 #undef GetCurrentThread
68 #undef _CDECL
69 #undef DPRINTF
70 #undef GetCurrentProcess
71 #undef AnimatePalette
72 #undef EqualRgn
73 #undef FillRgn
74 #undef FrameRgn
75 #undef GetPixel
76 #undef InvertRgn
77 #undef LineTo
78 #undef OffsetRgn
79 #undef PaintRgn
80 #undef Polygon
81 #undef ResizePalette
82 #undef SetRectRgn
83 #undef CheckMenuItem
84 #undef DeleteMenu
85 #undef DrawMenuBar
86 #undef EnableMenuItem
87 #undef EqualRect
88 #undef FillRect
89 #undef FrameRect
90 #undef GetCursor
91 #undef GetMenu
92 #undef InvertRect
93 #undef IsWindowVisible
94 #undef MoveWindow
95 #undef OffsetRect
96 #undef PtInRect
97 #undef SetCursor
98 #undef SetRect
99 #undef ShowCursor
100 #undef ShowWindow
101 #undef UnionRect
102
103 #undef ULONG
104 #undef HRESULT
105 #undef DPRINTF
106 #undef STDMETHODCALLTYPE
107
108 #include <assert.h>
109 #include <stdio.h>
110 #include <stdarg.h>
111
112 #define NONAMELESSSTRUCT
113 #define NONAMELESSUNION
114 #define COBJMACROS
115
116 #include "windef.h"
117 #include "winbase.h"
118 #include "wtypes.h"
119 #include "winuser.h"
120 #include "dshow.h"
121
122 #include <assert.h>
123
124 #include "wine/unicode.h"
125 #include "wine/debug.h"
126
127 #include "qtprivate.h"
128
129 WINE_DEFAULT_DEBUG_CHANNEL(qtdatahandler);
130
131 static ComponentDescription myType =
132 {
133     'dhlr',
134     'WINE',
135     'WINE',
136     0,
137     0
138 };
139
140 typedef struct DHData
141 {
142     WineDataRefRecord dataRef;
143
144    Ptr AsyncPtr;
145    long AsyncRefCon;
146    DataHCompletionUPP AsyncCompletionRtn;
147 } DHData;
148
149 static pascal ComponentResult myComponentRoutineProc ( ComponentParameters *
150 cp, Handle componentStorage);
151
152 void RegisterWineDataHandler( void )
153 {
154     ComponentRoutineUPP MyComponentRoutineUPP;
155
156     MyComponentRoutineUPP = NewComponentRoutineUPP(&myComponentRoutineProc);
157     RegisterComponent( &myType , MyComponentRoutineUPP, 0, NULL, NULL, NULL);
158 }
159
160 static pascal ComponentResult myDataHCanUseDataRef ( DataHandler dh,
161                                        Handle dataRef,
162                                        long *useFlags
163 )
164 {
165     WineDataRefRecord *record = (WineDataRefRecord*)(*dataRef);
166     TRACE("%p %p %p\n",dh,dataRef,useFlags);
167     if (record->pReader == NULL)
168         return badComponentSelector;
169     *useFlags = kDataHCanRead;
170     return noErr;
171 }
172
173 static pascal ComponentResult myDataHSetDataRef ( DataHandler dh, Handle dataRef)
174 {
175     Handle storage = GetComponentInstanceStorage(dh);
176     DHData *data = (DHData*)*storage;
177     WineDataRefRecord* newRef = (WineDataRefRecord*)(*dataRef);
178     TRACE("\n");
179     if (newRef->pReader != data->dataRef.pReader)
180         IAsyncReader_AddRef(newRef->pReader);
181     data->dataRef = *newRef;
182     return noErr;
183 }
184
185 static pascal ComponentResult myDataHGetAvailableFileSize ( DataHandler dh,
186                                                    long *fileSize)
187 {
188     Handle storage = GetComponentInstanceStorage(dh);
189     DHData *data = (DHData*)*storage;
190     LONGLONG total;
191     LONGLONG available;
192
193     TRACE("%p\n",dh);
194
195     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
196     *fileSize = available;
197     return noErr;
198 }
199
200 static pascal ComponentResult myDataHGetFileSize ( DataHandler dh, long *fileSize)
201 {
202     Handle storage = GetComponentInstanceStorage(dh);
203     DHData *data = (DHData*)*storage;
204     LONGLONG total;
205     LONGLONG available;
206
207     TRACE("%p\n",dh);
208
209     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
210     *fileSize = total;
211     return noErr;
212 }
213
214 static pascal ComponentResult myDataHScheduleData ( DataHandler dh,
215                                              Ptr PlaceToPutDataPtr,
216                                              long FileOffset,
217                                              long DataSize,
218                                              long RefCon,
219                                              DataHSchedulePtr scheduleRec,
220                                              DataHCompletionUPP CompletionRtn)
221 {
222     Handle storage = GetComponentInstanceStorage(dh);
223     DHData *data = (DHData*)*storage;
224     HRESULT hr;
225     LONGLONG offset = FileOffset;
226     BYTE* buffer = (BYTE*)PlaceToPutDataPtr;
227
228     TRACE("%p %p %li %li %li %p %p\n",dh, PlaceToPutDataPtr, FileOffset, DataSize, RefCon, scheduleRec, CompletionRtn);
229
230     hr = IAsyncReader_SyncRead(data->dataRef.pReader, offset, DataSize, buffer);
231     TRACE("result %x\n",hr);
232     if (CompletionRtn)
233     {
234         if (data->AsyncCompletionRtn)
235             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
236
237         data->AsyncPtr = PlaceToPutDataPtr;
238         data->AsyncRefCon = RefCon;
239         data->AsyncCompletionRtn = CompletionRtn;
240     }
241
242     return noErr;
243 }
244
245 static pascal ComponentResult myDataHFinishData (DataHandler dh, Ptr PlaceToPutDataPtr, Boolean Cancel)
246 {
247     Handle storage = GetComponentInstanceStorage(dh);
248     DHData *data = (DHData*)*storage;
249     if (!data->AsyncCompletionRtn)
250         return noErr;
251     if (!PlaceToPutDataPtr || PlaceToPutDataPtr == data->AsyncPtr)
252     {
253         if (!Cancel)
254             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
255         data->AsyncPtr = NULL;
256         data->AsyncRefCon = 0;
257         data->AsyncCompletionRtn = NULL;
258     }
259     return noErr;
260 }
261
262 static pascal ComponentResult myDataHGetData ( DataHandler dh,
263                                         Handle h,
264                                         long hOffset,
265                                         long offset,
266                                         long size)
267 {
268     Handle storage = GetComponentInstanceStorage(dh);
269     DHData *data = (DHData*)*storage;
270     BYTE *target = (BYTE*)*h;
271     LONGLONG off = offset;
272     HRESULT hr;
273
274     TRACE("%p %p %li %li %li\n",dh, h, hOffset, offset, size);
275     hr = IAsyncReader_SyncRead(data->dataRef.pReader, off, size, target+hOffset);
276     TRACE("result %x\n",hr);
277
278     return noErr;
279 }
280
281 static pascal ComponentResult myDataHCompareDataRef ( DataHandler dh,
282                                                Handle dataRef, Boolean *equal)
283 {
284     WineDataRefRecord *ptr1;
285     Handle storage = GetComponentInstanceStorage(dh);
286     DHData *data = (DHData*)*storage;
287     TRACE("\n");
288
289     ptr1 = (WineDataRefRecord*)dataRef;
290
291     *equal = (ptr1->pReader == data->dataRef.pReader);
292     return noErr;
293 }
294
295 static pascal ComponentResult myDataHGetDataRef ( DataHandler dh, Handle *dataRef)
296 {
297     Handle storage = GetComponentInstanceStorage(dh);
298     TRACE("\n");
299     *dataRef = storage;
300     HandToHand(dataRef);
301     return noErr;
302 }
303
304 static pascal ComponentResult myDataHGetScheduleAheadTime ( DataHandler dh,
305                                                        long *millisecs)
306 {
307     TRACE("\n");
308     *millisecs = 1000;
309     return noErr;
310 }
311
312 static pascal ComponentResult myDataHGetInfoFlags ( DataHandler dh, UInt32 *flags)
313 {
314     TRACE("\n");
315     *flags = 0;
316     return noErr;
317 }
318
319 static pascal ComponentResult myDataHGetFileTypeOrdering ( DataHandler dh,
320                            DataHFileTypeOrderingHandle *orderingListHandle)
321 {
322     OSType orderlist[1] = {kDataHFileTypeExtension};
323     TRACE("\n");
324     PtrToHand( &orderlist, (Handle*)orderingListHandle, sizeof(OSType));
325     return noErr;
326 }
327
328 typedef struct {
329     const CFStringRef fname;
330     const int sig_length;
331     const BYTE sig[10];
332 } signature;
333
334 static const signature stream_sigs[] = {
335     {CFSTR("video.asf"),4,{0x30,0x26,0xb2,0x75}},
336     {CFSTR("video.mov"),8,{0x00,0x00,0x00,0x14,0x66,0x74,0x79,0x70}},
337     {CFSTR("video.mp4"),8,{0x00,0x00,0x00,0x18,0x66,0x74,0x79,0x70}},
338     {CFSTR("video.m4v"),8,{0x00,0x00,0x00,0x1c,0x66,0x74,0x79,0x70}},
339     {CFSTR("video.flv"),4,{0x46,0x4C,0x56,0x01}},
340     {CFSTR("video.mpg"),3,{0x00,0x00,0x01}},
341     {CFSTR("avideo.rm"),4,{0x2E,0x52,0x4D,0x46}}
342 };
343
344 static pascal ComponentResult myDataHGetFileName ( DataHandler dh, Str255 str)
345 {
346     Handle storage = GetComponentInstanceStorage(dh);
347     DHData *data = (DHData*)*storage;
348     TRACE("%p %s\n",str,debugstr_guid(&data->dataRef.streamSubtype));
349
350     /* Todo Expand this list */
351     if (IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_MPEG1Video) ||
352         IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_MPEG1System))
353         CFStringGetPascalString(CFSTR("video.mpg"),str,256,kCFStringEncodingMacRoman);
354     else if(IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_Asf))
355         CFStringGetPascalString(CFSTR("video.asf"),str,256,kCFStringEncodingMacRoman);
356     else if(IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_Avi))
357         CFStringGetPascalString(CFSTR("video.avi"),str,256,kCFStringEncodingMacRoman);
358     else if(IsEqualIID(&data->dataRef.streamSubtype, &MEDIASUBTYPE_QTMovie))
359         CFStringGetPascalString(CFSTR("video.mov"),str,256,kCFStringEncodingMacRoman);
360     else
361     {
362         BYTE header[10] = {0,0,0,0,0,0,0,0,0,0};
363         int i;
364         IAsyncReader_SyncRead(data->dataRef.pReader, 0, 8, header);
365
366         for (i=0; i < sizeof(stream_sigs)/sizeof(signature); i++)
367             if (memcmp(header, stream_sigs[i].sig, stream_sigs[i].sig_length)==0)
368             {
369                 CFStringGetPascalString(stream_sigs[i].fname,str,256,kCFStringEncodingMacRoman);
370                 return noErr;
371             }
372
373         return badComponentSelector;
374     }
375
376     return noErr;
377 }
378
379 static pascal ComponentResult myDataHOpenForRead(DataHandler dh)
380 {
381     TRACE("\n");
382     return noErr;
383 }
384
385 static pascal ComponentResult myDataHTask(DataHandler dh)
386 {
387     Handle storage = GetComponentInstanceStorage(dh);
388     DHData *data = (DHData*)*storage;
389
390     if (data->AsyncCompletionRtn)
391     {
392         TRACE("Sending Completion\n");
393         InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
394         data->AsyncPtr = NULL;
395         data->AsyncRefCon = 0;
396         data->AsyncCompletionRtn = NULL;
397     }
398     return noErr;
399 }
400
401 static pascal ComponentResult myDataHPlaybackHints(DataHandler dh, long flags,
402                 unsigned long minFileOffset, unsigned long maxFileOffset,
403                 long bytesPerSecond)
404 {
405     TRACE("%lu %lu %li\n",minFileOffset, maxFileOffset, bytesPerSecond);
406     return noErr;
407 }
408
409 static pascal ComponentResult myDataHPlaybackHints64(DataHandler dh, long flags,
410                 wide *minFileOffset, wide *maxFileOffset,
411                 long bytesPerSecond)
412 {
413     if (TRACE_ON(qtdatahandler))
414     {
415         SInt64 minFileOffset64 = WideToSInt64(*minFileOffset);
416         LONGLONG minFileOffsetLL = minFileOffset64;
417         SInt64 maxFileOffset64 = WideToSInt64(*maxFileOffset);
418         LONGLONG maxFileOffsetLL = maxFileOffset64;
419
420         TRACE("%s %s %li\n",wine_dbgstr_longlong(minFileOffsetLL), wine_dbgstr_longlong(maxFileOffsetLL), bytesPerSecond);
421     }
422     return noErr;
423 }
424
425 static pascal ComponentResult myDataHGetFileSize64(DataHandler dh, wide * fileSize)
426 {
427     Handle storage = GetComponentInstanceStorage(dh);
428     DHData *data = (DHData*)*storage;
429     LONGLONG total;
430     LONGLONG available;
431     SInt64 total64;
432
433     TRACE("%p\n",dh);
434
435     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
436     total64 = total;
437     *fileSize = SInt64ToWide(total64);
438     return noErr;
439 }
440
441 static pascal ComponentResult myDataHGetFileSizeAsync ( DataHandler dh, wide *fileSize, DataHCompletionUPP CompletionRtn, long RefCon )
442 {
443     Handle storage = GetComponentInstanceStorage(dh);
444     DHData *data = (DHData*)*storage;
445     LONGLONG total;
446     LONGLONG avaliable;
447     SInt64 total64;
448
449     TRACE("%p\n",dh);
450
451     IAsyncReader_Length(data->dataRef.pReader,&total,&avaliable);
452     total64 = total;
453     *fileSize = SInt64ToWide(total64);
454
455     if (CompletionRtn)
456     {
457         if (data->AsyncCompletionRtn)
458             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
459
460         data->AsyncPtr = (Ptr)fileSize;
461         data->AsyncRefCon = RefCon;
462         data->AsyncCompletionRtn = CompletionRtn;
463     }
464
465     return noErr;
466 }
467
468 static pascal ComponentResult myDataHGetAvailableFileSize64(DataHandler dh, wide * fileSize)
469 {
470     Handle storage = GetComponentInstanceStorage(dh);
471     DHData *data = (DHData*)*storage;
472     LONGLONG total;
473     LONGLONG available;
474     SInt64 total64;
475
476     TRACE("%p\n",dh);
477
478     IAsyncReader_Length(data->dataRef.pReader,&total,&available);
479     total64 = available;
480     *fileSize = SInt64ToWide(total64);
481     return noErr;
482 }
483
484 static pascal ComponentResult myDataHScheduleData64( DataHandler dh,
485                                           Ptr PlaceToPutDataPtr,
486                                           const wide * FileOffset,
487                                           long DataSize,
488                                           long RefCon,
489                                           DataHSchedulePtr scheduleRec,
490                                           DataHCompletionUPP CompletionRtn)
491 {
492     Handle storage = GetComponentInstanceStorage(dh);
493     DHData *data = (DHData*)*storage;
494     HRESULT hr;
495     SInt64 fileOffset64 = WideToSInt64(*FileOffset);
496     LONGLONG offset = fileOffset64;
497     BYTE* buffer = (BYTE*)PlaceToPutDataPtr;
498
499     TRACE("%p %p %s %li %li %p %p\n",dh, PlaceToPutDataPtr, wine_dbgstr_longlong(offset), DataSize, RefCon, scheduleRec, CompletionRtn);
500
501     hr = IAsyncReader_SyncRead(data->dataRef.pReader, offset, DataSize, buffer);
502     TRACE("result %x\n",hr);
503     if (CompletionRtn)
504     {
505         if (data->AsyncCompletionRtn)
506             InvokeDataHCompletionUPP(data->AsyncPtr, data->AsyncRefCon, noErr, data->AsyncCompletionRtn);
507
508         data->AsyncPtr = PlaceToPutDataPtr;
509         data->AsyncRefCon = RefCon;
510         data->AsyncCompletionRtn = CompletionRtn;
511     }
512
513     return noErr;
514 }
515
516 static const struct { LPVOID proc; ProcInfoType type;} componentFunctions[] =
517 {
518     {NULL, 0}, /* 0 */
519     {NULL, 0}, /* 1 */
520     {myDataHGetData,  kPascalStackBased
521             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
522             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
523             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
524             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
525             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
526             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
527 }, /* kDataHGetDataSelect                        */
528     {NULL, 0}, /* kDataHPutDataSelect                        */
529     {NULL, 0}, /* kDataHFlushDataSelect                      */
530     {NULL, 0}, /* kDataHOpenForWriteSelect                   */
531     {NULL, 0}, /* kDataHCloseForWriteSelect                  */
532     {NULL, 0}, /* 7 */
533     {myDataHOpenForRead, kPascalStackBased
534             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
535             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
536 }, /* kDataHOpenForReadSelect
537 */
538     {NULL, 0}, /* kDataHCloseForReadSelect                   */
539     {myDataHSetDataRef,  kPascalStackBased
540             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
541             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
542             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
543 }, /* kDataHSetDataRefSelect                     */
544     {myDataHGetDataRef,  kPascalStackBased
545             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
546             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
547             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
548 }, /* kDataHGetDataRefSelect                     */
549     {myDataHCompareDataRef,  kPascalStackBased
550             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
551             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
552             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
553             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Boolean*)))
554 }, /* kDataHCompareDataRefSelect                 */
555     {myDataHTask, kPascalStackBased
556             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
557             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
558 }, /* kDataHTaskSelect                           */
559     {myDataHScheduleData,  kPascalStackBased
560             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
561             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
562             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
563             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long)))
564             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
565             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
566             | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(DataHSchedulePtr)))
567             | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(DataHCompletionUPP)))
568 }, /* kDataHScheduleDataSelect                   */
569     {myDataHFinishData, kPascalStackBased
570             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
571             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
572             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
573             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Boolean)))
574 }, /* kDataHFinishDataSelect                     */
575     {NULL, 0}, /* kDataHFlushCacheSelect       0x10              */
576     {NULL, 0}, /* kDataHResolveDataRefSelect                 */
577     {myDataHGetFileSize,  kPascalStackBased
578             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
579             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
580             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long*)))
581 }, /* kDataHGetFileSizeSelect                    */
582     {myDataHCanUseDataRef,  kPascalStackBased
583             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
584             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
585             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle)))
586             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long*)))
587 }, /* kDataHCanUseDataRefSelect                  */
588     {NULL, 0}, /* kDataHGetVolumeListSelect                  */
589     {NULL, 0}, /* kDataHWriteSelect                          */
590     {NULL, 0}, /* kDataHPreextendSelect                      */
591     {NULL, 0}, /* kDataHSetFileSizeSelect                    */
592     {NULL, 0}, /* kDataHGetFreeSpaceSelect                   */
593     {NULL, 0}, /* kDataHCreateFileSelect                     */
594     {NULL, 0}, /* kDataHGetPreferredBlockSizeSelect          */
595     {NULL, 0}, /* kDataHGetDeviceIndexSelect                 */
596     {NULL, 0}, /* kDataHIsStreamingDataHandlerSelect         */
597     {NULL, 0}, /* kDataHGetDataInBufferSelect                */
598     {myDataHGetScheduleAheadTime,  kPascalStackBased
599             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
600             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
601             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long*)))
602 }, /* kDataHGetScheduleAheadTimeSelect           */
603 /* End of Required List */
604     {NULL, 0}, /* kDataHSetCacheSizeLimitSelect              */
605     {NULL, 0}, /* kDataHGetCacheSizeLimitSelect       0x20   */
606     {NULL, 0}, /* kDataHGetMovieSelect                       */
607     {NULL, 0}, /* kDataHAddMovieSelect                       */
608     {NULL, 0}, /* kDataHUpdateMovieSelect                    */
609     {NULL, 0}, /* kDataHDoesBufferSelect                     */
610     {myDataHGetFileName,  kPascalStackBased
611             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
612             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
613             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Str255*)))
614 }, /* kDataHGetFileNameSelect                    */
615     {myDataHGetAvailableFileSize,   kPascalStackBased
616             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
617             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
618             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long*)))
619 }, /* kDataHGetAvailableFileSizeSelect           */
620     {NULL, 0}, /* kDataHGetMacOSFileTypeSelect               */
621     {NULL, 0}, /* kDataHGetMIMETypeSelect                    */
622     {NULL, 0}, /* kDataHSetDataRefWithAnchorSelect           */
623     {NULL, 0}, /* kDataHGetDataRefWithAnchorSelect           */
624     {NULL, 0}, /* kDataHSetMacOSFileTypeSelect               */
625     {NULL, 0}, /* kDataHSetTimeBaseSelect                    */
626     {myDataHGetInfoFlags,  kPascalStackBased
627             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
628             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
629             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(UInt32*)))
630 }, /* kDataHGetInfoFlagsSelect                   */
631     {myDataHScheduleData64, kPascalStackBased
632             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
633             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
634             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
635             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(wide*)))
636             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
637             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
638             | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(DataHSchedulePtr)))
639             | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(DataHCompletionUPP)))
640 }, /* kDataHScheduleData64Select                 */
641     {NULL, 0}, /* kDataHWrite64Select                        */
642     {myDataHGetFileSize64, kPascalStackBased
643             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
644             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
645             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(wide*)))
646 }, /* kDataHGetFileSize64Select     0x30         */
647     {NULL, 0}, /* kDataHPreextend64Select                    */
648     {NULL, 0}, /* kDataHSetFileSize64Select                  */
649     {NULL, 0}, /* kDataHGetFreeSpace64Select                 */
650     {NULL, 0}, /* kDataHAppend64Select                       */
651     {NULL, 0}, /* kDataHReadAsyncSelect                      */
652     {NULL, 0}, /* kDataHPollReadSelect                       */
653     {NULL, 0}, /* kDataHGetDataAvailabilitySelect            */
654     {NULL, 0}, /* 0x0038 */
655     {NULL, 0}, /* 0x0039 */
656     {myDataHGetFileSizeAsync, kPascalStackBased
657             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
658             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
659             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(wide*)))
660             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(DataHCompletionUPP)))
661             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
662 }, /* kDataHGetFileSizeAsyncSelect               */
663     {NULL, 0}, /* kDataHGetDataRefAsTypeSelect               */
664     {NULL, 0}, /* kDataHSetDataRefExtensionSelect            */
665     {NULL, 0}, /* kDataHGetDataRefExtensionSelect            */
666     {NULL, 0}, /* kDataHGetMovieWithFlagsSelect              */
667     {NULL, 0}, /* 0x3F */
668     {myDataHGetFileTypeOrdering, kPascalStackBased
669             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
670             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
671             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(DataHFileTypeOrderingHandle*)))
672 }, /* kDataHGetFileTypeOrderingSelect  0x40      */
673     {NULL, 0}, /* kDataHCreateFileWithFlagsSelect            */
674     {NULL, 0}, /* kDataHGetMIMETypeAsyncSelect               */
675     {NULL, 0}, /* kDataHGetInfoSelect                        */
676     {NULL, 0}, /* kDataHSetIdleManagerSelect                 */
677     {NULL, 0}, /* kDataHDeleteFileSelect                     */
678     {NULL, 0}, /* kDataHSetMovieUsageFlagsSelect             */
679     {NULL, 0}, /* kDataHUseTemporaryDataRefSelect            */
680     {NULL, 0}, /* kDataHGetTemporaryDataRefCapabilitiesSelect */
681     {NULL, 0}, /* kDataHRenameFileSelect                     */
682     {NULL, 0}, /* 0x4A */
683     {NULL, 0}, /* 0x4B */
684     {NULL, 0}, /* 0x4C */
685     {NULL, 0}, /* 0x4D */
686     {myDataHGetAvailableFileSize64, kPascalStackBased
687             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
688             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
689             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(wide*)))
690 }, /* kDataHGetAvailableFileSize64Select         */
691     {NULL, 0}, /* kDataHGetDataAvailability64Select          */
692 };
693
694 static const struct { LPVOID proc; ProcInfoType type;} componentFunctions_2[] =
695 {
696     {myDataHPlaybackHints, kPascalStackBased
697             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
698             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
699             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
700             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long)))
701             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(unsigned long)))
702             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
703 }, /* kDataHPlaybackHintsSelect     0x103 */
704     {myDataHPlaybackHints64, kPascalStackBased
705             | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult)))
706             | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(DataHandler)))
707             | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
708             | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(wide*)))
709             | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(wide*)))
710             | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(long)))
711 }, /* kDataHPlaybackHints64Select   0x10E */
712     {NULL, 0}, /* kDataHGetDataRateSelect       0x110 */
713     {NULL, 0}, /* kDataHSetTimeHintsSelect      0x111 */
714 };
715
716 /* Component Functions */
717
718 static pascal ComponentResult myComponentOpen(ComponentInstance ci, ComponentInstance self)
719 {
720     DHData myData;
721     Handle storage;
722
723     ZeroMemory(&myData,sizeof(DHData));
724     PtrToHand( &myData, &storage, sizeof(DHData));
725     SetComponentInstanceStorage(self,storage);
726
727     return noErr;
728 }
729
730 static pascal ComponentResult myComponentClose(ComponentInstance ci, ComponentInstance self)
731 {
732     Handle storage = GetComponentInstanceStorage(self);
733     DHData *data;
734     if (storage)
735     {
736         data = (DHData*)*storage;
737         if (data && data->dataRef.pReader != NULL)
738             IAsyncReader_Release(data->dataRef.pReader);
739         DisposeHandle(storage);
740         SetComponentInstanceStorage(self,NULL);
741     }
742     return noErr;
743 }
744
745 static pascal ComponentResult myComponentCanDo(ComponentInstance ci, SInt16 ftnNumber)
746 {
747     TRACE("test 0x%x\n",ftnNumber);
748     if (ftnNumber <= kComponentOpenSelect && ftnNumber >= kComponentCanDoSelect)
749         return TRUE;
750     if (ftnNumber == kDataHPlaybackHintsSelect)
751         return TRUE;
752     if (ftnNumber == kDataHPlaybackHints64Select)
753         return TRUE;
754     if (ftnNumber > kDataHGetDataAvailability64Select)
755         return FALSE;
756     TRACE("impl? %i\n",(componentFunctions[ftnNumber].proc != NULL));
757     return (componentFunctions[ftnNumber].proc != NULL);
758 }
759
760 /* Main Proc */
761
762 static ComponentResult callOurFunction(LPVOID proc, ProcInfoType type, ComponentParameters * cp)
763 {
764     ComponentRoutineUPP myUUP;
765     ComponentResult result;
766
767     myUUP = NewComponentFunctionUPP(proc, type);
768     result = CallComponentFunction(cp, myUUP);
769     DisposeComponentFunctionUPP(myUUP);
770     return result;
771 }
772
773 static pascal ComponentResult myComponentRoutineProc ( ComponentParameters * cp,
774                                          Handle componentStorage)
775 {
776     switch (cp->what)
777     {
778         case kComponentOpenSelect:
779             return callOurFunction(myComponentOpen, uppCallComponentOpenProcInfo,  cp);
780         case kComponentCloseSelect:
781             return callOurFunction(myComponentClose, uppCallComponentOpenProcInfo,  cp);
782         case kComponentCanDoSelect:
783             return callOurFunction(myComponentCanDo, uppCallComponentCanDoProcInfo,  cp);
784         case kDataHPlaybackHintsSelect:
785             return callOurFunction(componentFunctions_2[0].proc, componentFunctions_2[0].type, cp);
786         case kDataHPlaybackHints64Select:
787             return callOurFunction(componentFunctions_2[1].proc, componentFunctions_2[1].type, cp);
788     }
789
790     if (cp->what > 0 && cp->what <=kDataHGetDataAvailability64Select && componentFunctions[cp->what].proc)
791         return callOurFunction(componentFunctions[cp->what].proc, componentFunctions[cp->what].type, cp);
792
793     FIXME("unhandled select 0x%x\n",cp->what);
794     return badComponentSelector;
795 }