Some compiler warnings removed.
[cake.git] / workbench / classes / datatypes / sound / dispatch.c
blob1a60d0306d2ad78fdb77afe69c614cdaa767cdd3
1 /*
2 **
3 ** sound.datatype v41
4 ** © 1998-2004 by Stephan Rupprecht
5 ** all rights reserved
6 **
7 */
9 #if !defined(__MAXON__) && !defined(__AROS__)
10 #define CLIB_ALIB_PROTOS_H
11 #endif
13 #include <exec/memory.h>
14 #include <exec/execbase.h>
15 #include <dos/dos.h>
16 #include <dos/var.h>
17 #include <dos/dostags.h>
18 #include <dos/rdargs.h>
19 #include <graphics/gfx.h>
20 #include <graphics/gfxbase.h>
21 #include <datatypes/soundclass.h>
22 #include <datatypes/soundclassext.h>
23 #include <datatypes/datatypesclass.h>
24 #include <datatypes/pictureclass.h>
25 #include <libraries/iffparse.h>
26 #include <devices/audio.h>
27 #include <intuition/classes.h>
28 #include <intuition/gadgetclass.h>
29 #include <intuition/icclass.h>
30 #include <intuition/imageclass.h>
31 #include <intuition/intuitionbase.h>
32 #include <intuition/cghooks.h>
33 #include <devices/ahi.h>
34 #include <gadgets/tapedeck.h>
35 #include <graphics/gfxmacros.h>
36 #include <graphics/gfxbase.h>
38 #ifdef __GNUC__
39 #include <proto/dos.h>
40 #include <proto/exec.h>
41 #include <proto/iffparse.h>
42 #include <proto/graphics.h>
43 #include <proto/intuition.h>
44 #include <proto/utility.h>
45 #include <proto/datatypes.h>
46 #include <proto/ahi.h>
47 #include <clib/alib_protos.h>
48 #else
49 #include <pragma/exec_lib.h>
50 #include <pragma/intuition_lib.h>
51 #include <pragma/dos_lib.h>
52 #include <pragma/utility_lib.h>
53 #include <pragma/iffparse_lib.h>
54 #include <pragma/graphics_lib.h>
55 #include <pragma/datatypes_lib.h>
56 #include <pragma/ahi_lib.h>
57 #endif
59 #ifndef __AROS__
60 #pragma header
61 #endif
63 #include "classbase.h"
65 #ifndef __MAXON__
66 #include "CompilerSpecific.h"
67 #ifndef __AROS__
68 #include "BoopsiStubs.h"
69 #endif
70 #endif
72 #include "aiff.h"
74 #ifdef __AROS__
75 #define DEBUG 1
76 #include <aros/debug.h>
77 #endif
79 #if !defined(__MAXON__) && !defined(__AROS__)
80 #define IntuitionBase cb->cb_IntuitionBase
81 #define GfxBase cb->cb_GfxBase
82 #define DOSBase cb->cb_DOSBase
83 #define SysBase cb->cb_SysBase
84 #define DataTypesBase cb->cb_DataTypesBase
85 #define UtilityBase cb->cb_UtilityBase
86 #define IFFParseBase cb->cb_IFFParseBase
87 #elif !defined(__AROS__)
88 #define REG(r,v) register __## r v
89 #define __regargs
90 #endif
92 #define G(x) ((struct Gadget *)(x))
93 #define MAX( a, b ) ((a) > (b) ? (a) : (b))
94 #define EXTG( x ) ((struct ExtGadget *)(x))
96 #ifndef ID_CHAN
97 #define ID_CHAN MAKE_ID( 'C', 'H', 'A', 'N' )
98 #endif
99 #ifndef ID_16SV
100 #define ID_16SV MAKE_ID( '1', '6', 'S', 'V' )
101 #endif
103 #ifdef __AROS__
104 #include <aros/symbolsets.h>
105 /* Optionally open tapedeck gadget */
106 ADD2LIBS("gadgets/tapedeck.gadget", -40, struct Library *, TapeDeckBase)
107 #endif
109 #ifndef ID_PAN
110 #define ID_PAN MAKE_ID( 'P', 'A', 'N', ' ' )
111 #endif
112 #ifndef ID_ANNO
113 #define ID_ANNO MAKE_ID( 'A', 'N', 'N', 'O' )
114 #endif
115 #ifndef ID_AUTH
116 #define ID_AUTH MAKE_ID( 'A', 'U', 'T', 'H' )
117 #endif
118 #ifndef ID_FVER
119 #define ID_FVER MAKE_ID( 'F', 'V', 'E', 'R' )
120 #endif
121 #ifndef ID_Copyright
122 #define ID_Copyright MAKE_ID( '(', 'c', ')', ' ' )
123 #endif
125 #define TEMPLATE "VOLUME/N/K,BUFFERSIZE/N/K,AHI/S,AHIMODEID/K,FAM=FORCEAHIMODE/S,AMF=AHIMIXFREQ/N/K,AIFF16/S,C=COMPRESS/S," \
126 "W=WIDTH/N/K,H=HEIGHT/N/K,BG=BACKGROUNDCOLOR/K,WF=WAVEFORMCOLOR/K,CP=CONTROLPANEL/T,NOGTSLIDER/S"
128 // MaxonC likes to use 16bit math even when 020+ optimiziation is turned on (BUG!)
129 #ifdef __MAXON__
130 #define UMult( x, y ) UMult32( (x), (y) )
131 #define SMult( x, y ) SMult32( (x), (y) )
132 #define UDiv( x, y ) UDivMod32( (x), (y) )
133 #define SDiv( x, y ) SDivMod32( (x), (y) )
134 #else
135 #define UMult( x, y ) ( (x) * (y) )
136 #define SMult( x, y ) ( (x) * (y) )
137 #define UDiv( x, y ) ( (x) / (y) )
138 #define SDiv( x, y ) ( (x) / (y) )
139 #endif
141 #ifdef __AROS__
142 #define Period2Freq( x ) ( UDiv( UMult(709379, 5L ), (x) ) )
143 #else
144 #define Period2Freq( x ) ( UDiv( UMult( ((struct ExecBase *)SysBase)->ex_EClockFrequency, 5L ), (x) ) )
145 #endif
147 #define Freq2Period( x ) Period2Freq( x )
148 #define IsStereo( x ) ( (BOOL) ( ( x ) & 1 ) )
150 #ifndef SHRT_MAX
151 #define SHRT_MAX 0x7fff
152 #endif
154 //#define DEBUG
155 #ifdef DEBUG
156 #define dbug( x ) x
157 #else
158 #define dbug( x )
159 #endif
161 /****************************************************************************/
163 #ifndef __AROS__
164 IPTR Dispatcher(REG(a0,Class *cl), REG(a2,Object *o), REG(a1,Msg msg));
165 #endif
166 IPTR __regargs Sound_NEW( Class *cl, Object *o, struct opSet *ops );
167 IPTR __regargs Sound_GET( Class *cl, Object *o, struct opGet *ops );
168 IPTR __regargs Sound_SET( Class *cl, Object *o, struct opSet *ops );
169 IPTR __regargs Sound_UPDATE( Class *cl, Object *o, struct opUpdate *opu );
170 IPTR __regargs Sound_DISPOSE( Class *cl, Object *o, Msg msg );
171 IPTR __regargs Sound_RENDER( Class *cl, Object *o, struct gpRender *gpr );
172 IPTR __regargs Sound_HANDLEINPUT( Class *cl, Object *o, struct gpInput *gpi );
173 IPTR __regargs Sound_TRIGGER( Class *cl, Object *o, struct dtTrigger *dtt );
174 IPTR __regargs Sound_WRITE( Class *cl, Object *o, struct dtWrite *dtw );
175 IPTR __regargs Sound_LAYOUT( Class *cl, Object *o, struct gpLayout *gpl );
176 IPTR __regargs Sound_DOMAIN( Class *cl, Object *o, struct gpDomain *gpd );
177 LONG __regargs Sound_SELECT( Class *cl, Object *o, struct dtSelect *dts );
178 LONG __regargs Sound_CLEARSELECTED( Class *cl, Object *o, struct dtGeneral *dtg );
179 IPTR __regargs Sound_HITTEST( Class *cl, Object *o, struct gpHitTest *gpht );
180 IPTR __regargs Sound_GOINACTIVE( Class *cl, Object *o, struct gpGoInactive *gpgi );
181 IPTR __regargs Sound_DRAW( Class *cl, Object *o, struct dtDraw *dtd );
182 IPTR __regargs Sound_OBTAINDRAWINFO( Class *cl, Object *o, struct opSet *ops );
183 IPTR __regargs Sound_REMOVEDTOBJECT( Class *cl, Object *o, Msg msg );
184 IPTR __regargs Sound_RELEASEDRAWINFO( Class *cl, Object *o, Msg msg );
185 LONG __regargs hex2long( STRPTR hex );
186 BOOL __regargs parsetaglist( Class *cl, Object *o, struct opSet *ops, ULONG *cnt_p );
187 struct Process * __regargs CreatePlayerProc( struct ClassBase *cb, struct MsgPort **mp );
188 void __regargs GetSoundDTPrefs( struct ClassBase *cb );
189 struct IBox __regargs GetAbsGadgetBox( struct IBox *domain, struct ExtGadget *g, BOOL useBounds );
190 IPTR __regargs DoMemberHitTest( struct IBox *domain, Object *member, struct gpHitTest *gpht );
191 void PlayerProc( void );
192 void PlayerProcAHI( void );
193 void __regargs makeqtab( BYTE *qtab );
194 unsigned __regargs StrLen( STRPTR str );
195 IPTR propgdispatcher( REG(a0, Class *cl), REG(a2, Object *o), REG(a1, Msg msg) );
197 /****************************************************************************/
199 BYTE fibtab[] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
201 UBYTE bytesPerPoint[] = { 1, 2, 2, 4 };
203 LONG ifferr2doserr[] =
205 0L, // EOF
206 0L, // EOC
207 DTERROR_INVALID_DATA, /* No lexical scope. */
208 ERROR_NO_FREE_STORE, /* Insufficient memory. */
209 ERROR_SEEK_ERROR, /* Stream read error. */
210 ERROR_SEEK_ERROR, /* Stream write error. */
211 ERROR_SEEK_ERROR, /* Stream seek error. */
212 DTERROR_INVALID_DATA, /* File is corrupt. */
213 DTERROR_INVALID_DATA, /* IFF syntax error. */
214 ERROR_OBJECT_WRONG_TYPE,/* Not an IFF file. */
215 ERROR_REQUIRED_ARG_MISSING,/* Required call-back hook missing. */
216 0xDEADDEAD /* Return to client. You should never see this ! */
219 struct DTMethod TriggerMethods[] =
221 {"Play", "PLAY", STM_PLAY},
222 {"Stop", "STOP", STM_STOP},
223 {"Pause", "PAUSE", STM_PAUSE},
224 {(0)}
227 ULONG Methods[] = {
228 OM_NEW,
229 OM_DISPOSE,
230 OM_SET,
231 OM_GET,
232 OM_UPDATE,
233 GM_RENDER,
234 GM_LAYOUT,
235 GM_DOMAIN,
236 GM_HITTEST,
237 GM_HELPTEST,
238 GM_GOACTIVE,
239 GM_HANDLEINPUT,
240 GM_GOINACTIVE,
241 DTM_TRIGGER,
242 DTM_WRITE,
243 DTM_COPY,
244 DTM_SELECT,
245 DTM_CLEARSELECTED,
246 DTM_PROCLAYOUT,
247 DTM_REMOVEDTOBJECT,
248 DTM_OBTAINDRAWINFO,
249 DTM_DRAW,
250 DTM_RELEASEDRAWINFO,
251 ~0UL
254 #if defined(__MAXON__) || defined(__AROS__)
255 struct Library *AHIBase = NULL;
256 #endif
258 /****************************************************************************/
260 #ifdef DEBUG
261 #if !defined(__MAXON__) && !defined(__AROS__)
262 void kprintf( STRPTR FormatStr, ... )
264 #undef SysBase
265 struct Library *SysBase = (*(struct Library **)4L);
266 TEXT PutChData[64];
267 STRPTR p = PutChData;
269 RawDoFmt(FormatStr, ((STRPTR)(&FormatStr))+4, (void (*)())"\x16\xc0\x4e\x75", PutChData);
271 do RawPutChar( *p );
272 while( *p++ );
273 #define SysBase cb->cb_SysBase
275 #endif
276 #endif
278 /****************************************************************************/
279 #ifndef __AROS__
280 IPTR Dispatcher(REG(a0,Class *cl), REG(a2,Object *o), REG(a1,Msg msg))
282 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
283 IPTR retval;
285 (void)cb;
287 switch( msg->MethodID )
289 case OM_NEW:
290 retval = Sound_NEW( cl, o, (struct opSet *)msg );
291 break;
293 case OM_GET:
294 retval = Sound_GET( cl, o, (struct opGet *)msg );
295 break;
297 case OM_UPDATE:
298 retval = Sound_UPDATE( cl, o, (struct opUpdate *)msg );
299 break;
301 case OM_SET:
302 retval = Sound_SET( cl, o, (struct opSet *)msg );
303 break;
305 case OM_DISPOSE:
306 retval = Sound_DISPOSE( cl, o, msg );
307 break;
309 case GM_HELPTEST:
310 case GM_HITTEST:
311 retval = Sound_HITTEST( cl, o, (struct gpHitTest *) msg );
312 break;
314 case GM_GOACTIVE:
315 case GM_HANDLEINPUT:
316 retval = Sound_HANDLEINPUT( cl, o, (struct gpInput *)msg );
317 break;
319 case GM_GOINACTIVE:
320 retval = Sound_GOINACTIVE( cl, o, (struct gpGoInactive *) msg );
321 break;
323 case GM_DOMAIN:
324 retval = Sound_DOMAIN( cl, o, (struct gpDomain *)msg );
325 break;
327 case GM_LAYOUT:
328 case DTM_PROCLAYOUT:
329 retval = Sound_LAYOUT( cl, o, (struct gpLayout *)msg );
330 break;
332 case GM_RENDER:
333 retval = Sound_RENDER( cl, o, (struct gpRender *)msg );
334 break;
336 case DTM_TRIGGER:
337 retval = Sound_TRIGGER( cl, o, (struct dtTrigger *)msg );
338 break;
340 case DTM_COPY:
341 case DTM_WRITE:
342 retval = Sound_WRITE( cl, o, (struct dtWrite *)msg );
343 break;
345 case DTM_SELECT:
346 retval = Sound_SELECT( cl, o, (struct dtSelect *) msg );
347 break;
349 case DTM_CLEARSELECTED:
350 retval = Sound_CLEARSELECTED( cl, o, (struct dtGeneral *) msg );
351 break;
353 case DTM_OBTAINDRAWINFO:
354 retval = Sound_OBTAINDRAWINFO( cl, o, (struct opSet *) msg );
355 break;
357 case DTM_DRAW:
358 retval = Sound_DRAW( cl, o, (struct dtDraw *) msg );
359 break;
361 case DTM_RELEASEDRAWINFO:
363 dbug( kprintf( "DTM_RELEASEDRAWINFO\n" ); )
365 retval = 0L;
366 break;
368 case DTM_REMOVEDTOBJECT:
369 retval = Sound_REMOVEDTOBJECT(cl, o, msg);
370 break;
372 //case OM_NOTIFY:
373 default:
374 dbug( kprintf("METHOD: %08lx\n", msg->MethodID); )
375 retval = (IPTR) DoSuperMethodA(cl, o, msg);
378 return(retval);
380 #endif
382 /****************************************************************************/
384 #ifdef __MAXON__
385 ULONG NotifyAttrs( Object *o, struct GadgetInfo *ginfo, ULONG flags, Tag tag1, ... )
387 struct opUpdate opu;
389 opu . MethodID = OM_NOTIFY;
390 opu . opu_AttrList = (struct TagItem *)(&tag1);
391 opu . opu_GInfo = ginfo;
392 opu . opu_Flags = flags;
394 return( DoMethodA( o, (Msg)(&opu) ) );
396 #endif
398 /****************************************************************************/
400 LONG SendObjectMsg( struct InstanceData *id, ULONG Command, APTR Data )
402 #if !defined(__MAXON__) && !defined(__AROS__)
403 #undef SysBase
404 struct Library *SysBase = (*(struct Library **)4L);
405 #endif
406 struct ObjectMsg *msg;
408 if( ( msg = AllocVec( sizeof( *msg ), MEMF_PUBLIC|MEMF_CLEAR ) ) )
410 msg->Command = Command;
411 msg->Data = Data;
412 PutMsg( id->PlayerPort, &msg->Message );
414 else
416 dbug( kprintf( "No memory to send objmsg\n" ); )
419 return( (LONG) (msg!=NULL) );
420 #if !defined(__MAXON__) && !defined(__AROS__)
421 #define SysBase cb->cb_SysBase
422 #endif
425 /****************************************************************************/
427 LONG __regargs Sound_CLEARSELECTED( Class *cl, Object *o, struct dtGeneral *dtg )
429 struct RastPort *rp;
430 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
431 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
432 LONG retval = 0L;
434 (void)cb;
436 dbug( kprintf( "DTM_CLEARSELECTED\n"); )
438 /* 'magic' nothing selected value */
439 id->MinX =
440 id->MaxX = ~0;
441 id->StartSample =
442 id->EndSample = ~0L;
444 if( ( rp = ObtainGIRPort( dtg->dtg_GInfo ) ) )
446 DoMethod( o, GM_RENDER, (IPTR) dtg->dtg_GInfo, (IPTR) rp, (IPTR) GREDRAW_REDRAW );
447 ReleaseGIRPort( rp );
450 ((struct DTSpecialInfo *)(G( o ) -> SpecialInfo)) -> si_Flags &= ~DTSIF_HIGHLIGHT;
452 return retval;
455 /****************************************************************************/
457 LONG __regargs Sound_SELECT( Class *cl, Object *o, struct dtSelect *dts )
459 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
460 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
461 WORD minX = id->MinX, maxX = id->MaxX, oldx,
462 x = G(o)->LeftEdge, w = G(o)->Width;
463 ULONG samplelength = id->SampleLength,
464 startSample = ~0L, endSample = ~0L;
465 LONG dy = samplelength, dx, error, add, sub, step = 1L, i,
466 retval = 0L;
468 (void)cb;
470 dbug( kprintf("DTM_SELECT\n"); )
472 if( minX > maxX )
474 maxX = minX;
475 minX = id->MaxX;
477 /* get abs xpos/width */
478 if( G(o)->Flags & GFLG_RELWIDTH )
480 w += dts->dts_GInfo->gi_Domain.Width;
483 if( G(o)->Flags & GFLG_RELRIGHT )
485 x += dts->dts_GInfo->gi_Domain.Left;
488 oldx = x+=4; w-=8;
490 dx = w;
491 /* a big sample */
492 if( samplelength >> 17 )
494 dy >>= 7;
495 step = 128;
497 /* get first and last sample of the marked area by
498 ** comparing the coordinates */
499 if( samplelength <= w )
501 LONG c = 0L;
503 error = dy-2*dx-1;
504 sub = 2*(dx+1); add = 2*(dy+1);
506 for( i = w; i; i-- )
508 if( x >= minX && startSample == ~0 )
510 startSample = c;
512 else if( x++ >= maxX )
514 endSample = c;
515 break;
518 if( error > 0 )
520 c += step;
521 error -= sub;
524 error += add;
527 else
529 error = dx-2*dy-1;
530 sub = 2*(dy+1); add = 2*(dx+1);
532 for( i = 0; i < samplelength; i+=step )
534 if( error > 0 )
536 if( x >= minX && startSample == ~0 )
538 startSample = i;
540 else if( x++ >= maxX )
542 endSample = i;
543 break;
546 error -= sub;
549 error += add;
552 /* some corrections */
553 if( endSample == ~0 )
555 endSample = samplelength;
558 if( minX == oldx)
560 startSample = 0L;
563 id->StartSample = startSample;
564 id->EndSample = endSample;
566 dbug( kprintf( "%ld, %ld\n", startSample, endSample ); )
568 return retval;
571 /****************************************************************************/
573 void __regargs GetSoundDTPrefs( struct ClassBase *cb )
575 TEXT buf[256];
576 LONG len;
578 dbug( kprintf( "GetSoundDTPrefs\n" ); )
580 ObtainSemaphore( &cb->cb_LibLock );
582 /* set default settings */
583 dbug( kprintf( "Setting default values\n" ); )
584 #ifdef __AROS__
585 cb->cb_AHI = TRUE;
586 #else
587 cb->cb_AHI = FALSE;
588 #endif
589 cb->cb_AHIModeID = AHI_DEFAULT_ID;
590 cb->cb_ForceAHIMode = FALSE;
591 cb->cb_AHIMixFrequency = AHI_DEFAULT_FREQ;
593 cb->cb_Compress = FALSE;
594 cb->cb_AIFF = FALSE;
596 cb->cb_NomWidth = 160;
597 cb->cb_NomHeight = 100;
599 cb->cb_BgCol[0] =
600 cb->cb_BgCol[1] =
601 cb->cb_BgCol[2] = 0;
603 cb->cb_WfCol[0] = 35 << 24L;
604 cb->cb_WfCol[1] = 204 << 24L;
605 cb->cb_WfCol[2] = 23 << 24L;
607 cb->cb_BufferSize = 65536L;
608 cb->cb_Volume = 64L;
609 cb->cb_ControlPanel = FALSE;
610 cb->cb_NoGTSlider = FALSE;
612 if( ( len = GetVar( "datatypes/sounddt41.prefs", buf, sizeof( buf )-1, GVF_GLOBAL_ONLY ) ) > 0 )
614 struct RDArgs *rdargs;
616 dbug( kprintf( "Prefs: %s\n", buf ); )
618 if( ( rdargs = AllocDosObject( DOS_RDARGS, NULL ) ) )
620 struct RDArgs *freeargs;
621 struct {
622 LONG *volume;
623 LONG *buffersize;
624 LONG ahi;
625 STRPTR ahimodeid;
626 LONG forceahimode;
627 LONG *mixfreq;
628 LONG aiff;
629 LONG compress;
630 LONG *width, *height;
631 STRPTR bg, wf;
632 LONG cp;
633 LONG nogtsl;
634 } args = { };
636 /* prepare rdargs */
637 buf[len++] = '\n';
638 rdargs->RDA_Source.CS_Buffer = buf;
639 rdargs->RDA_Source.CS_Length = len;
640 rdargs->RDA_Flags = RDAF_NOPROMPT;
642 if( ( freeargs = ReadArgs( TEMPLATE, (IPTR *)&args, rdargs ) ) )
644 dbug( kprintf( "List of options:\n" ); )
646 if( args.ahi )
648 cb->cb_AHI = TRUE;
649 dbug( kprintf( "AHI\n" ); )
652 if( args.ahimodeid )
654 cb->cb_AHIModeID = hex2long( args.ahimodeid );
655 dbug( kprintf( "AHIMODEID = %lx\n", cb->cb_AHIModeID ); )
658 if( args.forceahimode )
660 cb->cb_ForceAHIMode = TRUE;
661 dbug( kprintf( "FAM\n" ); )
664 if( args.mixfreq )
666 cb->cb_AHIMixFrequency = *args.mixfreq;
667 dbug( kprintf( "AHIMIXFREQ = %ld\n", *args.mixfreq ); )
670 if( args.aiff )
672 cb->cb_AIFF = TRUE;
673 dbug( kprintf( "AIFF16\n" ); )
676 if( args.compress )
678 cb->cb_Compress = TRUE;
679 dbug( kprintf( "COMPRESS\n" ); )
682 if( args.width )
684 cb->cb_NomWidth = *args.width;
685 dbug( kprintf( "WIDTH = %ld\n", *args.width ); )
688 if( args.height )
690 cb->cb_NomHeight = *args.height;
691 dbug( kprintf( "HEIGHT = %ld\n", *args.height ); )
694 if( args.wf )
696 LONG num = hex2long( args.wf );
698 cb->cb_WfCol[0] = (num>>16L)<<24;
699 cb->cb_WfCol[1] = (num>>8L)<<24L;
700 cb->cb_WfCol[2] = (num)<<24L;
701 dbug( kprintf( "WFCOL = %08lx\n", num ); )
704 if( args.bg )
706 LONG num = hex2long( args.bg );
708 cb->cb_BgCol[0] = (num>>16L)<<24L;
709 cb->cb_BgCol[1] = (num>>8L)<<24L;
710 cb->cb_BgCol[2] = (num)<<24L;
711 dbug( kprintf( "BGCOL = %08lx\n", num ); )
714 if( args.buffersize )
716 LONG bufsize = *args.buffersize;
718 if( bufsize > 1023 && bufsize < 131073 )
720 cb->cb_BufferSize = bufsize;
723 dbug( kprintf( "BUFFERSZ = %ld\n", bufsize ); )
726 if( args.cp )
728 cb->cb_ControlPanel = TRUE;
729 dbug( kprintf( "CP=YES\n" ); )
731 else
733 cb->cb_ControlPanel = FALSE;
734 dbug( kprintf( "CP=NO\n" ); )
737 if( args.volume )
739 cb->cb_Volume = *args.volume;
740 dbug( kprintf( "VOLUME = %ld\n", *args.volume ); )
743 if( args.nogtsl )
745 cb->cb_NoGTSlider = TRUE;
746 dbug( kprintf( "NOGTSLIDER\n" ); )
749 FreeArgs( freeargs );
751 else
753 struct EasyStruct es = { sizeof(struct EasyStruct), 0, "sound.datatype", buf, "Okay" };
755 if( Fault( IoErr(), "Error in prefs file", buf, sizeof( buf ) ) )
757 dbug( kprintf( "Prefserr: %s\n" , buf ); )
758 EasyRequestArgs( NULL, &es, NULL, NULL );
762 FreeDosObject( DOS_RDARGS, rdargs );
764 else
766 dbug( kprintf( "AllocDosObject() failed\n" ); )
769 else
771 dbug( kprintf( "GetVar failed\n" ); )
774 ReleaseSemaphore( &cb->cb_LibLock );
777 /****************************************************************************/
779 LONG __regargs hex2long(STRPTR s)
780 { ULONG a;
781 BYTE c;
783 if (s && (c=*s++) && (c=='$' || (c == '0' && *s++ == 'x'))) {
784 a=0;
785 while ((c=*s++)) {
786 if (c>'9')
787 c&=0x5f;
788 if ((c-='0')<0 || (c>9 && (c-=7)>15))
789 return 0;
790 a<<=4,a|=c;
792 return a;
794 return 0;
797 /****************************************************************************/
799 void CreateTapeDeck( struct ClassBase *cb, struct InstanceData *id, Object *o )
801 #if defined(__MAXON__) || defined(__AROS__)
802 extern struct Library *TapeDeckBase;
803 #else
804 #define TapeDeckBase cb->cb_TapeDeckBase
805 #endif
806 ULONG cp;
808 dbug( kprintf( "Creating panel\n" ); )
810 GetDTAttrs( o, DTA_ControlPanel, (IPTR) &cp, TAG_DONE );
812 if( TapeDeckBase && cp )
814 STATIC struct TagItem prop2vol[] = { {PGA_Top, SDTA_Volume}, {TAG_END} };
816 ObtainSemaphoreShared( &cb->cb_LibLock );
818 if( ( id->VolumeSlider = NewObject( NULL, PROPGCLASS,
819 PGA_Top, id->Volume,
820 PGA_Visible, 1L,
821 PGA_Total, 64L,
822 PGA_Freedom, FREEHORIZ,
823 PGA_NewLook, cb->cb_NoGTSlider,
824 ! cb->cb_NoGTSlider ? PGA_Borderless : TAG_IGNORE, TRUE,
825 ICA_TARGET, (IPTR) o,
826 ICA_MAP, (IPTR) prop2vol,
827 TAG_DONE ) ) )
829 if( ( id->TapeDeckGadget = NewObject( NULL, "tapedeck.gadget",
830 TDECK_Tape, TRUE,
831 TAG_DONE ) ) )
833 ReleaseSemaphore( &cb->cb_LibLock );
834 return;
837 DisposeObject( id->VolumeSlider );
838 id->VolumeSlider = NULL;
841 ReleaseSemaphore( &cb->cb_LibLock );
843 else
845 dbug( kprintf( "Failed or turned off\n" ); )
848 id->ControlPanel = FALSE;
851 /****************************************************************************/
853 IPTR __regargs Sound_NEW( Class *cl, Object *o, struct opSet *ops )
855 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
856 struct TagItem ti[6];
858 dbug( kprintf( "OM_NEW\n" ); )
860 GetSoundDTPrefs( cb );
862 ObtainSemaphoreShared( &cb->cb_LibLock );
863 ti[0].ti_Tag = DTA_NominalHoriz;
864 ti[0].ti_Data = cb->cb_NomWidth;
865 ti[1].ti_Tag = DTA_NominalVert;
866 ti[1].ti_Data = cb->cb_NomHeight;
867 ti[2].ti_Tag = DTA_VertUnit;
868 ti[2].ti_Data = 1L;
869 ti[3].ti_Tag = DTA_HorizUnit;
870 ti[3].ti_Data = 1L;
871 ti[4].ti_Tag = DTA_ControlPanel;
872 ti[4].ti_Data = cb->cb_ControlPanel;
873 ti[5].ti_Tag = TAG_MORE;
874 ti[5].ti_Data = (IPTR) ops->ops_AttrList;
875 ReleaseSemaphore( &cb->cb_LibLock );
877 ops->ops_AttrList = ti;
879 if( ( o = (Object *) DoSuperMethodA( cl, o, (Msg) ops ) ) )
881 struct InstanceData *id = INST_DATA( cl, o );
882 struct ObjectMsg *msg;
883 struct MsgPort *replyport;
885 id->Volume = cb->cb_Volume;
886 id->Frequency = Period2Freq( 394 );
887 id->Cycles = 1;
888 id->SignalBit = -1L;
889 // id->SampleType = SDTST_M8S;
890 id->Panning = 0x8000;
891 /* 'magic' nothing selected value */
892 id->MinX =
893 id->MaxX = ~0L;
894 id->StartSample =
895 id->EndSample = ~0L;
896 id->TapeDeckHeight = 15L; // tapedeck.gadget is currently limited to 15 pixels
897 id->BackgroundPen =
898 id->WaveformPen = -1;
899 id->ClassBase = cb;
900 id->FreeSampleData = TRUE;
901 // id->SyncSampleChange = FALSE;
902 InitSemaphore( &id->Lock );
904 /* create process */
905 replyport = CreateMsgPort();
907 if( ( msg = (struct ObjectMsg *) CreateIORequest( replyport, sizeof( *msg ) ) ) )
909 ObtainSemaphoreShared( &cb->cb_LibLock );
911 if( ( id->PlayerProc = CreateNewProcTags(
912 NP_Name, (IPTR) "sound.datatype",
913 NP_Entry, (IPTR) (cb->cb_AHI) ? (IPTR) PlayerProcAHI : (IPTR) PlayerProc,
914 NP_Priority, 19L,
915 TAG_DONE ) ) )
917 msg->Data = (APTR) id;
918 msg->Command = COMMAND_INIT;
919 PutMsg( &id->PlayerProc->pr_MsgPort, &msg->Message );
920 WaitPort( replyport );
921 GetMsg( replyport );
923 if( msg->Data )
925 id->PlayerPort = (struct MsgPort *) msg->Data;
927 else
929 id->PlayerProc = NULL;
933 ReleaseSemaphore( &cb->cb_LibLock );
935 DeleteIORequest( (struct IORequest *) msg );
937 if( id->PlayerProc )
939 parsetaglist( cl, o, ops, NULL );
940 CreateTapeDeck( cb, id, o );
942 else
944 CoerceMethod( cl, o, OM_DISPOSE );
945 o = NULL;
948 else
950 dbug( kprintf( "No memory for ioreq or msgport\n" ); )
953 DeleteMsgPort( replyport );
955 else
957 dbug( kprintf( "OM_NEW failed\n" ); )
960 ops->ops_AttrList = (struct TagItem *) ti[5].ti_Data;
962 dbug( if( !o ) kprintf("Object creation failed\n"); )
964 return( (IPTR) o );
967 /****************************************************************************/
969 void __regargs SetVSlider( struct ClassBase *cb, struct InstanceData *id )
971 /* this function works aroung a "spilled register" error */
972 if( id->ControlPanel )
974 IPTR top;
975 GetAttr( PGA_Top, (Object *)id->VolumeSlider, &top );
976 if( top != id->Volume ) // avoid loops
978 SetGadgetAttrs( id->VolumeSlider, id->Window, id->Requester,
979 PGA_Top, id->Volume, TAG_DONE );
984 /****************************************************************************/
986 BOOL __regargs parsetaglist( Class *cl, Object *o, struct opSet *ops, ULONG *cnt_p )
988 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
989 struct TagItem *ti, *tstate = ops->ops_AttrList;
990 struct InstanceData *id = INST_DATA( cl, o );
991 BOOL pervol = FALSE, newSample = FALSE;
992 LONG cnt = 0L;
994 ObtainSemaphore( &id->Lock );
995 dbug( kprintf( "NextTagItem\n" ); )
996 while( ( ti = NextTagItem( (const struct TagItem **)&tstate ) ) )
998 IPTR data = ti->ti_Data;
1000 switch( ti->ti_Tag )
1002 case SDTA_VoiceHeader:
1003 id->VoiceHeader = *(struct VoiceHeader *) data;
1004 dbug( kprintf("SDTA_VoiceHeader\n"); )
1005 cnt++;
1006 break;
1008 case SDTA_Sample:
1009 id->Sample = (BYTE *) data;
1010 id->LeftSample = FALSE;
1011 dbug( kprintf("SDTA_Sample = %08lx\n", data); )
1012 newSample = TRUE;
1013 cnt++;
1014 break;
1016 case SDTA_SampleLength:
1017 id->SampleLength = data;
1018 dbug( kprintf("SDTA_SampleLength = %ld\n", data); )
1019 cnt++;
1020 break;
1022 case SDTA_Period:
1023 id->Frequency = (UWORD) Period2Freq( data );
1024 pervol = TRUE;
1025 dbug( kprintf("SDTA_Period = %ld (%lDHz)\n", data, Period2Freq(data) ); )
1026 cnt++;
1027 break;
1029 case SDTA_Volume:
1030 id->Volume = (UWORD) data;
1031 pervol = TRUE;
1033 SetVSlider( cb, id );
1035 dbug( kprintf("SDTA_Volume = %ld\n", data); )
1037 cnt++;
1038 break;
1040 case SDTA_Cycles:
1041 id->Cycles = (UWORD) data;
1042 dbug( kprintf("SDTA_Cycles = %ld\n", data); )
1043 cnt++;
1044 break;
1046 case SDTA_SignalTask:
1047 id->SignalTask = (struct Task *) data;
1048 dbug( kprintf("SDTA_SignalTask = %08lx\n", data); )
1049 cnt++;
1050 break;
1052 case SDTA_SignalBitMask: // aka: SDTA_SignalBit
1053 dbug( kprintf("SDTA_SignalBit(Mask) = %08lx\n", data); )
1054 if( data != 0L )
1056 LONG i;
1058 for( i = 0; i < 32; i++ )
1060 if( ( 1L << i ) & data )
1062 id->SignalBit = i;
1063 break;
1067 else id->SignalBit = -1;
1068 cnt++;
1069 break;
1071 case SDTA_Continuous:
1072 id->Continuous = (BOOL) data;
1073 dbug( kprintf("SDTA_Continuous = %ld\n", data); )
1074 cnt++;
1075 break;
1077 case SDTA_SampleType:
1078 id->SampleType = data;
1079 dbug( kprintf("SDTA_SampleType = %ld\n", data ); )
1080 cnt++;
1081 break;
1083 case SDTA_Pan:
1084 case SDTA_Panning:
1085 id->Panning = data;
1086 pervol = TRUE;
1087 dbug( kprintf("SDTA_Panning = %05lx\n", data ); )
1088 cnt++;
1089 break;
1091 case SDTA_SamplesPerSec:
1092 case SDTA_Frequency:
1093 id->Frequency = data;
1094 pervol = TRUE;
1095 dbug( kprintf("SDTA_Frequency/SamplesPerSec =%ld\n", data); )
1096 cnt++;
1097 break;
1099 case DTA_ControlPanel:
1100 if( data != id->ControlPanel )
1102 id->ForceRefresh = TRUE;
1105 id->ControlPanel = (BOOL) data;
1106 dbug( kprintf("DTA_ControlPanel =%ld\n", data); )
1107 cnt++;
1108 break;
1110 case DTA_Immediate:
1111 if( ! ( id->Immediate = data ) )
1113 CoerceMethod( cl, o, DTM_TRIGGER, 0, STM_STOP, 0 );
1115 else
1117 newSample = ( id->Sample != NULL );
1118 id->DelayedImmed = TRUE;
1120 dbug( kprintf("DTA_Immediate = %ld\n", data ); )
1121 cnt++;
1122 break;
1124 case DTA_Repeat:
1125 id->Repeat = (BOOL) data;
1126 dbug( kprintf("DTA_Repeat = %ld\n", data ); )
1127 cnt++;
1128 break;
1130 case SDTA_SyncSampleChange:
1131 id->SyncSampleChange = data;
1132 dbug( kprintf("SDTA_SyncSampleChange = %ld\n", data ); )
1133 cnt++;
1134 break;
1136 case SDTA_FreeSampleData:
1137 id->FreeSampleData = data;
1138 dbug( kprintf("SDTA_FreeSampleData = %ld\n", data ); )
1139 cnt++;
1140 break;
1142 case SDTA_LeftSample:
1143 id->LeftSample = TRUE;
1144 id->Sample = (BYTE *) data;
1145 newSample = TRUE;
1146 dbug( kprintf("SDTA_LeftSample = %08lx\n", data ); )
1147 cnt++;
1148 break;
1150 case SDTA_RightSample:
1151 id->RightSample = (BYTE *) data;
1152 newSample = TRUE;
1153 dbug( kprintf("SDTA_RightSample = %08lx\n", data ); )
1154 cnt++;
1155 break;
1157 case SDTA_SignalBitNumber:
1158 id->SignalBit = data;
1159 dbug( kprintf("SDTA_SignalBitNumber = %ld\n", data ); )
1160 cnt++;
1161 break;
1163 default:
1164 dbug( kprintf("Attr: %08lx\n", ti->ti_Tag); )
1165 break;
1169 ReleaseSemaphore( &id->Lock );
1170 dbug( kprintf( "NextTagItem done.\n" ); )
1171 /*- inform sound object handler about that change -*/
1172 if( pervol && id->PlayerProc )
1173 {dbug( kprintf( "NextTagItem 2\n" ); )
1174 SendObjectMsg( id, COMMAND_PERVOL, NULL );
1177 if( newSample )
1178 {dbug( kprintf( "NextTagItem 3\n" ); )
1179 /* continuous stream of data ? */
1180 if( id->Continuous )
1182 /* inform player process that we got a new buffer */
1183 SendObjectMsg( id, COMMAND_NEXT_BUFFER, NULL );
1185 if( id->SyncSampleChange )
1189 else if( id->Immediate && id->DelayedImmed )
1191 id->DelayedImmed = FALSE;
1192 CoerceMethod( cl, o, DTM_TRIGGER, 0, STM_PLAY, 0 );
1195 dbug( kprintf( "NextTagItem4\n" ); )
1197 if( cnt_p ) *cnt_p = cnt;
1199 return( pervol );
1202 /****************************************************************************/
1204 IPTR __regargs Sound_GET( Class *cl, Object *o, struct opGet *opg )
1206 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
1207 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
1208 IPTR retval = TRUE, data;
1210 dbug( kprintf("OM_GET\n"); )
1212 switch( opg->opg_AttrID )
1214 case SDTA_VoiceHeader:
1215 data = (IPTR) &id->VoiceHeader;
1216 dbug( kprintf("SDTA_VoiceHeader\n"); )
1217 break;
1219 case SDTA_Sample:
1220 data = (IPTR) ( ( id->LeftSample ) ? NULL : id->Sample );
1221 dbug( kprintf("SDTA_Sample\n"); )
1222 break;
1224 case SDTA_SampleLength:
1225 data = id->SampleLength;
1226 dbug( kprintf("SDTA_SampleLength\n"); )
1227 break;
1229 case SDTA_Period:
1230 data = (IPTR) Freq2Period( id->Frequency );
1231 dbug( kprintf("SDTA_Period\n"); )
1232 break;
1234 case SDTA_Volume:
1235 data = (IPTR) id->Volume;
1236 dbug( kprintf("SDTA_Volume\n"); )
1237 break;
1239 case SDTA_Cycles:
1240 data = (IPTR) id->Cycles;
1241 dbug( kprintf("SDTA_Cycles\n"); )
1242 break;
1244 case SDTA_SignalTask:
1245 data = (IPTR) id->SignalTask;
1246 dbug( kprintf("SDTA_SignalTask\n"); )
1247 break;
1249 case SDTA_SignalBitMask: // aka SDTA_SignalBit
1250 data = (IPTR) ( id->SignalBit == -1 ) ? 0L : ( 1L << id->SignalBit );
1251 dbug( kprintf("SDTA_SignalBit(Mask)\n"); )
1252 break;
1254 case SDTA_SignalBitNumber:
1255 data = id->SignalBit;
1256 dbug( kprintf("SDTA_SignalBitNumber\n"); )
1257 break;
1259 case SDTA_Continuous:
1260 data = (IPTR) id->Continuous;
1261 dbug( kprintf("SDTA_Continuous\n"); )
1262 break;
1264 case SDTA_Pan:
1265 case SDTA_Panning:
1266 data = id->Panning;
1267 dbug( kprintf("SDTA_Pan(ning)\n"); )
1268 break;
1270 case SDTA_SampleType:
1271 data = id->SampleType;
1272 dbug( kprintf("SDTA_SampleType\n"); )
1273 break;
1275 case SDTA_SamplesPerSec:
1276 case SDTA_Frequency:
1277 data = id->Frequency;
1278 dbug( kprintf("SDTA_Frequency/SamplesPerSec\n"); )
1279 break;
1281 case DTA_TriggerMethods:
1282 data = (IPTR) TriggerMethods;
1283 dbug( kprintf("SDTA_TriggerMethods\n"); )
1284 break;
1286 case DTA_ControlPanel:
1287 data = (IPTR) id->ControlPanel;
1288 dbug( kprintf("DTA_ControlPanel\n"); )
1289 break;
1291 case DTA_Repeat:
1292 data = (IPTR) id->Repeat;
1293 dbug( kprintf("DTA_Repeat\n"); )
1294 break;
1296 case DTA_Immediate:
1297 data = (IPTR) id->Immediate;
1298 dbug( kprintf("DTA_Immediate\n"); )
1299 break;
1301 case DTA_Methods:
1303 dbug( kprintf( "DTA_Methods\n"); )
1304 #ifndef __GNUC__
1305 ObtainSemaphore( &cb->cb_LibLock );
1306 /* first request of DTA_Methods ? */
1307 if( ! ( data = (IPTR) cb->cb_Methods ) )
1309 ULONG cntSuper, cntMethods, *superMethods, *newMethods;
1310 /* create Methods array */
1311 DoSuperMethod( cl, o, OM_GET, DTA_Methods, (IPTR) &superMethods );
1313 for( cntSuper = 0; superMethods[ cntSuper ] != ~0; cntSuper++ ) {}
1314 for( cntMethods = 0; Methods[ cntMethods ] != ~0; cntMethods++ ) {}
1316 cb->cb_Methods = // For any reasons, GNUC seems to have problems here !
1317 newMethods = (ULONG *) AllocVec( ( cntSuper+cntMethods+1UL ) * sizeof( ULONG ), MEMF_PUBLIC );
1319 if( data = (ULONG) newMethods )
1321 ULONG num = 0L;
1323 CopyMem( superMethods, newMethods, sizeof( ULONG ) * cntSuper );
1324 newMethods += cntSuper;
1326 for( num = 0; num < cntMethods; num++ )
1328 ULONG i, method = Methods[ num ];
1330 for( i = 0; i < cntSuper; i++ )
1332 if( superMethods[ i ] == method )
1334 break;
1338 if( i == cntSuper )
1340 *newMethods++ = method;
1344 *newMethods = ~0L;
1346 else
1348 data = (ULONG) Methods;
1352 ReleaseSemaphore( &cb->cb_LibLock );
1353 #else
1354 ObtainSemaphore( &cb->cb_LibLock );
1356 if( ! ( data = (IPTR) cb->cb_Methods ) )
1358 if( DataTypesBase->lib_Version >= 45L )
1360 ULONG *superMethods = NULL;
1362 DoSuperMethod( cl, o, OM_GET, DTA_Methods, (ULONG) &superMethods );
1364 data = (ULONG) ( cb->cb_Methods = CopyDTMethods( superMethods, Methods, NULL ) );
1366 dbug( kprintf( "CopyDTMethods returned %08lx\n", data ); )
1370 if( ! data )
1372 data = (IPTR) Methods;
1375 ReleaseSemaphore (&cb->cb_LibLock );
1376 #endif
1378 break;
1380 case SDTA_SyncSampleChange:
1381 data = id->SyncSampleChange;
1382 dbug( kprintf("SDTA_SyncSampleChange\n"); )
1383 break;
1385 case SDTA_FreeSampleData:
1386 data = id->FreeSampleData;
1387 dbug( kprintf("SDTA_FreeSampleData\n"); )
1388 break;
1390 case SDTA_LeftSample:
1391 data = (IPTR) ( ( id->LeftSample ) ? id->Sample : NULL );
1392 dbug( kprintf("SDTA_LeftSample\n"); )
1393 break;
1395 case SDTA_RightSample:
1396 data = (IPTR) id->RightSample;
1397 dbug( kprintf("SDTA_RightSample\n"); )
1398 break;
1400 case SDTA_ReplayPeriod:
1402 ULONG secs, micro;
1404 data = (IPTR) &id->ReplayPeriod;
1406 if( id->Continuous )
1408 secs =
1409 micro = -1L;
1411 else if( id->SampleLength )
1413 secs = UDiv( id->SampleLength, id->Frequency );
1414 micro = UMult( UDiv( 1000000, id->Frequency ), ( id->SampleLength % id->Frequency ) );
1416 else
1418 secs =
1419 micro = 0L;
1422 id->ReplayPeriod.tv_secs = secs;
1423 id->ReplayPeriod.tv_micro = micro;
1425 dbug( kprintf("SDTA_ReplayPeriod %ld:%ld\n", secs, micro ); )
1427 break;
1429 default:
1430 retval = FALSE;
1431 dbug( kprintf("Attr: %08lx\n", opg->opg_AttrID); )
1434 if( retval )
1436 *opg->opg_Storage = data;
1438 else
1440 retval = DoSuperMethodA( cl, o, (Msg) opg );
1441 dbug( kprintf("SuperAttr: %08lx, %08lx\n", opg->opg_AttrID, *opg->opg_Storage); )
1444 return( retval );
1447 /****************************************************************************/
1449 IPTR __regargs Sound_SET( Class *cl, Object *o, struct opSet *ops )
1451 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
1452 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
1453 IPTR retval, cnt;
1455 (void)cb;
1457 dbug( kprintf("OM_SET\n"); )
1459 retval = DoSuperMethodA( cl, o, (Msg) ops );
1460 dbug( kprintf("parsing list\n"); )
1461 parsetaglist( cl, o, ops, (ULONG *)&cnt );
1462 dbug( kprintf("refreshing\n"); )
1463 if( retval || ( ( id->ForceRefresh ) && ( id->Gadget ) ) )
1465 struct RastPort *rp;
1467 if( ( rp = ObtainGIRPort( ops->ops_GInfo ) ) )
1469 DoMethod( o, GM_RENDER, (IPTR) ops->ops_GInfo, (IPTR) rp, GREDRAW_REDRAW );
1470 ReleaseGIRPort( rp );
1472 id->ForceRefresh = FALSE;
1475 dbug( kprintf("leaving OM_SET\n"); )
1476 return( retval+cnt );
1479 /****************************************************************************/
1481 IPTR __regargs Sound_UPDATE( Class *cl, Object *o, struct opUpdate *opu )
1483 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
1484 STATIC IPTR methodID = ICM_CHECKLOOP;
1486 (void)cb;
1488 dbug( kprintf("OM_UPDATE\n"); )
1490 if( DoSuperMethodA( cl, o, (Msg) &methodID ) )
1492 return FALSE;
1495 dbug( kprintf("no loop %08lx\n", (ULONG)opu); )
1497 return Sound_SET( cl, o, (struct opSet *) opu );
1500 /****************************************************************************/
1502 IPTR __regargs Sound_DISPOSE( Class *cl, Object *o, Msg msg )
1504 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
1505 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
1506 struct SignalSemaphore *lock = &((struct DTSpecialInfo *)G( o )->SpecialInfo)->si_Lock;
1508 (void)cb;
1510 dbug( kprintf("OM_DISPOSE\n"); )
1512 /* free playerproc stuff */
1513 if( id->PlayerProc )
1515 struct MsgPort *replyport;
1516 struct ObjectMsg *msg;
1518 while( ! ( replyport = CreateMsgPort() ) )
1520 Delay( 25L );
1523 while( ! ( msg = (struct ObjectMsg *) CreateIORequest( replyport, sizeof( *msg ) ) ) )
1525 Delay( 25L );
1528 msg->Command = COMMAND_EXIT;
1529 PutMsg( id->PlayerPort, &msg->Message );
1530 WaitPort( replyport );
1531 GetMsg( replyport );
1533 DeleteIORequest( (struct IORequest *) msg );
1534 DeleteMsgPort( replyport );
1536 /* free controls */
1537 dbug( kprintf( "freeing controls\n" ); )
1538 DisposeObject( id->TapeDeckGadget );
1539 DisposeObject( id->VolumeSlider );
1541 /* free sample memory, obtain semaphore in case that there's a write in progess */
1542 dbug( kprintf( "releasing memory\n" ); )
1544 ObtainSemaphore( lock );
1545 if( id->FreeSampleData && ! id->Continuous )
1547 FreeVec( id->Sample );
1548 if( id->Sample != id->RightSample ) FreeVec( id->RightSample );
1550 ReleaseSemaphore( lock );
1552 return( DoSuperMethodA( cl, o, msg ) );
1555 /****************************************************************************/
1557 IPTR __regargs Sound_DOMAIN( Class *cl, Object *o, struct gpDomain *gpd )
1559 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
1560 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
1561 struct IBox *gbox = &gpd->gpd_Domain;
1563 dbug( kprintf("GDOMAIN\n"); )
1565 *gbox = GetAbsGadgetBox( &gpd->gpd_GInfo->gi_Domain, EXTG( o ), FALSE );
1567 switch( gpd->gpd_Which )
1569 case GDOMAIN_MINIMUM:
1570 gbox->Width = 32;
1571 gbox->Height = id->TapeDeckHeight + 10;
1572 break;
1574 case GDOMAIN_NOMINAL:
1575 ObtainSemaphoreShared( &cb->cb_LibLock );
1576 gbox->Width = cb->cb_NomWidth;
1577 gbox->Height = cb->cb_NomHeight;
1578 ReleaseSemaphore( &cb->cb_LibLock );
1579 break;
1581 case GDOMAIN_MAXIMUM:
1582 gbox->Width =
1583 gbox->Height = SHRT_MAX;
1584 break;
1587 return TRUE;
1590 /****************************************************************************/
1592 IPTR __regargs Sound_LAYOUT( Class *cl, Object *o, struct gpLayout *gpl )
1594 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
1595 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
1596 struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
1597 struct GadgetInfo *gi = gpl->gpl_GInfo;
1598 struct IBox *domain = NULL;
1599 STRPTR name = NULL;
1600 IPTR retval;
1602 dbug( kprintf( "GM_LAYOUT\n" ); )
1604 retval = DoSuperMethodA( cl, o, (Msg) gpl );
1606 si->si_Flags |= DTSIF_LAYOUT;
1607 ObtainSemaphore( &si->si_Lock );
1609 #ifndef __AROS__
1610 NotifyAttrs( o, gi, 0L,
1611 GA_ID, G( o )->GadgetID,
1612 DTA_Busy, TRUE,
1613 TAG_DONE );
1614 #else
1616 struct TagItem tags[] =
1618 {GA_ID, G( o )->GadgetID},
1619 {DTA_Busy, TRUE},
1620 {TAG_DONE}
1623 DoMethod(o, OM_NOTIFY, (IPTR)tags, (IPTR)gi, 0);
1625 #endif
1627 if( GetDTAttrs( o,
1628 DTA_ObjName, (IPTR) &name,
1629 DTA_Domain, (IPTR) &domain,
1630 TAG_DONE ) == 2L )
1632 ULONG vunit = si->si_VertUnit,
1633 hunit = si->si_HorizUnit,
1634 totalw = si->si_TotHoriz,
1635 totalh = si->si_TotVert;
1637 si->si_VertUnit = vunit;
1638 si->si_VisVert = domain->Height / vunit;
1639 si->si_TotVert = totalh;
1641 si->si_HorizUnit = hunit;
1642 si->si_VisHoriz = domain->Width / hunit;
1643 si->si_TotHoriz = totalw;
1645 if( ! name )
1647 if( ! GetDTAttrs( o, DTA_Name, (IPTR) &name, TAG_DONE ) || ! name )
1649 name = "Untitled";
1651 else
1653 name = FilePart( name );
1657 if( gpl->gpl_Initial )
1659 ObtainSemaphore( &id->Lock );
1660 id->Window = gi->gi_Window;
1661 id->Requester = gi->gi_Requester;
1662 id->Gadget = (struct Gadget *) o;
1663 ReleaseSemaphore( &id->Lock );
1664 /* obtain pens */
1665 id->ColorMap = gi->gi_Screen->ViewPort.ColorMap;
1667 ObtainSemaphoreShared( &cb->cb_LibLock );
1668 id->BackgroundPen = ObtainBestPenA( id->ColorMap,
1669 cb->cb_BgCol[0], cb->cb_BgCol[1], cb->cb_BgCol[2], NULL );
1670 id->WaveformPen = ObtainBestPenA( id->ColorMap,
1671 cb->cb_WfCol[0], cb->cb_WfCol[1], cb->cb_WfCol[2], NULL );
1672 ReleaseSemaphore( &cb->cb_LibLock );
1675 if( id->TapeDeckGadget )
1677 struct gpLayout member_gpl;
1678 struct TagItem ti[] = {
1679 {GA_Left, domain->Left},
1680 {GA_Top, domain->Top + domain->Height - id->TapeDeckHeight},
1681 {GA_Width, 201},
1682 {GA_Height, id->TapeDeckHeight},
1683 {TAG_DONE }
1686 if( ( gpl->gpl_Initial ) && ( G( o )->GadgetType & GTYP_REQGADGET ) )
1688 id->TapeDeckGadget->GadgetType |= GTYP_REQGADGET;
1689 id->VolumeSlider->GadgetType |= GTYP_REQGADGET;
1692 ObtainSemaphoreShared( &cb->cb_LibLock );
1694 member_gpl = *gpl;
1695 member_gpl.MethodID = GM_LAYOUT;
1697 SetAttrsA( id->TapeDeckGadget, ti );
1699 DoMethodA( (Object *) id->TapeDeckGadget, (Msg) &member_gpl );
1701 ti[0].ti_Data += 205;
1702 ti[2].ti_Data = domain->Width - 205;
1704 if( ! cb->cb_NoGTSlider )
1706 ti[0].ti_Data += 4;
1707 ti[1].ti_Data += 2;
1708 ti[2].ti_Data -= 8;
1709 ti[3].ti_Data -= 4;
1712 SetAttrsA( id->VolumeSlider, ti );
1714 DoMethodA( (Object *) id->VolumeSlider, (Msg) &member_gpl );
1716 ReleaseSemaphore( &cb->cb_LibLock );
1719 #ifndef __AROS__
1720 NotifyAttrs( o, gi, 0L,
1721 GA_ID, G(o)->GadgetID,
1722 DTA_VisibleVert, si->si_VisVert,
1723 DTA_TotalVert, totalh,
1724 DTA_VertUnit, vunit,
1725 DTA_VisibleHoriz, si->si_VisHoriz,
1726 DTA_TotalHoriz, totalw,
1727 DTA_HorizUnit, hunit,
1728 DTA_Title, (IPTR) name,
1729 DTA_Busy, FALSE,
1730 DTA_Sync, TRUE,
1731 TAG_DONE );
1732 #else
1734 struct TagItem tags[] =
1736 {GA_ID, G(o)->GadgetID},
1737 {DTA_VisibleVert, si->si_VisVert},
1738 {DTA_TotalVert, totalh},
1739 {DTA_VertUnit, vunit},
1740 {DTA_VisibleHoriz, si->si_VisHoriz},
1741 {DTA_TotalHoriz, totalw},
1742 {DTA_HorizUnit, hunit},
1743 {DTA_Title, (IPTR) name},
1744 {DTA_Busy, FALSE},
1745 {DTA_Sync, TRUE},
1746 {TAG_DONE}
1749 DoMethod(o, OM_NOTIFY, (IPTR)tags, (IPTR)gi, 0);
1752 #endif
1755 ReleaseSemaphore( &si->si_Lock );
1756 si->si_Flags &= ~DTSIF_LAYOUT;
1758 return retval + si->si_TotVert;
1761 /****************************************************************************/
1763 void __regargs DrawWaveform( struct ClassBase *cb, struct RastPort *rp, struct InstanceData *id, UWORD x, UWORD y, UWORD w, UWORD h )
1765 ULONG sampleStart = id->StartSample, sampleEnd = id->EndSample;
1766 LONG samplelength = id->SampleLength, error, dx = w, dy = samplelength, sub, add, i,
1767 step = 1L, k=0L, oldx=x, shift = ( id->SampleType >= SDTST_M16S ? 1 : 0 );
1768 BOOL stereo = IsStereo( id->SampleType );
1769 WORD minX = ~0, maxX = ~0, oldy = y, oldh = h;
1770 /* scaling limit is 25500% */
1771 if( w > (samplelength<<8) )
1773 return;
1775 /* a big sample, speed up rendering */
1776 if( samplelength >> 17 )
1778 dy >>= 7;
1779 step = 128;
1781 /* adjust ypos and height for stereo sample */
1782 if( stereo )
1784 h /= 2;
1785 y += h/2;
1786 shift++;
1788 else
1790 y+= h/2;
1793 for( k = 0; k < (stereo?2:1); k++ )
1795 BYTE *sample = &id->Sample[ k ];
1797 if( k && id->SampleType == SDTST_S16S )
1799 sample++;
1802 Move( rp, x, y );
1804 if( samplelength <= w )
1806 LONG c = 0L;
1808 error = dy-2*dx-1;
1809 sub = 2*(dx+1); add = 2*(dy+1);
1811 for( i = 0; i < w; i++ )
1813 /* get minX and maxX for highlighting */
1814 if( sampleStart != ~0 )
1816 if( i >= sampleStart && minX == ~0 )
1818 minX = x;
1820 else if( i >= sampleEnd && maxX == ~0 )
1822 maxX = x;
1823 sampleStart = ~0L; // speed up
1827 Draw( rp, x++, y + ( SMult( sample[ c << shift ], h ) >> 8 ) );
1829 if( error > 0 )
1831 c += step;
1832 error -= sub;
1835 error += add;
1838 else
1840 error = dx-2*dy-1;
1841 sub = 2*(dy+1); add = 2*(dx+1);
1843 for( i = 0; i < samplelength; i+=step )
1845 if( error > 0 )
1847 /* get minX and maxX for highlighting */
1848 if( sampleStart != ~0 )
1850 if( i >= sampleStart && minX == ~0 )
1852 minX = x;
1854 else if( i >= sampleEnd && maxX == ~0 )
1856 maxX = x;
1857 sampleStart = ~0L; // speed up
1861 Draw( rp, x++, y + ( SMult( sample[ i << shift ], h ) >> 8 ) );
1862 error -= sub;
1865 error += add;
1869 y += h;
1870 x = oldx;
1872 /* something marked ? */
1873 if( minX != ~0 )
1875 if( maxX == ~0 )
1877 maxX = oldx+w-1;
1880 SetDrMd( rp, COMPLEMENT );
1881 RectFill( rp, minX, oldy, maxX, oldy+oldh-1 );
1882 /* fix tapedeck.gadget bug (?) */
1883 SetDrMd( rp, JAM1 );
1887 /****************************************************************************/
1889 IPTR __regargs Sound_RENDER( Class *cl, Object *o, struct gpRender *gpr )
1891 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
1892 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
1894 dbug( kprintf( "GM_RENDER\n" ); )
1896 // if( gpr->gpr_Redraw == GREDRAW_REDRAW )
1898 struct RastPort *rp = gpr->gpr_RPort;
1899 struct ColorMap *cm = NULL;
1900 struct IBox gbox;
1901 LONG bgpen=id->BackgroundPen, wfpen=id->WaveformPen;
1902 UWORD *pens = gpr->gpr_GInfo->gi_DrInfo->dri_Pens;
1903 WORD x,y, w,h;
1905 gbox = GetAbsGadgetBox( &gpr->gpr_GInfo->gi_Domain, EXTG( o ), FALSE );
1906 x = gbox.Left; y = gbox.Top;
1907 w = gbox.Width; h = gbox.Height;
1909 if( id->ControlPanel )
1911 h -= ( id->TapeDeckHeight + 2 );
1914 if( ( x != SHRT_MAX && y != SHRT_MAX ) && ( w >=16 && h >= 8 ) )
1916 if( gpr->gpr_GInfo->gi_Screen )
1918 cm = gpr->gpr_GInfo->gi_Screen->ViewPort.ColorMap;
1922 SetAPen( rp, ( bgpen == -1 ) ? pens[TEXTPEN] : bgpen );
1923 RectFill( rp, x,y, w+x-1, h+y-1 );
1925 x += 4; y += 2;
1926 w -= 8; h -= 4;
1928 SetAPen( rp, ( wfpen == -1 ) ? pens[HIGHLIGHTTEXTPEN] : wfpen );
1930 DrawWaveform( cb, rp, id, x, y, w, h );
1933 if( id->ControlPanel )
1935 /* SetAPen( rp, 4L );
1936 RectFill( rp, gbox.Left, gbox.Top+=(gbox.Height-id->TapeDeckHeight-3),
1937 gbox.Left+gbox.Width-1, gbox.Top+id->TapeDeckHeight+1 );*/
1939 if( gbox.Height >= ( id->TapeDeckHeight + 2 ) )
1941 if( gbox.Width >= 201)
1943 DoMethodA( (Object *)id->TapeDeckGadget, (Msg) gpr );
1945 if( gbox.Width >= 220 )
1947 DoMethodA( (Object *) id->VolumeSlider, (Msg) gpr );
1949 if( ! cb->cb_NoGTSlider )
1951 Object *img;
1953 if( ( img = NewObject( NULL, FRAMEICLASS,
1954 IA_Left, id->VolumeSlider->LeftEdge - 4,
1955 IA_Top, id->VolumeSlider->TopEdge - 2,
1956 IA_Width, id->VolumeSlider->Width + 8,
1957 IA_Height, id->TapeDeckHeight,
1958 IA_FrameType, FRAME_BUTTON,
1959 IA_EdgesOnly, TRUE,
1960 TAG_DONE ) ) )
1962 DrawImageState( rp, (struct Image *)img, 0,0, IDS_NORMAL, gpr->gpr_GInfo->gi_DrInfo );
1963 DisposeObject( img );
1971 if( G( o )->Flags & GFLG_DISABLED )
1973 ULONG patt = 0x11114444;
1975 SetAfPt(rp, (UWORD *)&patt, 1);
1976 SetAPen( rp, pens[ SHADOWPEN ] );
1977 RectFill( rp, gbox.Left, gbox.Top, gbox.Left+gbox.Width-1, gbox.Top+gbox.Height-1 );
1978 SetAfPt( rp, NULL, 0L );
1981 else if( gpr->gpr_Redraw == GREDRAW_UPDATE )
1985 return( TRUE );
1988 /****************************************************************************/
1990 IPTR __regargs Sound_DRAW( Class *cl, Object *o, struct dtDraw *dtd )
1992 struct InstanceData *id = INST_DATA( cl, o );
1993 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
1994 struct RastPort *rp = dtd->dtd_RPort;
1995 struct DrawInfo *dri;
1996 struct Screen *scr;
1997 struct ColorMap *cm = NULL;
1998 UWORD x = dtd->dtd_Left, y = dtd->dtd_Top, *pens,
1999 w = dtd->dtd_Width, h = dtd->dtd_Height;
2000 WORD bgpen = -1, wfpen = -1;
2001 BOOL freedri;
2003 dbug( kprintf( "DTM_DRAW\n" ); )
2005 if( ( scr = id->Screen ) )
2007 dri = GetScreenDrawInfo( scr );
2008 freedri = TRUE;
2010 else
2012 dri = id->DrawInfo;
2013 freedri = FALSE;
2016 if( dri )
2018 pens = dri->dri_Pens;
2020 if( scr )
2022 cm = scr->ViewPort.ColorMap;
2024 ObtainSemaphoreShared( &cb->cb_LibLock );
2025 bgpen = ObtainBestPenA( cm,
2026 cb->cb_BgCol[0], cb->cb_BgCol[1], cb->cb_BgCol[2], NULL );
2027 wfpen = ObtainBestPenA( cm,
2028 cb->cb_WfCol[0], cb->cb_WfCol[1], cb->cb_WfCol[2], NULL );
2029 ReleaseSemaphore( &cb->cb_LibLock );
2032 SetAPen( rp, ( bgpen == -1 ) ? pens[TEXTPEN] : bgpen );
2033 RectFill( rp, x,y, w+x-1, h+y-1 );
2035 x += 4; y += 2;
2036 w -= 8; h -= 4;
2038 SetAPen( rp, ( wfpen == -1 ) ? pens[HIGHLIGHTTEXTPEN] : wfpen );
2040 DrawWaveform( cb, rp, id, x, y, w, h );
2042 if( cm )
2044 ReleasePen( cm, bgpen );
2045 ReleasePen( cm, wfpen );
2048 if( freedri )
2050 FreeScreenDrawInfo( scr, dri );
2054 return( dri != NULL );
2057 /****************************************************************************/
2059 IPTR __regargs Sound_HITTEST( Class *cl, Object *o, struct gpHitTest *gpht )
2061 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2062 IPTR retval = GMR_GADGETHIT;
2063 WORD h = G(o)->Height;
2065 dbug( kprintf( "GM_HITTEST\n" ); )
2067 if( ! ( G( o )->Flags & GFLG_DISABLED ) )
2069 /* calculate absolute height */
2070 if( G(o)->Flags & GFLG_RELHEIGHT )
2072 h += gpht->gpht_GInfo->gi_Domain.Height;
2074 /* check if one of our members was hit */
2075 if( gpht->gpht_Mouse.Y > ( h - ( id->TapeDeckHeight + 3 ) ) )
2077 if( id->ControlPanel )
2079 struct IBox domain;
2081 domain = GetAbsGadgetBox( &gpht->gpht_GInfo->gi_Domain, EXTG( o ), FALSE );
2083 if( ! DoMemberHitTest( &domain, (Object *) id->TapeDeckGadget, gpht ) )
2085 if( ! DoMemberHitTest( &domain, (Object *) id->VolumeSlider, gpht ) )
2087 retval = 0L;
2092 else
2094 /* We were hit, change return code if it was GM_HELPTEST */
2095 if( gpht->MethodID == GM_HELPTEST )
2097 retval = GMR_HELPHIT;
2101 else
2103 retval = 0L;
2106 return retval;
2109 /****************************************************************************/
2111 IPTR __regargs Sound_HANDLEINPUT( Class *cl, Object *o, struct gpInput *gpi )
2113 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
2114 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2115 struct InputEvent *ie = gpi->gpi_IEvent;
2116 struct DTSpecialInfo *si = (struct DTSpecialInfo *)G( o )->SpecialInfo;
2117 struct IBox gbox = GetAbsGadgetBox( &gpi->gpi_GInfo->gi_Domain, EXTG( o ), FALSE );
2118 IPTR retval = GMR_MEACTIVE;
2119 WORD mx = gpi->gpi_Mouse.X, my = gpi->gpi_Mouse.Y;
2121 (void)cb;
2123 dbug( kprintf("GM_GOACTIVE / GM_HANDLEINPUT\n"); )
2124 /* no input processing during layout */
2125 if( si->si_Flags & DTSIF_LAYOUT )
2127 return GMR_NOREUSE;
2130 /* check if we're hit or one of our members */
2131 if( gpi->MethodID == GM_GOACTIVE )
2133 G( o )->Activation |= GACT_ACTIVEGADGET;
2134 G( o )->Flags |= GFLG_SELECTED;
2135 /* check if mousepointer is over one of our members */
2136 if( id->ControlPanel )
2138 if( my > ( gbox.Height - id->TapeDeckHeight - 3 ) )
2140 struct gpHitTest gpht = { GM_HITTEST, gpi->gpi_GInfo, {mx, my} };
2142 if( gbox.Width >= 201 && DoMemberHitTest( &gbox, (Object *) id->TapeDeckGadget, &gpht ) )
2144 id->ActiveMember = id->TapeDeckGadget;
2146 else if( gbox.Width >= 220 && DoMemberHitTest( &gbox, (Object *) id->VolumeSlider, &gpht ) )
2148 id->ActiveMember = id->VolumeSlider;
2150 /* nothing hit ? */
2151 if( ! id->ActiveMember )
2153 retval = GMR_NOREUSE;
2158 /* pass input to the active member ( if there's one ) */
2159 if( id->ActiveMember )
2161 struct IBox domain = gbox;
2163 gbox = GetAbsGadgetBox( &gpi->gpi_GInfo->gi_Domain, EXTG( id->ActiveMember ), FALSE );
2165 (gpi -> gpi_Mouse . X) -= ((gbox . Left) - (domain . Left));
2166 (gpi -> gpi_Mouse . Y) -= ((gbox . Top) - (domain . Top));
2168 if( ( retval = DoMethodA( (Object *) id->ActiveMember, (Msg) gpi ) ) & GMR_VERIFY )
2169 { /* tapedeck.gadget doesn't send OM_UPDATE :( */
2170 if( id->ActiveMember == id->TapeDeckGadget )
2172 if( ie->ie_Code == IECODE_LBUTTON )
2174 ULONG stm = 0L;
2176 dbug( kprintf( "TapeDeck ICSPECIAL_CODE: %04lx\n", *gpi->gpi_Termination ); )
2178 if( *gpi->gpi_Termination & 0x1000 )
2180 stm = STM_PAUSE;
2182 else
2184 switch( *gpi->gpi_Termination )
2186 case BUT_PLAY:
2187 stm = STM_PLAY;
2188 break;
2190 case BUT_STOP:
2191 stm = STM_STOP;
2192 break;
2196 if( stm )
2198 CoerceMethod( cl, o, DTM_TRIGGER, 0, stm, 0 );
2204 (gpi -> gpi_Mouse . X) += ((gbox . Left) - (domain . Left));
2205 (gpi -> gpi_Mouse . Y) += ((gbox . Top) - (domain . Top));
2207 /* we're hit */
2208 else if( retval == GMR_MEACTIVE )
2210 while( ie )
2212 if( ie->ie_Class == IECLASS_RAWMOUSE )
2214 /* test for mark mode */
2215 if( si->si_Flags & DTSIF_DRAGSELECT )
2217 struct RastPort *rp;
2218 WORD mx = gpi->gpi_Mouse.X, x, y, w, h;
2220 x = gbox.Left; y = gbox.Top + 2;
2221 w = gbox.Width - 8; h = gbox.Height - 4;
2223 if( id->ControlPanel )
2225 h -= ( id->TapeDeckHeight + 2 );
2228 if( mx > (w+3) )
2230 mx = w+3;
2232 else if( mx < 4 )
2234 mx = 4;
2237 if( id->MarkMode )
2239 if( id->MaxX != (x+mx) )
2241 if( ( rp = ObtainGIRPort( gpi->gpi_GInfo ) ) )
2243 UWORD minX, maxX;
2245 SetDrMd( rp, COMPLEMENT );
2247 minX = id->MinX;
2248 maxX = id->MaxX;
2250 if( minX > maxX )
2252 maxX = minX;
2253 minX = id->MaxX;
2255 //WaitTOF();
2256 RectFill( rp, minX, y, maxX, y+h-1 );
2258 minX = id->MinX;
2259 maxX =
2260 id->MaxX = x + mx;
2262 if( minX > maxX )
2264 maxX = minX;
2265 minX = id->MaxX;
2267 //WaitTOF();
2268 RectFill( rp, minX, y, maxX, y+h-1 );
2269 /* fixes a bug (?) of tapedeck.gadget */
2270 SetDrMd( rp, JAM1 );
2272 ReleaseGIRPort( rp );
2276 /* start mark mode */
2277 else if( ie->ie_Code == IECODE_LBUTTON )
2279 if( id->MinX != ~0 )
2281 DoMethod( o, DTM_CLEARSELECTED, (IPTR) gpi->gpi_GInfo );
2284 id->MarkMode = TRUE;
2286 id->MinX =
2287 id->MaxX = x + mx;
2290 /* not in mark mode - start or stop playing */
2291 else if( ie->ie_Code == IECODE_LBUTTON )
2293 struct timeval tv = gpi->gpi_IEvent->ie_TimeStamp;
2294 STATIC ULONG stm[] = { STM_PLAY, STM_STOP };
2296 CoerceMethod( cl, o, DTM_TRIGGER, 0, stm[ DoubleClick( id->LastClick.tv_secs, id->LastClick.tv_micro, tv.tv_secs, tv.tv_micro ) ], 0L );
2298 id->LastClick = tv;
2301 if( ie->ie_Code == SELECTUP )
2303 retval = GMR_NOREUSE;
2304 break;
2308 ie = ie->ie_NextEvent;
2312 return( retval );
2315 /****************************************************************************/
2317 IPTR __regargs Sound_GOINACTIVE( Class *cl, Object *o, struct gpGoInactive *gpgi )
2319 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2320 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
2322 (void)cb;
2324 DoSuperMethodA( cl, o, (Msg) gpgi );
2326 dbug( kprintf("GOINACTIVE\n"); )
2328 if( id->ActiveMember )
2330 DoMethodA( (Object *) id->ActiveMember, (Msg) gpgi );
2331 id->ActiveMember = NULL;
2334 id->MarkMode = FALSE;
2336 G( o )->Activation &= ~GACT_ACTIVEGADGET;
2337 G( o )->Flags &= ~GFLG_SELECTED;
2339 return 0L;
2342 /****************************************************************************/
2344 IPTR __regargs Sound_TRIGGER( Class *cl, Object *o, struct dtTrigger *dtt )
2346 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
2347 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2348 APTR data = NULL;
2349 ULONG cmd = ~0L;
2351 (void)cb;
2353 dbug( kprintf("DTM_TRIGGER\n"); )
2355 switch( dtt->dtt_Function )
2357 case STM_PLAY:
2358 dbug( kprintf( "STM_PLAY\n" ); )
2359 cmd = COMMAND_PLAY;
2360 data = (APTR) id;
2361 break;
2363 case STM_STOP:
2364 dbug( kprintf( "STM_STOP\n" ); )
2365 cmd = COMMAND_STOP;
2366 break;
2368 case STM_PAUSE:
2369 dbug( kprintf( "STM_PAUSE\n" ); )
2370 cmd = COMMAND_PAUSE;
2371 break;
2374 if( cmd != ~0 )
2376 SendObjectMsg( id, cmd, data );
2379 return 0L;
2382 /****************************************************************************/
2383 // "stolen" from embeddt
2384 IPTR __regargs DoMemberHitTest( struct IBox *domain, Object *member, struct gpHitTest *gpht )
2386 struct GadgetInfo *gi = gpht -> gpht_GInfo;
2387 struct IBox gbox;
2388 IPTR retval = 0L;
2390 gbox = GetAbsGadgetBox( &gi->gi_Domain, EXTG( member ), (BOOL) ( gpht -> MethodID == GM_HELPTEST ) );
2392 (gpht->gpht_Mouse.X) -= ((gbox.Left) - (domain->Left));
2393 (gpht->gpht_Mouse.Y) -= ((gbox.Top) - (domain->Top));
2395 /* Mouse coordinates must be inside members's select box */
2396 if( ((gpht->gpht_Mouse . X) >= 0) &&
2397 ((gpht->gpht_Mouse . Y) >= 0) &&
2398 ((gpht->gpht_Mouse . X) <= (gbox.Width)) &&
2399 ((gpht->gpht_Mouse . Y) <= (gbox.Height)) )
2401 retval = DoMethodA( member, (Msg)gpht );
2404 (gpht->gpht_Mouse.X) += ((gbox.Left) - (domain->Left));
2405 (gpht->gpht_Mouse.Y) += ((gbox.Top) - (domain->Top));
2407 return( retval );
2410 /****************************************************************************/
2412 struct IBox __regargs GetAbsGadgetBox( struct IBox *domain, struct ExtGadget *g, BOOL useBounds )
2414 struct IBox retbox = { 0, 0, 0, 0 };
2416 if( domain && g )
2418 if( ((g->MoreFlags) & GMORE_BOUNDS) && useBounds )
2420 retbox = *((struct IBox *)(&(g->BoundsLeftEdge)));
2422 else
2424 retbox = *(GADGET_BOX( g ));
2427 if( (g->Flags) & GFLG_RELBOTTOM )
2429 (retbox.Top) += ((domain->Top) + (domain->Height));
2432 if( (g->Flags) & GFLG_RELRIGHT )
2434 (retbox.Left) += ((domain->Left) + (domain->Width));
2437 if( (g->Flags) & GFLG_RELWIDTH )
2439 (retbox.Width) += (domain->Width);
2442 if( (g->Flags) & GFLG_RELHEIGHT )
2444 (retbox.Height) += (domain->Height);
2448 return( retbox );
2451 /****************************************************************************/
2453 void __regargs makeqtab( BYTE *qtab )
2455 LONG i;
2457 for( i=0; i < 512; i++ )
2459 qtab[i] = 0;
2462 for ( i = 1; i < 16; i++ )
2464 LONG j = 256 + fibtab[i],
2465 k = 256 + fibtab[i-1];
2467 if( fibtab[i] < 0 )
2469 while( j > k )
2471 qtab[j--] = i;
2474 else
2476 while( j < 512 )
2478 qtab[j++] = i;
2484 /****************************************************************************/
2486 LONG __regargs WriteChunk( struct ClassBase *cb, struct IFFHandle *iff, ULONG type, ULONG id, APTR data, ULONG size )
2488 LONG err;
2490 if( ! ( err = PushChunk( iff, type, id, size ) ) )
2492 if( ( err = WriteChunkBytes( iff, data, size ) ) == size )
2494 err = PopChunk( iff );
2498 return err;
2501 /****************************************************************************/
2503 LONG __regargs WriteAIFF( struct ClassBase *cb, Object *o, struct IFFHandle *iff, struct InstanceData *id )
2505 LONG err;
2507 if( ! ( err = PushChunk( iff, ID_AIFF, ID_FORM, IFFSIZE_UNKNOWN ) ) )
2509 CommonChunk common;
2510 UBYTE sampleType = id->SampleType;
2511 ULONG sampleLength = id->SampleLength;
2512 BYTE *sample = id->Sample;
2514 if( id->StartSample != ~0 )
2516 sample = &sample[ UMult32( id->StartSample, bytesPerPoint[ sampleType ] ) ];
2517 sampleLength = id->EndSample - id->StartSample;
2520 common.numChannels = ( sampleType & 1 ) + 1;
2521 common.numSampleFrames = sampleLength;
2522 common.sampleSize = ( sampleType >= SDTST_M16S ) ? 16 : 8;
2523 ulong2extended( id->Frequency, &common.sampleRate );
2525 if( ! ( err = WriteChunk( cb, iff, ID_AIFF, ID_COMM, &common, sizeof( common ) ) ) )
2527 SampledSoundHeader ssnd = { 0L, 0L };
2529 if( ! ( err = PushChunk( iff, ID_AIFF, ID_SSND, IFFSIZE_UNKNOWN ) ) )
2531 if( ( err = WriteChunkBytes( iff, &ssnd, sizeof( ssnd ) ) ) == sizeof( ssnd ) )
2533 ULONG bytes = UMult32( sampleLength, bytesPerPoint[ sampleType ] );
2535 if( ( err = WriteChunkBytes( iff, sample, bytes ) ) == bytes )
2537 err = PopChunk( iff );
2543 if( ! err )
2545 err = PopChunk( iff );
2549 return( err );
2552 /****************************************************************************/
2554 LONG __regargs WriteSVX( struct ClassBase *cb, Object *o, struct IFFHandle *iff, struct InstanceData *id )
2556 UBYTE sampletype = id->SampleType, bps = ( sampletype >= SDTST_M16S ? 2 : 1 );
2557 BOOL stereo = IsStereo( id->SampleType );
2558 LONG err, type = ( sampletype >= SDTST_M16S ? ID_16SV : ID_8SVX );
2559 ULONG sampleLength = id->SampleLength;
2560 BYTE *sample = id->Sample;
2561 struct VoiceHeader vhdr;
2563 CopyMem( &id->VoiceHeader, &vhdr, sizeof( vhdr ) );
2564 vhdr.vh_Compression = ( ( id->VoiceHeader.vh_Compression == CMP_FIBDELTA ) || ( cb->cb_Compress ) ) && ( sampletype <= SDTST_S8S );
2566 if( id->StartSample != ~0 )
2568 sample = &sample[ UMult( id->StartSample, bytesPerPoint[ sampletype ] ) ];
2569 sampleLength = id->EndSample - id->StartSample;
2570 vhdr.vh_OneShotHiSamples = sampleLength;
2571 vhdr.vh_RepeatHiSamples = 0L;
2574 if( ! ( err = PushChunk( iff, type, ID_FORM, IFFSIZE_UNKNOWN ) ) )
2576 if( ! ( err = WriteChunk( cb, iff, type, ID_VHDR, &vhdr, sizeof( vhdr ) ) ) )
2578 struct ObjectData
2580 ULONG attr;
2581 ULONG id;
2582 STRPTR data;
2583 } ObjData[] = {
2584 {DTA_ObjName, ID_NAME, NULL},
2585 {DTA_ObjAnnotation, ID_ANNO, NULL},
2586 {DTA_ObjAuthor, ID_AUTH, NULL},
2587 {DTA_ObjCopyright, ID_Copyright, NULL},
2588 {DTA_ObjVersion, ID_FVER, NULL},
2591 LONG i;
2593 for( i = 0; ObjData[i].attr; i++ )
2595 struct ObjectData *od = &ObjData[i];
2597 if( GetDTAttrs( o, od->attr, (IPTR) &od->data, TAG_DONE ) && od->data )
2599 if( ( err = WriteChunk( cb, iff, type, od->id, od->data, StrLen( od->data ) ) ) )
2601 break;
2606 if( ! err )
2608 if( stereo )
2610 ULONG chan = 6L;
2611 err = WriteChunk( cb, iff, type, ID_CHAN, &chan, sizeof( ULONG ) );
2613 else
2615 ULONG pan = 0x10000 - id->Panning;
2616 err = WriteChunk( cb, iff, type, ID_PAN, &pan, sizeof( ULONG ) );
2620 if( ! err )
2622 if( vhdr.vh_Compression == CMP_FIBDELTA )
2624 BYTE *qtab, *buf;
2625 LONG buffersize;
2627 buffersize = sampleLength;
2629 while( ! ( buf = AllocVec( buffersize + 512L, MEMF_PUBLIC ) ) )
2631 if( ( buffersize /= 2 ) < 1024L )
2633 break;
2637 if( buf )
2639 if( ! ( err = PushChunk( iff, type, ID_BODY, IFFSIZE_UNKNOWN ) ) )
2641 LONG i;
2643 qtab = &buf[buffersize];
2644 makeqtab( qtab );
2646 for( i = 0; i < (stereo?2:1) && !err; i++ )
2648 LONG length = sampleLength, samples = 0L;
2649 BYTE c0 = 0, *src = &sample[i], add = stereo?2:1;
2650 UBYTE o, x = 1;
2652 if( length & 1 )
2654 c0 = *src++;
2655 length--;
2658 buf[ 0 ] = 0;
2659 buf[ 1 ] = c0;
2660 samples += 2;
2662 while( length-- )
2664 UBYTE n;
2666 c0 += fibtab[ n = qtab[256+(*src-c0)] ];
2668 src+=add;
2670 if( x^=1 )
2672 buf[samples++] = o | n;
2674 else
2676 o = n << 4;
2679 if( samples == buffersize || length == 0L )
2681 if( ( err = WriteChunkBytes( iff, buf, samples ) ) != samples )
2683 break;
2685 err = samples = 0L;
2690 if( ! err )
2692 err = PopChunk( iff );
2696 FreeVec( buf );
2698 else
2700 err = ERROR_NO_FREE_STORE;
2704 ** write uncompressed svx file
2706 else
2709 ** create a stereo BODY
2711 if( stereo )
2713 if( ! ( err = PushChunk( iff, type, ID_BODY, IFFSIZE_UNKNOWN ) ) )
2715 BYTE *buf;
2716 LONG bufsize = sampleLength;
2718 while( ! ( buf = AllocVec( UMult( bufsize, bps ), MEMF_PUBLIC ) ) )
2720 if( ( bufsize /= 2 ) < 1024L )
2722 break;
2726 if( buf )
2728 LONG i;
2730 for( i = 0; i < 2 && ! err; i++, sample+=bps )
2732 LONG samples = bufsize, length = sampleLength;
2733 BYTE *src = sample;
2735 while( length )
2737 ULONG bytes = UMult( samples, bps );
2739 if( sampletype == SDTST_S16S )
2741 WORD *dst = (WORD *)buf,
2742 *src_p = (WORD *)src;
2743 LONG c;
2745 for( c = samples; c; c--, src_p+=2 )
2747 *dst++ = *src_p;
2750 src = (BYTE *) src_p;
2752 else
2754 BYTE *dst = buf;
2755 LONG c;
2757 for( c = samples; c; c--, src+=2 )
2759 *dst++ = *src;
2763 if( ( err = WriteChunkBytes( iff, buf, bytes ) ) != bytes )
2765 break;
2768 if( (length-=samples) < samples )
2770 samples = length;
2773 err = 0L;
2778 else
2780 err = ERROR_NO_FREE_STORE;
2783 if( ! err )
2785 err = PopChunk( iff );
2790 ** write uncompressed mono sample
2792 else
2794 err = WriteChunk( cb, iff, type, ID_BODY, sample, UMult( sampleLength, bps ) );
2800 if( ! err )
2802 err = PopChunk( iff );
2806 return( err );
2809 /****************************************************************************/
2811 IPTR __regargs Sound_WRITE( Class *cl, Object *o, struct dtWrite *dtw )
2813 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
2814 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2815 struct IFFHandle *iff;
2816 struct SignalSemaphore *lock = &((struct DTSpecialInfo *)G( o )->SpecialInfo)->si_Lock;
2817 LONG err = 0L;
2819 dbug( kprintf( "DTM_WRITE / DTM_COPY\n" ); )
2821 ObtainSemaphoreShared( &cb->cb_LibLock );
2823 if( id->Sample )
2825 ObtainSemaphoreShared( lock );
2827 if( ( iff = AllocIFF() ) )
2829 if( dtw->MethodID == DTM_WRITE )
2831 dbug( kprintf( "DTWM_RAW\n" ); )
2833 if( ( iff->iff_Stream = (IPTR)dtw->dtw_FileHandle ) )
2835 InitIFFasDOS( iff );
2837 else
2839 dbug( kprintf( "NULL filehandle\n"); )
2840 err = ERROR_INVALID_LOCK;
2843 else
2845 dbug( kprintf( "DTM_COPY\n" ); )
2847 if( ( iff->iff_Stream = (IPTR) OpenClipboard( PRIMARY_CLIP ) ) )
2849 InitIFFasClip( iff );
2851 else
2853 dbug( kprintf( "Cant open clipboard\n" ); )
2854 err = ERROR_OBJECT_IN_USE;
2858 if( ! err )
2860 if( ( err = OpenIFF( iff, IFFF_WRITE ) ) )
2862 err = ifferr2doserr[-err-1];
2863 dbug( kprintf( "OpenIFF() failed\n" ); )
2867 else
2869 err = ERROR_NO_FREE_STORE;
2870 dbug( kprintf( "AllocIFF failed\n" ); )
2873 if( ! err )
2875 dbug( kprintf( "Everything fine so far ...\n" ); )
2877 if( id->SampleType >= SDTST_M16S && cb->cb_AIFF )
2879 err = WriteAIFF( cb, o, iff, id );
2881 else
2883 err = WriteSVX( cb, o, iff, id );
2886 if( err < 0L )
2888 err = ifferr2doserr[-err-1];
2891 else
2893 dbug( kprintf( "Something failed\n" ); )
2896 dbug( kprintf( "closing iff stream\n" ); )
2898 CloseIFF( iff );
2900 if( dtw->MethodID == DTM_COPY )
2902 CloseClipboard( (struct ClipboardHandle *)iff->iff_Stream );
2905 FreeIFF( iff );
2907 ReleaseSemaphore( lock );
2909 else
2911 err = ERROR_REQUIRED_ARG_MISSING;
2914 ReleaseSemaphore( &cb->cb_LibLock );
2916 SetIoErr( err );
2917 return( err ? FALSE : TRUE );
2920 /****************************************************************************/
2923 ** test if dblscan screenmode
2924 ** taken from the ahi paula driver by Martin Blom
2926 #if 0
2927 BOOL Is31Khz( struct ClassBase *cb )
2929 BOOL ret = FALSE;
2931 /* check for ocs */
2932 #ifdef __MAXON__
2933 extern struct Library *GfxBase, *IntuitionBase;
2935 if( ((struct GfxBase *)GfxBase)->ChipRevBits0 & ( GFXF_HR_DENISE|GFXF_AA_LISA ) )
2936 #else
2937 #undef GfxBase
2938 if( ((struct GfxBase *)cb->cb_GfxBase)->ChipRevBits0 & ( GFXF_HR_DENISE|GFXF_AA_LISA ) )
2939 #define GfxBase cb->cb_GfxBase
2940 #endif
2942 ULONG lock, modeid;
2944 lock = LockIBase( 0L );
2945 #ifdef __MAXON__
2946 modeid = GetVPModeID( & ((struct IntuitionBase *)IntuitionBase)->FirstScreen->ViewPort );
2947 #else
2948 #undef IntuitionBase
2949 modeid = GetVPModeID( & ((struct IntuitionBase *)cb->cb_IntuitionBase)->FirstScreen->ViewPort );
2950 #define IntuitionBase cb->cb_IntuitionBase
2951 #endif
2952 UnlockIBase( lock );
2954 /* gfxboard */
2955 if( modeid & 0x40000000 )
2957 Forbid();
2958 if( FindTask( "Picasso96" ) )
2960 UBYTE buf[16];
2962 Permit();
2964 if( GetVar( "Picasso96/AmigaVideo", buf, sizeof( buf ), GVF_GLOBAL_ONLY ) )
2966 if( ! Strnicmp( buf, "31Khz" , 5L ) )
2968 ret = TRUE;
2972 else
2974 #ifdef __MAXON__
2975 struct copinit *ci = ((struct GfxBase *)GfxBase)->copinit;
2976 #else
2977 #undef GfxBase
2978 struct copinit *ci = ((struct GfxBase *)cb->cb_GfxBase)->copinit;
2979 #define GfxBase cb->cb_GfxBase
2980 #endif
2981 Permit();
2983 if( ( ci->fm0[ 0 ] != 0x01fc ) || ( ci->fm0[ 1 ] & 0xc000 ) )
2985 ret = TRUE;
2989 /* native screen */
2990 else
2992 struct MonitorInfo moni;
2994 if( GetDisplayInfoData( NULL, (UBYTE *) &moni, sizeof( moni ), DTAG_MNTR, modeid ) )
2996 if( moni.TotalColorClocks * moni.TotalRows / ( 2 * ( moni.TotalRows - moni.MinRow + 1 ) ) <= 64 )
2998 ret = TRUE;
3004 return ret;
3006 #endif
3007 /****************************************************************************/
3009 void __regargs CalcPanVol( UWORD overall, ULONG pan, UWORD *leftvol, UWORD *rightvol )
3011 pan = ( pan << 6 ) >> 16;
3012 *rightvol = pan ? overall / ( 64 / pan ) : 0;
3013 *leftvol = overall - *rightvol;
3016 /****************************************************************************/
3018 void __regargs RemoveRequest( struct IORequest *ior )
3020 #if !defined(__MAXON__) && !defined(__AROS__)
3021 #undef SysBase
3022 struct Library *SysBase = (*(struct Library **)4L);
3023 #endif
3024 struct Node *ln, *succ;
3026 Disable();
3027 for( ln = ior->io_Message.mn_ReplyPort->mp_MsgList.lh_Head;
3028 (succ = ln->ln_Succ); ln = succ )
3030 if( ln == &ior->io_Message.mn_Node )
3032 Remove( ln );
3033 SetSignal( 0L, 1L << ior->io_Message.mn_ReplyPort->mp_SigBit );
3034 break;
3037 Enable();
3038 #if !defined(__MAXON__) && !defined(__AROS__)
3039 #undef SysBase
3040 #define SysBase cb->cb_SysBase
3041 #endif
3044 /****************************************************************************/
3046 #define LEFT_CHANNEL_0 1
3047 #define RIGHT_CHANNEL_1 2
3048 #define RIGHT_CHANNEL_2 4
3049 #define LEFT_CHANNEL_3 8
3050 #define MAX_SAMPLE 131072
3051 #define MAX_SAMPLE_RATE 28867
3052 #define LEFT_MASK (LEFT_CHANNEL_0|LEFT_CHANNEL_3)
3053 #define RIGHT_MASK (RIGHT_CHANNEL_1|RIGHT_CHANNEL_2)
3055 enum {
3056 AUDIO_CONTROL,
3057 AUDIO_LEFT,
3058 AUDIO_LEFT2,
3059 AUDIO_RIGHT,
3060 AUDIO_RIGHT2,
3061 NUM_REQUESTS
3064 /****************************************************************************/
3066 void __regargs SetTDMode( struct ClassBase *cb, struct InstanceData *id, ULONG mode )
3068 if( id->ControlPanel )
3070 IPTR oldmode = mode;
3072 ObtainSemaphoreShared( &id->Lock );
3074 /* avoid deadlocks */
3075 GetAttr( TDECK_Mode, (Object *)id->TapeDeckGadget, &oldmode );
3076 if( oldmode != mode )
3078 SetGadgetAttrs( id->TapeDeckGadget, id->Window, id->Requester,
3079 TDECK_Mode, mode, TAG_DONE );
3082 ReleaseSemaphore( &id->Lock );
3086 /****************************************************************************/
3088 void PlayerProc( void )
3090 #if !defined(__MAXON__) && !defined(__AROS__)
3091 #undef SysBase
3092 struct Library *SysBase = *(struct Library **)4L;
3093 #endif
3094 struct Process *pr = (struct Process *) FindTask( NULL );
3095 struct MsgPort *mp, *mpaudio = NULL;
3096 struct IOAudio *ioaudio[NUM_REQUESTS] = { };
3097 struct ClassBase *cb;
3098 struct InstanceData *id;
3099 LONG numChAllocated, samples, buffersize, length, cycles,
3100 loops, audiompmsk = 0, mpmsk;
3101 BOOL releaseAudio = FALSE, restart, paused = FALSE;
3102 BYTE *sample, *buffer[4] = {};
3104 mp = &pr->pr_MsgPort;
3105 mpmsk = 1L << mp->mp_SigBit;
3107 dbug( kprintf("child process launched\n"); )
3109 for( ;; )
3111 struct ObjectMsg *msg;
3112 LONG rcv;
3114 rcv = Wait( mpmsk | audiompmsk );
3116 if( rcv & mpmsk )
3118 while( ( msg = (struct ObjectMsg *) GetMsg( mp ) ) )
3120 switch( msg->Command )
3122 case COMMAND_NEXT_BUFFER:
3123 if( releaseAudio )
3125 ObtainSemaphoreShared( &id->Lock );
3126 sample = id->Sample;
3127 length = id->SampleLength;
3128 samples = ( length > buffersize ) ? buffersize : length;
3129 rcv = audiompmsk;
3130 ReleaseSemaphore( &id->Lock );
3132 break;
3134 case COMMAND_INIT:
3135 dbug( kprintf( "child/COMMAND_INIT\n"); )
3137 id = (struct InstanceData *) msg->Data;
3138 cb = id->ClassBase;
3140 if( ! ( msg->Data = mp = CreateMsgPort() ) )
3142 ReplyMsg( &msg->Message );
3143 return;
3146 mpmsk = 1L << mp->mp_SigBit;
3147 break;
3149 case COMMAND_EXIT:
3150 case COMMAND_STOP:
3151 dbug( kprintf( "child/COMMAND_EXIT or STOP\n"); )
3153 if( releaseAudio )
3155 LONG i;
3157 SetTDMode( cb, id, BUT_STOP );
3159 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
3161 struct IORequest *ioa = (struct IORequest *) ioaudio[ i ];
3163 if( CheckIO( ioa ) )
3165 RemoveRequest( ioa );
3167 else
3169 AbortIO( ioa );
3170 WaitIO( ioa );
3174 CloseDevice( (struct IORequest *) ioaudio[ AUDIO_CONTROL ] );
3175 DeleteMsgPort( mpaudio );
3176 audiompmsk = 0L;
3177 FreeVec( ioaudio[ AUDIO_CONTROL ] );
3178 FreeVec( buffer[0] ); buffer[0] = NULL;
3179 releaseAudio = FALSE;
3182 if( msg->Command == COMMAND_EXIT )
3184 Forbid();
3185 ReplyMsg( &msg->Message );
3186 DeleteMsgPort( mp );
3187 return;
3189 break;
3191 case COMMAND_PERVOL:
3193 dbug( kprintf( "child/COMMAND_PERVOL\n"); )
3195 if( releaseAudio )
3197 struct IOAudio *ioa = ioaudio[ AUDIO_CONTROL ];
3199 ObtainSemaphoreShared( &id->Lock );
3201 if( numChAllocated == 1L || IsStereo( id->SampleType ) )
3203 ioa->ioa_Period = Freq2Period( id->Frequency );
3204 ioa->ioa_Volume = id->Volume;
3205 ioa->ioa_Request.io_Flags = 0;
3206 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
3207 DoIO( &ioa->ioa_Request );
3209 Forbid();
3210 ioaudio[ AUDIO_LEFT ]->ioa_Volume =
3211 ioaudio[ AUDIO_LEFT2 ]->ioa_Volume =
3212 ioaudio[ AUDIO_RIGHT ]->ioa_Volume =
3213 ioaudio[ AUDIO_RIGHT2 ]->ioa_Volume = id->Volume;
3214 Permit();
3216 else
3218 UWORD leftvol, rightvol;
3219 ULONG oldmask = (ULONG) ioa->ioa_Request.io_Unit;
3221 CalcPanVol( id->Volume, id->Panning, &leftvol, &rightvol );
3223 ioa->ioa_Request.io_Command = CMD_STOP;
3224 DoIO( &ioa->ioa_Request );*/
3226 ioa->ioa_Request.io_Unit = (struct Unit *) ( oldmask & LEFT_MASK );
3227 ioa->ioa_Period = Freq2Period( id->Frequency );
3228 ioa->ioa_Volume = leftvol;
3229 ioa->ioa_Request.io_Flags = 0;
3230 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
3231 DoIO( &ioa->ioa_Request );
3233 ioa->ioa_Request.io_Unit = (struct Unit *) ( oldmask & RIGHT_MASK );
3234 ioa->ioa_Period = Freq2Period( id->Frequency );
3235 ioa->ioa_Volume = rightvol;
3236 ioa->ioa_Request.io_Flags = 0;
3237 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
3238 DoIO( &ioa->ioa_Request );
3240 ioa->ioa_Request.io_Unit = (struct Unit *) oldmask;
3242 Forbid();
3243 ioaudio[ AUDIO_LEFT ]->ioa_Volume =
3244 ioaudio[ AUDIO_LEFT2 ]->ioa_Volume = leftvol;
3245 ioaudio[ AUDIO_RIGHT ]->ioa_Volume =
3246 ioaudio[ AUDIO_RIGHT2 ]->ioa_Volume = rightvol;
3247 Permit();
3250 ioa->ioa_Request.io_Command = CMD_START;
3251 DoIO( &ioa->ioa_Request );*/
3254 Forbid();
3255 ioaudio[ AUDIO_LEFT ]->ioa_Period =
3256 ioaudio[ AUDIO_LEFT2 ]->ioa_Period =
3257 ioaudio[ AUDIO_RIGHT ]->ioa_Period =
3258 ioaudio[ AUDIO_RIGHT2 ]->ioa_Period = Freq2Period( id->Frequency );
3259 Permit();
3261 ReleaseSemaphore( &id->Lock );
3264 break;
3266 case COMMAND_PAUSE:
3268 dbug( kprintf( "child/COMMAND_PAUSE\n"); )
3270 if( releaseAudio )
3272 if( ! paused )
3274 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_STOP;
3275 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
3276 paused = TRUE;
3280 break;
3282 case COMMAND_PLAY:
3284 dbug( kprintf( "child/COMMAND_PLAY\n"); )
3286 ObtainSemaphoreShared( &id->Lock );
3288 if( releaseAudio )
3290 if( paused )
3292 rcv = audiompmsk;
3293 restart = TRUE;
3294 paused = FALSE;
3296 else
3298 LONG i;
3300 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
3302 struct IORequest *ioa = &ioaudio[ i ]->ioa_Request;
3304 if( CheckIO( ioa ) )
3306 RemoveRequest( ioa );
3308 else
3310 AbortIO( ioa );
3311 WaitIO( ioa );
3315 sample = id->Sample;
3316 length = id->SampleLength;
3317 samples = buffersize;
3318 if( length <= buffersize )
3320 loops = 1L;
3321 cycles = id->Cycles;
3323 else
3325 loops = id->Cycles;
3326 cycles = 1L;
3330 else
3332 UBYTE ChMap[] = {
3333 LEFT_CHANNEL_0 | RIGHT_CHANNEL_1,
3334 LEFT_CHANNEL_3 | RIGHT_CHANNEL_2,
3335 LEFT_CHANNEL_0, LEFT_CHANNEL_3,
3336 RIGHT_CHANNEL_1, RIGHT_CHANNEL_2
3338 struct IOAudio *ioa;
3339 LONG i;
3341 if( ! id->Sample || ! id->SampleLength )
3343 break;
3346 dbug( kprintf( "child/allocating requests\n" ); )
3348 /*- allocate requests and msgport -*/
3349 if( ! ( ioa = AllocVec( sizeof( *ioa ) * NUM_REQUESTS, MEMF_PUBLIC|MEMF_CLEAR ) ) ||
3350 ! ( mpaudio = CreateMsgPort() ) )
3352 FreeVec( ioa );
3353 SetTDMode( cb, id, BUT_STOP );
3354 break;
3357 for( i = 0; i < NUM_REQUESTS; i++ )
3359 ioaudio[i] = ioa++;
3362 audiompmsk = 1L << mpaudio->mp_SigBit;
3364 /*- Open audio.device and intialize requests -*/
3365 ioa = ioaudio[ AUDIO_CONTROL ];
3366 ioa->ioa_Request.io_Message.mn_ReplyPort = mpaudio;
3367 ioa->ioa_Request.io_Message.mn_Length = sizeof( *ioa );
3369 ioa->ioa_Data = ChMap;
3370 ioa->ioa_Length = sizeof( ChMap );
3372 if( ! OpenDevice( "audio.device", 0L, (struct IORequest *) ioa, 0L ) )
3374 /*- make CheckIO() work -*/
3375 ioa->ioa_Request.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
3377 for( i = 1; i < NUM_REQUESTS; i++ )
3379 CopyMem( ioa, ioaudio[i], sizeof( *ioa ) );
3382 for( i = 0; i < sizeof( ChMap ); i++ )
3384 if( (ULONG) ioa->ioa_Request.io_Unit == (ULONG) ChMap[i] )
3386 break;
3390 if( i < 2 )
3392 dbug( kprintf( "child/got two stereo channels\n" ); )
3393 numChAllocated = 2L;
3394 /*- stop device in order to sync stereo channels -*/
3395 ioa->ioa_Request.io_Command = CMD_STOP;
3396 DoIO( &ioa->ioa_Request );
3397 restart = TRUE;
3399 else
3401 dbug( kprintf( "child/got only one channel\n" ); )
3402 numChAllocated = 1L;
3403 restart = FALSE;
3406 ioaudio[ AUDIO_LEFT ]->ioa_Request.io_Unit =
3407 ioaudio[ AUDIO_LEFT2 ]->ioa_Request.io_Unit = (struct Unit *) ( (ULONG) ioa->ioa_Request.io_Unit & LEFT_MASK );
3408 ioaudio[ AUDIO_RIGHT ]->ioa_Request.io_Unit =
3409 ioaudio[ AUDIO_RIGHT2 ]->ioa_Request.io_Unit = (struct Unit *) ( (ULONG) ioa->ioa_Request.io_Unit & RIGHT_MASK );
3411 sample = id->Sample;
3412 length = id->SampleLength;
3414 if( ( id->SampleType == SDTST_M8S ) && ( TypeOfMem( sample ) & MEMF_CHIP ) )
3416 buffersize = samples = ( length > MAX_SAMPLE ) ? MAX_SAMPLE : length;
3417 dbug( kprintf( "child/chip sample\n" ); )
3419 /*- allocate buffers -*/
3420 else
3422 ObtainSemaphoreShared( &cb->cb_LibLock ); /* determine buffersize, don't go below 1k (heavy system load) */
3423 buffersize = ( length > cb->cb_BufferSize ) ? cb->cb_BufferSize : ( ((length+1)/2) < 1024L ? length : (length+1)/2 );
3424 ReleaseSemaphore( &cb->cb_LibLock );
3426 while( ! ( buffer[0] = AllocVec( buffersize << numChAllocated, MEMF_CHIP ) ) )
3428 dbug( kprintf( "child/failed to allocate %ld bytes of buffer\n", buffersize ); )
3429 if( (buffersize /= 2) < 1024L )
3431 break;
3435 samples = buffersize;
3437 dbug( kprintf( "child/Buffer at %08lx, size %ld, num %ld\n", buffer[0], buffersize, numChAllocated*2 ); )
3439 if( buffer[0] == NULL )
3441 CloseDevice( (struct IORequest *) ioa );
3442 DeleteMsgPort( mpaudio );
3443 audiompmsk = 0L;
3444 FreeVec( ioa );
3445 SetTDMode( cb, id, BUT_STOP );
3446 break;
3449 for( i = 1; i < 4; i++ )
3451 buffer[ i ] = buffer[ i-1 ] + buffersize;
3455 if( buffersize <= length )
3457 cycles = id->Cycles;
3458 loops = 1L;
3460 else
3462 cycles = 1L;
3463 loops = id->Cycles;
3466 dbug( kprintf( "child/Sample: %08lx, Length: %ld, Cycles: %ld, Loops: %ld, Freq: %ld\n", sample, length, cycles, loops, id->Frequency ); )
3468 releaseAudio = TRUE;
3469 rcv = audiompmsk;
3470 SetTDMode( cb, id, BUT_PLAY );
3472 else
3474 dbug( kprintf("child/can't open audio.device\n"); )
3475 DeleteMsgPort( mpaudio );
3476 audiompmsk = 0L;
3477 FreeVec( ioa );
3478 SetTDMode( cb, id, BUT_STOP );
3482 ReleaseSemaphore( &id->Lock );
3484 break;
3485 } // switch
3487 if( msg->Message.mn_ReplyPort )
3489 ReplyMsg( &msg->Message );
3491 else // NT_FREEMSG
3493 FreeVec( msg );
3495 } // while
3496 } // if
3498 if( rcv & audiompmsk )
3500 ObtainSemaphoreShared( &id->Lock );
3502 if( length == 0L )
3504 LONG i;
3505 BOOL Done = TRUE;
3507 dbug( kprintf( "child/reachend end of sample\n" ); )
3509 /*- wait for any outstanding request -*/
3510 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
3512 struct IORequest *ioa = &ioaudio[i]->ioa_Request;
3514 if( ! CheckIO( ioa ) )
3516 /* don't block doing WaitIO() */
3517 Done = FALSE;
3519 else
3521 RemoveRequest( ioa );
3525 if( ! Done || id->Continuous )
3527 ReleaseSemaphore( &id->Lock );
3528 continue;
3531 if( id->Repeat || ( --loops > 0L ) )
3533 dbug( kprintf( "child/%ld loops to go\n", loops ); )
3535 sample = id->Sample;
3536 length = id->SampleLength;
3537 samples = buffersize;
3538 /*- stop device in order to sync stereo channels -*/
3539 if( numChAllocated == 2L )
3541 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_STOP;
3542 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
3543 restart = TRUE;
3545 else
3547 restart = FALSE;
3550 else
3552 dbug( kprintf("child/cleanup\n"); )
3554 /*- cleanup -*/
3555 CloseDevice( &ioaudio[AUDIO_CONTROL]->ioa_Request );
3556 FreeVec( buffer[0] ); buffer[0] = NULL;
3557 FreeVec( ioaudio[ AUDIO_CONTROL ] );
3558 DeleteMsgPort( mpaudio ); audiompmsk = 0L;
3559 releaseAudio = FALSE;
3561 SetTDMode( cb, id, BUT_STOP );
3563 if( id->SignalTask && id->SignalBit != -1 )
3565 Signal( id->SignalTask, 1L << id->SignalBit );
3570 if( length )
3572 LONG i;
3573 UWORD volleft, volright;
3575 if( numChAllocated == 1L || IsStereo( id->SampleType ) )
3577 volright =
3578 volleft = id->Volume;
3580 else
3582 CalcPanVol( id->Volume, id->Panning, &volleft, &volright );
3585 /*- we work doublebuffered -*/
3586 for( i = 0; i < 2; i++ )
3588 struct IOAudio *ioa_left = ioaudio[ i + AUDIO_LEFT ],
3589 *ioa_right = ioaudio[ i + AUDIO_RIGHT ];
3591 /*- get free audiorequest -*/
3592 if( CheckIO( (struct IORequest *) ioa_left ) && CheckIO( (struct IORequest *) ioa_right ) )
3594 BYTE *data_left, *data_right;
3596 dbug( kprintf( "child/Request pair #%ld is free\n", i ); )
3598 RemoveRequest( (struct IORequest *) ioa_left );
3599 RemoveRequest( (struct IORequest *) ioa_right );
3601 if( buffer[ 0 ] )
3603 if( IsStereo( id->SampleType ) )
3605 LONG c, add = ( id->SampleType == SDTST_S16S ) ? 2 : 1;
3607 if( numChAllocated == 2L )
3609 BYTE *buf_left = buffer[ i * 2 ],
3610 *buf_right = buffer[ i * 2 + 1 ];
3612 data_left = buf_left;
3613 data_right = buf_right;
3615 for( c = samples; c; c-- )
3617 *buf_left++ = *sample; sample += add;
3618 *buf_right++ = *sample; sample += add;
3621 else
3623 BYTE *buf = buffer[ i ];
3625 data_left =
3626 data_right = buf;
3628 for( c = samples; c; c--, sample+=(add<<1) )
3630 *buf++ = ( sample[0] + sample[add] ) >> 1;
3634 else
3636 BYTE *buf = buffer[ i ];
3638 data_left =
3639 data_right = buf;
3641 if( id->SampleType == SDTST_M8S )
3643 if( (ULONG) sample&3 || (ULONG) buf&3 || samples&3 )
3645 CopyMem( sample, buf, samples );
3647 else
3649 CopyMemQuick( sample, buf, samples );
3652 sample += samples;
3654 else
3656 LONG c;
3658 for( c = samples; c; c--, sample+=2 )
3660 *buf++ = *sample;
3665 else
3667 data_left =
3668 data_right = sample;
3669 sample += samples;
3672 ioa_left->ioa_Data = data_left;
3673 ioa_left->ioa_Length = samples;
3674 ioa_left->ioa_Cycles = cycles;
3675 ioa_left->ioa_Period = Freq2Period( id->Frequency );
3676 ioa_left->ioa_Volume = volleft;
3677 ioa_left->ioa_Request.io_Flags = ADIOF_PERVOL;
3678 ioa_left->ioa_Request.io_Command = CMD_WRITE;
3679 BeginIO( (struct IORequest *) ioa_left );
3681 if( numChAllocated == 2L )
3683 ioa_right->ioa_Data = data_right;
3684 ioa_right->ioa_Length = samples;
3685 ioa_right->ioa_Cycles = cycles;
3686 ioa_right->ioa_Period = Freq2Period( id->Frequency );
3687 ioa_right->ioa_Volume = volright;
3688 ioa_right->ioa_Request.io_Flags = ADIOF_PERVOL;
3689 ioa_right->ioa_Request.io_Command = CMD_WRITE;
3690 BeginIO( (struct IORequest *) ioa_right );
3693 if( (length-=samples) < samples )
3695 samples = length;
3696 } // if
3697 } // if
3698 else
3700 dbug( kprintf( "child/Req #%ld in use\n", i ); )
3703 if( ! length )
3705 /* a continuous stream of data? */
3706 if( id->Continuous )
3708 /* notify */
3709 if( id->SignalTask && id->SignalBit != -1 )
3711 Signal( id->SignalTask, 1L << id->SignalBit );
3715 break;
3717 } // for
3719 if( restart )
3721 dbug( kprintf( "child/starting stereo channels\n" ); )
3722 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_START;
3723 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
3724 restart = FALSE;
3725 } // if
3726 } // if
3728 ReleaseSemaphore( &id->Lock );
3729 } // if
3730 } // while
3732 #if !defined(__MAXON__) && !defined(__AROS__)
3733 #define SysBase cb->cb_SysBase
3734 #endif
3737 /****************************************************************************/
3739 void __regargs CloseAHI( struct MsgPort *mp, struct AHIRequest *ahir )
3741 #if !defined(__MAXON__) && !defined(__AROS__)
3742 #undef SysBase
3743 struct Library *SysBase = (*(struct Library **)4L);
3744 #endif
3745 CloseDevice( (struct IORequest *) ahir );
3746 DeleteIORequest( (struct IORequest *) ahir );
3747 DeleteMsgPort( mp );
3748 #if !defined(__MAXON__) && !defined(__AROS__)
3749 #define SysBase cb->cb_SysBase
3750 #endif
3753 /****************************************************************************/
3755 struct Library * __regargs OpenAHI( struct MsgPort **mpp, struct AHIRequest **iop )
3757 #if !defined(__MAXON__) && !defined(__AROS__)
3758 #undef SysBase
3759 struct Library *SysBase = (*(struct Library **)4L);
3760 #endif
3761 struct MsgPort *mp;
3762 struct AHIRequest *ahir;
3764 mp = CreateMsgPort();
3765 if( ( ahir = (struct AHIRequest *) CreateIORequest( mp, sizeof( struct AHIRequest ) ) ) )
3767 ahir->ahir_Version = 4;
3768 if( ! OpenDevice( "ahi.device", AHI_NO_UNIT, (struct IORequest *)ahir, 0L ) )
3770 *mpp = mp;
3771 *iop = ahir;
3772 return( (struct Library *) ahir->ahir_Std.io_Device );
3774 else
3776 dbug( kprintf( "Can't open ahi.device v4\n" ); )
3779 DeleteIORequest( (struct IORequest *) ahir );
3781 else
3783 dbug( kprintf( "no memory for ahirequest or msgport\n" ); )
3785 DeleteMsgPort( mp );
3787 return FALSE;
3788 #if !defined(__MAXON__) && !defined(__AROS__)
3789 #define SysBase cb->cb_SysBase
3790 #endif
3793 /****************************************************************************/
3796 struct SoundFuncData {
3797 UWORD CyclesLeft;
3798 UWORD Cycles;
3799 UWORD Channels;
3800 UWORD Sound;
3801 BOOL Continuous;
3802 BOOL Valid[2];
3803 BOOL Restart;
3804 BOOL *Repeat;
3805 struct Task *SigTask;
3806 #if !defined(__MAXON__) && !defined(__AROS__)
3807 #undef SysBase
3808 struct Library *AHIBase;
3809 struct Library *SysBase;
3810 #define AHIBase sfd->AHIBase
3811 #define SysBase sfd->SysBase
3812 #endif
3815 #ifdef __MAXON__
3816 void SoundFunc( struct Hook *h, struct AHIAudioCtrl *actrl, struct AHISoundMessage *ahism )
3817 #else
3818 void __interrupt SoundFunc( REG(a0, struct Hook *h), REG(a2, struct AHIAudioCtrl *actrl), REG(a1, struct AHISoundMessage *ahism) )
3819 #endif
3821 struct SoundFuncData *sfd = (struct SoundFuncData *) h->h_Data;
3823 dbug( kprintf( "SoundFunc\n" ); )
3825 if( ! ( *sfd->Repeat ) )
3827 if( ! ( sfd->CyclesLeft-- ) )
3829 LONG i, snd = sfd->Sound;
3831 sfd->Valid[ snd ] = FALSE;
3833 sfd->Sound = snd = ( sfd->Continuous ) ? ! snd : AHI_NOSOUND;
3834 /* no echos please */
3835 if( ! sfd->Valid[ snd ] )
3837 snd = AHI_NOSOUND;
3838 sfd->Restart = TRUE;
3841 for( i = 0; i < sfd->Channels; i++ )
3843 AHI_SetSound( i, snd, 0L, 0L, actrl, 0L );
3846 sfd->CyclesLeft = sfd->Cycles;
3848 Signal ( sfd->SigTask, SIGBREAKF_CTRL_C );
3853 #if !defined(__MAXON__) && !defined(__AROS__)
3854 #undef AHIBase
3855 #undef SysBase
3856 #define SysBase cb->cb_SysBase
3857 #endif
3859 /****************************************************************************/
3861 void PlayerProcAHI( void )
3863 #if !defined(__MAXON__) && !defined(__AROS__)
3864 struct Library *SysBase = (*(struct Library **)4L);
3865 struct Library *AHIBase = NULL;
3866 #endif
3867 struct Process *pr = (struct Process *) FindTask( NULL );
3868 struct MsgPort *mp, *AHImp;
3869 struct AHIRequest *ahir;
3870 struct AHIAudioCtrl *actrl;
3871 struct SoundFuncData *sfd;
3872 struct Hook *SoundHook = NULL;
3873 struct ClassBase *cb;
3874 struct InstanceData *id;
3875 ULONG mpmsk, numCh, buffersize;
3876 BOOL stereo, paused = FALSE, failed;
3877 static UBYTE sdtst2ahist[] = { AHIST_M8S, AHIST_S8S, AHIST_M16S, AHIST_S16S };
3878 BYTE *buffer = NULL;
3880 mp = &pr->pr_MsgPort;
3881 mpmsk = 1L << mp->mp_SigBit;
3883 dbug( kprintf( "child launched\n" ); )
3885 for( ;; )
3887 LONG rcv;
3888 struct ObjectMsg *msg;
3890 rcv = Wait( mpmsk | SIGBREAKF_CTRL_C );
3892 if( rcv & mpmsk )
3894 while( ( msg = (struct ObjectMsg *) GetMsg( mp ) ) )
3896 switch( msg->Command )
3898 case COMMAND_NEXT_BUFFER:
3900 dbug( kprintf( "child: COMMAND_NEXT_BUFFER\n"); )
3902 ObtainSemaphoreShared( &id->Lock );
3904 if( AHIBase )
3906 BYTE *dst = ( sfd->Sound ) ? &buffer[ buffersize ] : buffer;
3907 ULONG transfer = UMult( id->SampleLength, bytesPerPoint[ id->SampleType ] ), i;
3909 if( transfer > buffersize )
3911 transfer = buffersize;
3914 if( (ULONG)id->Sample&3 || (ULONG)dst&3 || transfer&3 )
3916 CopyMem( id->Sample, dst, transfer );
3918 else
3920 CopyMemQuick( id->Sample, dst, transfer );
3923 for( i = transfer; i < buffersize; i++ )
3925 dst[ i ] = 0;
3928 sfd->Valid[ sfd->Sound ] = TRUE;
3930 /* new sample wasn't available fast enough */
3931 if( sfd->Restart )
3933 sfd->Restart = FALSE;
3935 dbug( kprintf( "restart playback\n" ); )
3937 for( i = 0; i < numCh; i++ )
3939 AHI_SetSound( i, sfd->Sound, 0,0, actrl, AHISF_IMM );
3944 ReleaseSemaphore( &id->Lock );
3946 break;
3948 case COMMAND_INIT:
3949 dbug( kprintf("child: COMMAND_INIT\n"); )
3951 id = (struct InstanceData *) msg->Data;
3952 cb = id->ClassBase;
3954 if( ! ( mp = msg->Data = CreateMsgPort() ) )
3956 ReplyMsg( &msg->Message );
3957 return;
3960 mpmsk = 1L << mp->mp_SigBit;
3961 break;
3963 case COMMAND_EXIT:
3964 case COMMAND_STOP:
3966 dbug( kprintf("child: COMMAND_STOP/EXIT\n"); )
3968 if( AHIBase )
3970 AHI_FreeAudio( actrl );
3971 FreeVec( SoundHook );
3972 FreeVec( buffer );
3973 buffer = NULL;
3974 CloseAHI( AHImp, ahir );
3975 AHIBase = NULL;
3977 SetTDMode( cb, id, BUT_STOP );
3980 if( msg->Command == COMMAND_EXIT )
3982 Forbid();
3983 ReplyMsg( &msg->Message );
3984 DeleteMsgPort( mp );
3985 return;
3988 break;
3990 case COMMAND_PERVOL:
3991 dbug( kprintf("child: COMMAND_PERVOL\n"); )
3993 if( AHIBase )
3995 ULONG freq, vol, pan, i;
3997 ObtainSemaphoreShared( &id->Lock );
3998 pan = id->Panning;
3999 vol = ( id->Volume << 10 );
4000 freq = id->Frequency;
4001 ReleaseSemaphore( &id->Lock );
4003 for( i = 0; i < numCh; i++ )
4005 if( ! paused )
4007 AHI_SetFreq( i, freq, actrl, AHISF_IMM );
4009 AHI_SetVol( i, vol, pan, actrl, AHISF_IMM );
4012 break;
4014 case COMMAND_PAUSE:
4016 if( AHIBase )
4018 if( ! paused )
4020 LONG i;
4022 for( i = 0; i < numCh; i++ )
4024 AHI_SetFreq( i, 0L, actrl, AHISF_IMM );
4027 paused = TRUE;
4031 break;
4033 case COMMAND_PLAY:
4034 dbug( kprintf("child: COMMAND_PLAY\n"); )
4036 // ObtainSemaphoreShared( &id->Lock );
4038 if( AHIBase )
4040 if( paused )
4042 LONG i;
4044 for( i = 0; i < numCh; i++ )
4046 AHI_SetFreq( i, id->Frequency, actrl, AHISF_IMM );
4049 paused = FALSE;
4051 else
4053 LONG i;
4055 AHI_ControlAudio( actrl,
4056 AHIC_Play, FALSE,
4057 TAG_DONE );
4059 for( i = 0; i < numCh; i++ )
4061 AHI_SetSound( i, sfd->Sound, 0,0, actrl, AHISF_IMM );
4064 sfd->CyclesLeft = sfd->Cycles;
4066 AHI_ControlAudio( actrl,
4067 AHIC_Play, TRUE,
4068 TAG_DONE );
4071 else
4073 failed = TRUE;
4075 if( ( AHIBase = OpenAHI( &AHImp, &ahir ) ) )
4077 stereo = IsStereo( id->SampleType );
4079 if( ( SoundHook = (struct Hook *) AllocVec( sizeof( *SoundHook ) + sizeof( *sfd ), MEMF_CLEAR|MEMF_PUBLIC ) ) )
4081 ULONG audioID, mixfreq;
4082 #ifndef __AROS__
4083 extern void HookEntry( void );
4084 #endif
4086 numCh = stereo ? 2 : 1;
4088 sfd = (struct SoundFuncData *) (SoundHook+1);
4089 #if defined(__MAXON__) || defined(__AROS__)
4090 SoundHook->h_Entry = (HOOKFUNC) HookEntry;
4091 SoundHook->h_SubEntry = (HOOKFUNC) SoundFunc;
4092 #else
4093 SoundHook->h_Entry = (HOOKFUNC) SoundFunc;
4094 #endif
4095 SoundHook->h_Data = (APTR) sfd;
4097 sfd->SigTask = &pr->pr_Task;
4098 sfd->Channels = numCh;
4099 sfd->Cycles =
4100 sfd->CyclesLeft = UMult( id->Cycles, numCh );
4101 // sfd->Sound = 0;
4102 sfd->Continuous = id->Continuous;
4103 sfd->Valid[ 0 ] = TRUE;
4104 sfd->Repeat = (BOOL *) &id->Repeat;
4105 // sfd->Valid[ 1 ] = FALSE;
4106 // sfd->Restart = FALSE;
4107 #if !defined(__MAXON__) && !defined(__AROS__)
4108 sfd->AHIBase = AHIBase;
4109 sfd->SysBase = SysBase;
4110 #endif
4111 dbug( kprintf("child: ahi is open\n"); )
4113 ObtainSemaphoreShared( &cb->cb_LibLock );
4115 mixfreq = cb->cb_AHIMixFrequency;
4117 if( cb->cb_ForceAHIMode )
4119 audioID = cb->cb_AHIModeID;
4121 else
4123 if( ( audioID = AHI_BestAudioID(
4124 ( cb->cb_AHIModeID ? AHIDB_AudioID : TAG_IGNORE ), cb->cb_AHIModeID,
4125 AHIDB_Volume, TRUE,
4126 ( ! stereo ? TAG_IGNORE : AHIDB_Stereo ), TRUE,
4127 ( ! stereo ? AHIDB_Panning : TAG_IGNORE ), TRUE,
4128 TAG_DONE ) ) == AHI_INVALID_ID )
4130 audioID = AHI_DEFAULT_ID;
4131 dbug( kprintf("child: bestaid failed\n"); )
4135 ReleaseSemaphore( &cb->cb_LibLock );
4137 if( ( actrl = AHI_AllocAudio(
4138 AHIA_AudioID, audioID,
4139 AHIA_Channels, numCh,
4140 AHIA_Sounds, ( id->Continuous ) ? 2L : 1L,
4141 AHIA_MixFreq, mixfreq,
4142 ( id->Cycles ? AHIA_SoundFunc : TAG_IGNORE), (IPTR) SoundHook,
4143 TAG_DONE ) ) )
4145 struct AHISampleInfo sample;
4146 ULONG freq, vol;
4148 freq = id->Frequency;
4149 vol = ( id->Volume << 10 );
4151 dbug( kprintf("child: alloc audio okay\n"); )
4153 sample.ahisi_Type = sdtst2ahist[ id->SampleType ];
4154 sample.ahisi_Length = id->SampleLength;
4156 if( id->Continuous )
4158 ULONG playsamples;
4160 AHI_GetAudioAttrs( AHI_INVALID_ID, actrl, AHIDB_MaxPlaySamples,(IPTR) &playsamples, TAG_DONE );
4161 AHI_ControlAudio( actrl, AHIC_MixFreq_Query, (IPTR) &mixfreq, TAG_DONE );
4163 buffersize = UDiv( UMult( playsamples, id->Frequency ), mixfreq );
4165 if( buffersize < id->SampleLength )
4167 buffersize = id->SampleLength;
4170 buffersize = UMult( buffersize, bytesPerPoint[ id->SampleType ] );
4172 if( ( buffer = AllocVec( buffersize*2, MEMF_PUBLIC|MEMF_CLEAR ) ) )
4174 sample.ahisi_Address = buffer;
4176 if( ! AHI_LoadSound( 0, AHIST_DYNAMICSAMPLE, &sample, actrl ) )
4178 sample.ahisi_Address = &buffer[ buffersize ];
4180 failed = (BOOL) AHI_LoadSound( 1, AHIST_DYNAMICSAMPLE, &sample, actrl );
4183 CopyMem( id->Sample, buffer, UMult( id->SampleLength, bytesPerPoint[ id->SampleType ] ) );
4187 else
4189 sample.ahisi_Address = id->Sample;
4191 failed = (BOOL) AHI_LoadSound( 0, AHIST_SAMPLE, &sample, actrl );
4194 dbug( kprintf("child: loading sample\n"); )
4196 if( ! failed )
4198 failed = TRUE;
4200 if( ! AHI_ControlAudio( actrl,
4201 AHIC_Play, TRUE,
4202 TAG_DONE ) )
4204 AHI_Play( actrl,
4205 AHIP_BeginChannel, 0,
4206 AHIP_Freq, freq,
4207 AHIP_Vol, vol,
4208 AHIP_Pan, id->Panning,
4209 AHIP_Sound, 0,
4210 AHIP_EndChannel, 0,
4211 ( stereo ? TAG_IGNORE : TAG_END ), 0L,
4212 AHIP_BeginChannel, 1,
4213 AHIP_Freq, freq,
4214 AHIP_Vol, vol,
4215 AHIP_Pan, id->Panning,
4216 AHIP_Sound, 0,
4217 AHIP_EndChannel, 0,
4218 TAG_DONE );
4220 failed = FALSE;
4222 dbug( kprintf( "child: playback started, freq: %ld\n", freq ); )
4224 else
4226 dbug( kprintf( "child: CtrlAudio failed\n" ); )
4229 else
4231 dbug( kprintf( "child: loadsample failed\n" ); )
4234 else
4236 dbug( kprintf( "child: AllocAudio failed\n"); )
4239 else
4241 dbug( kprintf( "child: No free store\n" ); )
4245 if( failed )
4247 AHI_FreeAudio( actrl );
4248 FreeVec( SoundHook );
4249 FreeVec( buffer );
4250 buffer = NULL;
4251 CloseAHI( AHImp, ahir );
4252 AHIBase = NULL;
4253 SetTDMode( cb, id, BUT_STOP );
4255 else
4257 SetTDMode( cb, id, BUT_PLAY );
4261 // ReleaseSemaphore( &id->Lock );
4262 break;
4265 if( msg->Message.mn_ReplyPort )
4267 ReplyMsg( &msg->Message );
4269 else // NT_FREEMSG
4271 FreeVec( msg );
4276 if( rcv & SIGBREAKF_CTRL_C )
4278 dbug( kprintf( "child: end of sample\n" ); )
4280 if( AHIBase )
4282 ObtainSemaphoreShared( &id->Lock );
4283 if( id->SignalTask && id->SignalBit != -1 )
4285 Signal( id->SignalTask, 1L << id->SignalBit );
4287 ReleaseSemaphore( &id->Lock );
4289 if( ! id->Continuous )
4291 AHI_FreeAudio( actrl );
4292 FreeVec( SoundHook );
4293 FreeVec( buffer );
4294 buffer = NULL;
4295 CloseAHI( AHImp, ahir );
4296 AHIBase = NULL;
4297 SetTDMode( cb, id, BUT_STOP );
4303 #if !defined(__MAXON__) && !defined(__AROS__)
4304 #define SysBase cb->cb_SysBase
4305 #endif
4308 /****************************************************************************/
4310 unsigned __regargs StrLen( STRPTR str )
4312 STRPTR p = str;
4314 while( *str++ );
4316 return( ~(unsigned) (p - str) );
4319 /****************************************************************************/
4321 IPTR __regargs Sound_OBTAINDRAWINFO( Class *cl, Object *o, struct opSet *ops )
4323 struct InstanceData *id = INST_DATA( cl, o );
4325 dbug( kprintf( "DTM_OBTAINDRAWINFO\n" ); )
4327 return (IPTR)( ( id->Screen = (struct Screen *) GetTagData( PDTA_Screen, 0, ops->ops_AttrList ) ) ||
4328 ( id->DrawInfo = (struct DrawInfo *) GetTagData( GA_DrawInfo, 0, ops->ops_AttrList ) )
4332 /****************************************************************************/
4334 IPTR __regargs Sound_RELEASEDRAWINFO( Class *cl, Object *o, Msg msg )
4336 return (IPTR)0;
4339 /****************************************************************************/
4341 IPTR __regargs Sound_REMOVEDTOBJECT( Class *cl, Object *o, Msg msg )
4343 struct InstanceData *id = INST_DATA( cl, o );
4344 /* prevent other tasks (cursor- or playertask) from reading this */
4345 dbug( kprintf( "DTM_REMOVEDTOBJECT\n" ); )
4347 ObtainSemaphore( &id->Lock );
4348 id->Window = (struct Window *)NULL;
4349 id->Requester = NULL;
4350 ReleaseSemaphore( &id->Lock );
4352 if( id->ColorMap )
4354 ReleasePen( id->ColorMap, id->BackgroundPen );
4355 ReleasePen( id->ColorMap, id->WaveformPen );
4358 return (IPTR) DoSuperMethodA(cl, o, msg);