revert between 56095 -> 55830 in arch
[AROS.git] / workbench / classes / datatypes / sound / dispatch.c
blob1ca3263e5233ad505db0849da25fd5bae7ab235a
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,
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(&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, (IPTR) &superMethods );
1364 data = (IPTR) ( 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 %16lx\n", (IPTR)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 IBox gbox;
1900 LONG bgpen=id->BackgroundPen, wfpen=id->WaveformPen;
1901 UWORD *pens = gpr->gpr_GInfo->gi_DrInfo->dri_Pens;
1902 WORD x,y, w,h;
1904 gbox = GetAbsGadgetBox( &gpr->gpr_GInfo->gi_Domain, EXTG( o ), FALSE );
1905 x = gbox.Left; y = gbox.Top;
1906 w = gbox.Width; h = gbox.Height;
1908 if( id->ControlPanel )
1910 h -= ( id->TapeDeckHeight + 2 );
1913 if( ( x != SHRT_MAX && y != SHRT_MAX ) && ( w >=16 && h >= 8 ) )
1915 SetAPen( rp, ( bgpen == -1 ) ? pens[TEXTPEN] : bgpen );
1916 RectFill( rp, x,y, w+x-1, h+y-1 );
1918 x += 4; y += 2;
1919 w -= 8; h -= 4;
1921 SetAPen( rp, ( wfpen == -1 ) ? pens[HIGHLIGHTTEXTPEN] : wfpen );
1923 DrawWaveform( cb, rp, id, x, y, w, h );
1926 if( id->ControlPanel )
1928 /* SetAPen( rp, 4L );
1929 RectFill( rp, gbox.Left, gbox.Top+=(gbox.Height-id->TapeDeckHeight-3),
1930 gbox.Left+gbox.Width-1, gbox.Top+id->TapeDeckHeight+1 );*/
1932 if( gbox.Height >= ( id->TapeDeckHeight + 2 ) )
1934 if( gbox.Width >= 201)
1936 DoMethodA( (Object *)id->TapeDeckGadget, (Msg) gpr );
1938 if( gbox.Width >= 220 )
1940 DoMethodA( (Object *) id->VolumeSlider, (Msg) gpr );
1942 if( ! cb->cb_NoGTSlider )
1944 Object *img;
1946 if( ( img = NewObject( NULL, FRAMEICLASS,
1947 IA_Left, id->VolumeSlider->LeftEdge - 4,
1948 IA_Top, id->VolumeSlider->TopEdge - 2,
1949 IA_Width, id->VolumeSlider->Width + 8,
1950 IA_Height, id->TapeDeckHeight,
1951 IA_FrameType, FRAME_BUTTON,
1952 IA_EdgesOnly, TRUE,
1953 TAG_DONE ) ) )
1955 DrawImageState( rp, (struct Image *)img, 0,0, IDS_NORMAL, gpr->gpr_GInfo->gi_DrInfo );
1956 DisposeObject( img );
1964 if( G( o )->Flags & GFLG_DISABLED )
1966 ULONG patt = 0x11114444;
1968 SetAfPt(rp, (UWORD *)&patt, 1);
1969 SetAPen( rp, pens[ SHADOWPEN ] );
1970 RectFill( rp, gbox.Left, gbox.Top, gbox.Left+gbox.Width-1, gbox.Top+gbox.Height-1 );
1971 SetAfPt( rp, NULL, 0L );
1974 else if( gpr->gpr_Redraw == GREDRAW_UPDATE )
1978 return( TRUE );
1981 /****************************************************************************/
1983 IPTR __regargs Sound_DRAW( Class *cl, Object *o, struct dtDraw *dtd )
1985 struct InstanceData *id = INST_DATA( cl, o );
1986 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
1987 struct RastPort *rp = dtd->dtd_RPort;
1988 struct DrawInfo *dri;
1989 struct Screen *scr;
1990 struct ColorMap *cm = NULL;
1991 UWORD x = dtd->dtd_Left, y = dtd->dtd_Top, *pens,
1992 w = dtd->dtd_Width, h = dtd->dtd_Height;
1993 WORD bgpen = -1, wfpen = -1;
1994 BOOL freedri;
1996 dbug( kprintf( "DTM_DRAW\n" ); )
1998 if( ( scr = id->Screen ) )
2000 dri = GetScreenDrawInfo( scr );
2001 freedri = TRUE;
2003 else
2005 dri = id->DrawInfo;
2006 freedri = FALSE;
2009 if( dri )
2011 pens = dri->dri_Pens;
2013 if( scr )
2015 cm = scr->ViewPort.ColorMap;
2017 ObtainSemaphoreShared( &cb->cb_LibLock );
2018 bgpen = ObtainBestPenA( cm,
2019 cb->cb_BgCol[0], cb->cb_BgCol[1], cb->cb_BgCol[2], NULL );
2020 wfpen = ObtainBestPenA( cm,
2021 cb->cb_WfCol[0], cb->cb_WfCol[1], cb->cb_WfCol[2], NULL );
2022 ReleaseSemaphore( &cb->cb_LibLock );
2025 SetAPen( rp, ( bgpen == -1 ) ? pens[TEXTPEN] : bgpen );
2026 RectFill( rp, x,y, w+x-1, h+y-1 );
2028 x += 4; y += 2;
2029 w -= 8; h -= 4;
2031 SetAPen( rp, ( wfpen == -1 ) ? pens[HIGHLIGHTTEXTPEN] : wfpen );
2033 DrawWaveform( cb, rp, id, x, y, w, h );
2035 if( cm )
2037 ReleasePen( cm, bgpen );
2038 ReleasePen( cm, wfpen );
2041 if( freedri )
2043 FreeScreenDrawInfo( scr, dri );
2047 return( dri != NULL );
2050 /****************************************************************************/
2052 IPTR __regargs Sound_HITTEST( Class *cl, Object *o, struct gpHitTest *gpht )
2054 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2055 IPTR retval = GMR_GADGETHIT;
2056 WORD h = G(o)->Height;
2058 dbug( kprintf( "GM_HITTEST\n" ); )
2060 if( ! ( G( o )->Flags & GFLG_DISABLED ) )
2062 /* calculate absolute height */
2063 if( G(o)->Flags & GFLG_RELHEIGHT )
2065 h += gpht->gpht_GInfo->gi_Domain.Height;
2067 /* check if one of our members was hit */
2068 if( gpht->gpht_Mouse.Y > ( h - ( id->TapeDeckHeight + 3 ) ) )
2070 if( id->ControlPanel )
2072 struct IBox domain;
2074 domain = GetAbsGadgetBox( &gpht->gpht_GInfo->gi_Domain, EXTG( o ), FALSE );
2076 if( ! DoMemberHitTest( &domain, (Object *) id->TapeDeckGadget, gpht ) )
2078 if( ! DoMemberHitTest( &domain, (Object *) id->VolumeSlider, gpht ) )
2080 retval = 0L;
2085 else
2087 /* We were hit, change return code if it was GM_HELPTEST */
2088 if( gpht->MethodID == GM_HELPTEST )
2090 retval = GMR_HELPHIT;
2094 else
2096 retval = 0L;
2099 return retval;
2102 /****************************************************************************/
2104 IPTR __regargs Sound_HANDLEINPUT( Class *cl, Object *o, struct gpInput *gpi )
2106 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
2107 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2108 struct InputEvent *ie = gpi->gpi_IEvent;
2109 struct DTSpecialInfo *si = (struct DTSpecialInfo *)G( o )->SpecialInfo;
2110 struct IBox gbox = GetAbsGadgetBox( &gpi->gpi_GInfo->gi_Domain, EXTG( o ), FALSE );
2111 IPTR retval = GMR_MEACTIVE;
2112 WORD mx = gpi->gpi_Mouse.X, my = gpi->gpi_Mouse.Y;
2114 (void)cb;
2116 dbug( kprintf("GM_GOACTIVE / GM_HANDLEINPUT\n"); )
2117 /* no input processing during layout */
2118 if( si->si_Flags & DTSIF_LAYOUT )
2120 return GMR_NOREUSE;
2123 /* check if we're hit or one of our members */
2124 if( gpi->MethodID == GM_GOACTIVE )
2126 G( o )->Activation |= GACT_ACTIVEGADGET;
2127 G( o )->Flags |= GFLG_SELECTED;
2128 /* check if mousepointer is over one of our members */
2129 if( id->ControlPanel )
2131 if( my > ( gbox.Height - id->TapeDeckHeight - 3 ) )
2133 struct gpHitTest gpht = { GM_HITTEST, gpi->gpi_GInfo, {mx, my} };
2135 if( gbox.Width >= 201 && DoMemberHitTest( &gbox, (Object *) id->TapeDeckGadget, &gpht ) )
2137 id->ActiveMember = id->TapeDeckGadget;
2139 else if( gbox.Width >= 220 && DoMemberHitTest( &gbox, (Object *) id->VolumeSlider, &gpht ) )
2141 id->ActiveMember = id->VolumeSlider;
2143 /* nothing hit ? */
2144 if( ! id->ActiveMember )
2146 retval = GMR_NOREUSE;
2151 /* pass input to the active member ( if there's one ) */
2152 if( id->ActiveMember )
2154 struct IBox domain = gbox;
2156 gbox = GetAbsGadgetBox( &gpi->gpi_GInfo->gi_Domain, EXTG( id->ActiveMember ), FALSE );
2158 (gpi -> gpi_Mouse . X) -= ((gbox . Left) - (domain . Left));
2159 (gpi -> gpi_Mouse . Y) -= ((gbox . Top) - (domain . Top));
2161 if( ( retval = DoMethodA( (Object *) id->ActiveMember, (Msg) gpi ) ) & GMR_VERIFY )
2162 { /* tapedeck.gadget doesn't send OM_UPDATE :( */
2163 if( id->ActiveMember == id->TapeDeckGadget )
2165 if( ie->ie_Code == IECODE_LBUTTON )
2167 ULONG stm = 0L;
2169 dbug( kprintf( "TapeDeck ICSPECIAL_CODE: %04lx\n", *gpi->gpi_Termination ); )
2171 if( *gpi->gpi_Termination & 0x1000 )
2173 stm = STM_PAUSE;
2175 else
2177 switch( *gpi->gpi_Termination )
2179 case BUT_PLAY:
2180 stm = STM_PLAY;
2181 break;
2183 case BUT_STOP:
2184 stm = STM_STOP;
2185 break;
2189 if( stm )
2191 CoerceMethod( cl, o, DTM_TRIGGER, 0, stm, 0 );
2197 (gpi -> gpi_Mouse . X) += ((gbox . Left) - (domain . Left));
2198 (gpi -> gpi_Mouse . Y) += ((gbox . Top) - (domain . Top));
2200 /* we're hit */
2201 else if( retval == GMR_MEACTIVE )
2203 while( ie )
2205 if( ie->ie_Class == IECLASS_RAWMOUSE )
2207 /* test for mark mode */
2208 if( si->si_Flags & DTSIF_DRAGSELECT )
2210 struct RastPort *rp;
2211 WORD mx = gpi->gpi_Mouse.X, x, y, w, h;
2213 x = gbox.Left; y = gbox.Top + 2;
2214 w = gbox.Width - 8; h = gbox.Height - 4;
2216 if( id->ControlPanel )
2218 h -= ( id->TapeDeckHeight + 2 );
2221 if( mx > (w+3) )
2223 mx = w+3;
2225 else if( mx < 4 )
2227 mx = 4;
2230 if( id->MarkMode )
2232 if( id->MaxX != (x+mx) )
2234 if( ( rp = ObtainGIRPort( gpi->gpi_GInfo ) ) )
2236 UWORD minX, maxX;
2238 SetDrMd( rp, COMPLEMENT );
2240 minX = id->MinX;
2241 maxX = id->MaxX;
2243 if( minX > maxX )
2245 maxX = minX;
2246 minX = id->MaxX;
2248 //WaitTOF();
2249 RectFill( rp, minX, y, maxX, y+h-1 );
2251 minX = id->MinX;
2252 maxX =
2253 id->MaxX = x + mx;
2255 if( minX > maxX )
2257 maxX = minX;
2258 minX = id->MaxX;
2260 //WaitTOF();
2261 RectFill( rp, minX, y, maxX, y+h-1 );
2262 /* fixes a bug (?) of tapedeck.gadget */
2263 SetDrMd( rp, JAM1 );
2265 ReleaseGIRPort( rp );
2269 /* start mark mode */
2270 else if( ie->ie_Code == IECODE_LBUTTON )
2272 if( id->MinX != ~0 )
2274 DoMethod( o, DTM_CLEARSELECTED, (IPTR) gpi->gpi_GInfo );
2277 id->MarkMode = TRUE;
2279 id->MinX =
2280 id->MaxX = x + mx;
2283 /* not in mark mode - start or stop playing */
2284 else if( ie->ie_Code == IECODE_LBUTTON )
2286 struct timeval tv = gpi->gpi_IEvent->ie_TimeStamp;
2287 STATIC ULONG stm[] = { STM_PLAY, STM_STOP };
2289 CoerceMethod( cl, o, DTM_TRIGGER, 0, stm[ DoubleClick( id->LastClick.tv_secs, id->LastClick.tv_micro, tv.tv_secs, tv.tv_micro ) ], 0L );
2291 id->LastClick = tv;
2294 if( ie->ie_Code == SELECTUP )
2296 retval = GMR_NOREUSE;
2297 break;
2301 ie = ie->ie_NextEvent;
2305 return( retval );
2308 /****************************************************************************/
2310 IPTR __regargs Sound_GOINACTIVE( Class *cl, Object *o, struct gpGoInactive *gpgi )
2312 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2313 struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
2315 (void)cb;
2317 DoSuperMethodA( cl, o, (Msg) gpgi );
2319 dbug( kprintf("GOINACTIVE\n"); )
2321 if( id->ActiveMember )
2323 DoMethodA( (Object *) id->ActiveMember, (Msg) gpgi );
2324 id->ActiveMember = NULL;
2327 id->MarkMode = FALSE;
2329 G( o )->Activation &= ~GACT_ACTIVEGADGET;
2330 G( o )->Flags &= ~GFLG_SELECTED;
2332 return 0L;
2335 /****************************************************************************/
2337 IPTR __regargs Sound_TRIGGER( Class *cl, Object *o, struct dtTrigger *dtt )
2339 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
2340 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2341 APTR data = NULL;
2342 ULONG cmd = ~0L;
2344 (void)cb;
2346 dbug( kprintf("DTM_TRIGGER\n"); )
2348 switch( dtt->dtt_Function )
2350 case STM_PLAY:
2351 dbug( kprintf( "STM_PLAY\n" ); )
2352 cmd = COMMAND_PLAY;
2353 data = (APTR) id;
2354 break;
2356 case STM_STOP:
2357 dbug( kprintf( "STM_STOP\n" ); )
2358 cmd = COMMAND_STOP;
2359 break;
2361 case STM_PAUSE:
2362 dbug( kprintf( "STM_PAUSE\n" ); )
2363 cmd = COMMAND_PAUSE;
2364 break;
2367 if( cmd != ~0 )
2369 SendObjectMsg( id, cmd, data );
2372 return 0L;
2375 /****************************************************************************/
2376 // "stolen" from embeddt
2377 IPTR __regargs DoMemberHitTest( struct IBox *domain, Object *member, struct gpHitTest *gpht )
2379 struct GadgetInfo *gi = gpht -> gpht_GInfo;
2380 struct IBox gbox;
2381 IPTR retval = 0L;
2383 gbox = GetAbsGadgetBox( &gi->gi_Domain, EXTG( member ), (BOOL) ( gpht -> MethodID == GM_HELPTEST ) );
2385 (gpht->gpht_Mouse.X) -= ((gbox.Left) - (domain->Left));
2386 (gpht->gpht_Mouse.Y) -= ((gbox.Top) - (domain->Top));
2388 /* Mouse coordinates must be inside members's select box */
2389 if( ((gpht->gpht_Mouse . X) >= 0) &&
2390 ((gpht->gpht_Mouse . Y) >= 0) &&
2391 ((gpht->gpht_Mouse . X) <= (gbox.Width)) &&
2392 ((gpht->gpht_Mouse . Y) <= (gbox.Height)) )
2394 retval = DoMethodA( member, (Msg)gpht );
2397 (gpht->gpht_Mouse.X) += ((gbox.Left) - (domain->Left));
2398 (gpht->gpht_Mouse.Y) += ((gbox.Top) - (domain->Top));
2400 return( retval );
2403 /****************************************************************************/
2405 struct IBox __regargs GetAbsGadgetBox( struct IBox *domain, struct ExtGadget *g, BOOL useBounds )
2407 struct IBox retbox = { 0, 0, 0, 0 };
2409 if( domain && g )
2411 if( ((g->MoreFlags) & GMORE_BOUNDS) && useBounds )
2413 retbox = *((struct IBox *)(&(g->BoundsLeftEdge)));
2415 else
2417 retbox = *(GADGET_BOX( g ));
2420 if( (g->Flags) & GFLG_RELBOTTOM )
2422 (retbox.Top) += ((domain->Top) + (domain->Height));
2425 if( (g->Flags) & GFLG_RELRIGHT )
2427 (retbox.Left) += ((domain->Left) + (domain->Width));
2430 if( (g->Flags) & GFLG_RELWIDTH )
2432 (retbox.Width) += (domain->Width);
2435 if( (g->Flags) & GFLG_RELHEIGHT )
2437 (retbox.Height) += (domain->Height);
2441 return( retbox );
2444 /****************************************************************************/
2446 void __regargs makeqtab( BYTE *qtab )
2448 LONG i;
2450 for( i=0; i < 512; i++ )
2452 qtab[i] = 0;
2455 for ( i = 1; i < 16; i++ )
2457 LONG j = 256 + fibtab[i],
2458 k = 256 + fibtab[i-1];
2460 if( fibtab[i] < 0 )
2462 while( j > k )
2464 qtab[j--] = i;
2467 else
2469 while( j < 512 )
2471 qtab[j++] = i;
2477 /****************************************************************************/
2479 LONG __regargs WriteChunk( struct ClassBase *cb, struct IFFHandle *iff, ULONG type, ULONG id, APTR data, ULONG size )
2481 LONG err;
2483 if( ! ( err = PushChunk( iff, type, id, size ) ) )
2485 if( ( err = WriteChunkBytes( iff, data, size ) ) == size )
2487 err = PopChunk( iff );
2491 return err;
2494 /****************************************************************************/
2496 LONG __regargs WriteAIFF( struct ClassBase *cb, Object *o, struct IFFHandle *iff, struct InstanceData *id )
2498 LONG err;
2500 if( ! ( err = PushChunk( iff, ID_AIFF, ID_FORM, IFFSIZE_UNKNOWN ) ) )
2502 CommonChunk common;
2503 UBYTE sampleType = id->SampleType;
2504 ULONG sampleLength = id->SampleLength;
2505 BYTE *sample = id->Sample;
2507 if( id->StartSample != ~0 )
2509 sample = &sample[ UMult32( id->StartSample, bytesPerPoint[ sampleType ] ) ];
2510 sampleLength = id->EndSample - id->StartSample;
2513 common.numChannels = ( sampleType & 1 ) + 1;
2514 common.numSampleFrames = sampleLength;
2515 common.sampleSize = ( sampleType >= SDTST_M16S ) ? 16 : 8;
2516 ulong2extended( id->Frequency, &common.sampleRate );
2518 if( ! ( err = WriteChunk( cb, iff, ID_AIFF, ID_COMM, &common, sizeof( common ) ) ) )
2520 SampledSoundHeader ssnd = { 0L, 0L };
2522 if( ! ( err = PushChunk( iff, ID_AIFF, ID_SSND, IFFSIZE_UNKNOWN ) ) )
2524 if( ( err = WriteChunkBytes( iff, &ssnd, sizeof( ssnd ) ) ) == sizeof( ssnd ) )
2526 ULONG bytes = UMult32( sampleLength, bytesPerPoint[ sampleType ] );
2528 if( ( err = WriteChunkBytes( iff, sample, bytes ) ) == bytes )
2530 err = PopChunk( iff );
2536 if( ! err )
2538 err = PopChunk( iff );
2542 return( err );
2545 /****************************************************************************/
2547 LONG __regargs WriteSVX( struct ClassBase *cb, Object *o, struct IFFHandle *iff, struct InstanceData *id )
2549 UBYTE sampletype = id->SampleType, bps = ( sampletype >= SDTST_M16S ? 2 : 1 );
2550 BOOL stereo = IsStereo( id->SampleType );
2551 LONG err, type = ( sampletype >= SDTST_M16S ? ID_16SV : ID_8SVX );
2552 ULONG sampleLength = id->SampleLength;
2553 BYTE *sample = id->Sample;
2554 struct VoiceHeader vhdr;
2556 CopyMem( &id->VoiceHeader, &vhdr, sizeof( vhdr ) );
2557 vhdr.vh_Compression = ( ( id->VoiceHeader.vh_Compression == CMP_FIBDELTA ) || ( cb->cb_Compress ) ) && ( sampletype <= SDTST_S8S );
2559 if( id->StartSample != ~0 )
2561 sample = &sample[ UMult( id->StartSample, bytesPerPoint[ sampletype ] ) ];
2562 sampleLength = id->EndSample - id->StartSample;
2563 vhdr.vh_OneShotHiSamples = sampleLength;
2564 vhdr.vh_RepeatHiSamples = 0L;
2567 if( ! ( err = PushChunk( iff, type, ID_FORM, IFFSIZE_UNKNOWN ) ) )
2569 if( ! ( err = WriteChunk( cb, iff, type, ID_VHDR, &vhdr, sizeof( vhdr ) ) ) )
2571 struct ObjectData
2573 ULONG attr;
2574 ULONG id;
2575 STRPTR data;
2576 } ObjData[] = {
2577 {DTA_ObjName, ID_NAME, NULL},
2578 {DTA_ObjAnnotation, ID_ANNO, NULL},
2579 {DTA_ObjAuthor, ID_AUTH, NULL},
2580 {DTA_ObjCopyright, ID_Copyright, NULL},
2581 {DTA_ObjVersion, ID_FVER, NULL},
2584 LONG i;
2586 for( i = 0; ObjData[i].attr; i++ )
2588 struct ObjectData *od = &ObjData[i];
2590 if( GetDTAttrs( o, od->attr, (IPTR) &od->data, TAG_DONE ) && od->data )
2592 if( ( err = WriteChunk( cb, iff, type, od->id, od->data, StrLen( od->data ) ) ) )
2594 break;
2599 if( ! err )
2601 if( stereo )
2603 ULONG chan = 6L;
2604 err = WriteChunk( cb, iff, type, ID_CHAN, &chan, sizeof( ULONG ) );
2606 else
2608 ULONG pan = 0x10000 - id->Panning;
2609 err = WriteChunk( cb, iff, type, ID_PAN, &pan, sizeof( ULONG ) );
2613 if( ! err )
2615 if( vhdr.vh_Compression == CMP_FIBDELTA )
2617 BYTE *qtab, *buf;
2618 LONG buffersize;
2620 buffersize = sampleLength;
2622 while( ! ( buf = AllocVec( buffersize + 512L, MEMF_PUBLIC ) ) )
2624 if( ( buffersize /= 2 ) < 1024L )
2626 break;
2630 if( buf )
2632 if( ! ( err = PushChunk( iff, type, ID_BODY, IFFSIZE_UNKNOWN ) ) )
2634 LONG i;
2636 qtab = &buf[buffersize];
2637 makeqtab( qtab );
2639 for( i = 0; i < (stereo?2:1) && !err; i++ )
2641 LONG length = sampleLength, samples = 0L;
2642 BYTE c0 = 0, *src = &sample[i], add = stereo?2:1;
2643 UBYTE o = 0, x = 1;
2645 if( length & 1 )
2647 c0 = *src++;
2648 length--;
2651 buf[ 0 ] = 0;
2652 buf[ 1 ] = c0;
2653 samples += 2;
2655 while( length-- )
2657 UBYTE n;
2659 c0 += fibtab[ n = qtab[256+(*src-c0)] ];
2661 src+=add;
2663 if( x^=1 )
2665 buf[samples++] = o | n;
2667 else
2669 o = n << 4;
2672 if( samples == buffersize || length == 0L )
2674 if( ( err = WriteChunkBytes( iff, buf, samples ) ) != samples )
2676 break;
2678 err = samples = 0L;
2683 if( ! err )
2685 err = PopChunk( iff );
2689 FreeVec( buf );
2691 else
2693 err = ERROR_NO_FREE_STORE;
2697 ** write uncompressed svx file
2699 else
2702 ** create a stereo BODY
2704 if( stereo )
2706 if( ! ( err = PushChunk( iff, type, ID_BODY, IFFSIZE_UNKNOWN ) ) )
2708 BYTE *buf;
2709 LONG bufsize = sampleLength;
2711 while( ! ( buf = AllocVec( UMult( bufsize, bps ), MEMF_PUBLIC ) ) )
2713 if( ( bufsize /= 2 ) < 1024L )
2715 break;
2719 if( buf )
2721 LONG i;
2723 for( i = 0; i < 2 && ! err; i++, sample+=bps )
2725 LONG samples = bufsize, length = sampleLength;
2726 BYTE *src = sample;
2728 while( length )
2730 ULONG bytes = UMult( samples, bps );
2732 if( sampletype == SDTST_S16S )
2734 WORD *dst = (WORD *)buf,
2735 *src_p = (WORD *)src;
2736 LONG c;
2738 for( c = samples; c; c--, src_p+=2 )
2740 *dst++ = *src_p;
2743 src = (BYTE *) src_p;
2745 else
2747 BYTE *dst = buf;
2748 LONG c;
2750 for( c = samples; c; c--, src+=2 )
2752 *dst++ = *src;
2756 if( ( err = WriteChunkBytes( iff, buf, bytes ) ) != bytes )
2758 break;
2761 if( (length-=samples) < samples )
2763 samples = length;
2766 err = 0L;
2771 else
2773 err = ERROR_NO_FREE_STORE;
2776 if( ! err )
2778 err = PopChunk( iff );
2783 ** write uncompressed mono sample
2785 else
2787 err = WriteChunk( cb, iff, type, ID_BODY, sample, UMult( sampleLength, bps ) );
2793 if( ! err )
2795 err = PopChunk( iff );
2799 return( err );
2802 /****************************************************************************/
2804 IPTR __regargs Sound_WRITE( Class *cl, Object *o, struct dtWrite *dtw )
2806 struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
2807 struct InstanceData *id = (struct InstanceData *) INST_DATA( cl, o );
2808 struct IFFHandle *iff;
2809 struct SignalSemaphore *lock = &((struct DTSpecialInfo *)G( o )->SpecialInfo)->si_Lock;
2810 LONG err = 0L;
2812 dbug( kprintf( "DTM_WRITE / DTM_COPY\n" ); )
2814 ObtainSemaphoreShared( &cb->cb_LibLock );
2816 if( id->Sample )
2818 ObtainSemaphoreShared( lock );
2820 if( ( iff = AllocIFF() ) )
2822 if( dtw->MethodID == DTM_WRITE )
2824 dbug( kprintf( "DTWM_RAW\n" ); )
2826 if( ( iff->iff_Stream = (IPTR)dtw->dtw_FileHandle ) )
2828 InitIFFasDOS( iff );
2830 else
2832 dbug( kprintf( "NULL filehandle\n"); )
2833 err = ERROR_INVALID_LOCK;
2836 else
2838 dbug( kprintf( "DTM_COPY\n" ); )
2840 if( ( iff->iff_Stream = (IPTR) OpenClipboard( PRIMARY_CLIP ) ) )
2842 InitIFFasClip( iff );
2844 else
2846 dbug( kprintf( "Cant open clipboard\n" ); )
2847 err = ERROR_OBJECT_IN_USE;
2851 if( ! err )
2853 if( ( err = OpenIFF( iff, IFFF_WRITE ) ) )
2855 err = ifferr2doserr[-err-1];
2856 dbug( kprintf( "OpenIFF() failed\n" ); )
2860 else
2862 err = ERROR_NO_FREE_STORE;
2863 dbug( kprintf( "AllocIFF failed\n" ); )
2866 if( ! err )
2868 dbug( kprintf( "Everything fine so far ...\n" ); )
2870 if( id->SampleType >= SDTST_M16S && cb->cb_AIFF )
2872 err = WriteAIFF( cb, o, iff, id );
2874 else
2876 err = WriteSVX( cb, o, iff, id );
2879 if( err < 0L )
2881 err = ifferr2doserr[-err-1];
2884 else
2886 dbug( kprintf( "Something failed\n" ); )
2889 dbug( kprintf( "closing iff stream\n" ); )
2891 CloseIFF( iff );
2893 if( dtw->MethodID == DTM_COPY )
2895 CloseClipboard( (struct ClipboardHandle *)iff->iff_Stream );
2898 FreeIFF( iff );
2900 ReleaseSemaphore( lock );
2902 else
2904 err = ERROR_REQUIRED_ARG_MISSING;
2907 ReleaseSemaphore( &cb->cb_LibLock );
2909 SetIoErr( err );
2910 return( err ? FALSE : TRUE );
2913 /****************************************************************************/
2916 ** test if dblscan screenmode
2917 ** taken from the ahi paula driver by Martin Blom
2919 #if 0
2920 BOOL Is31Khz( struct ClassBase *cb )
2922 BOOL ret = FALSE;
2924 /* check for ocs */
2925 #ifdef __MAXON__
2926 extern struct Library *GfxBase, *IntuitionBase;
2928 if( ((struct GfxBase *)GfxBase)->ChipRevBits0 & ( GFXF_HR_DENISE|GFXF_AA_LISA ) )
2929 #else
2930 #undef GfxBase
2931 if( ((struct GfxBase *)cb->cb_GfxBase)->ChipRevBits0 & ( GFXF_HR_DENISE|GFXF_AA_LISA ) )
2932 #define GfxBase cb->cb_GfxBase
2933 #endif
2935 ULONG lock, modeid;
2937 lock = LockIBase( 0L );
2938 #ifdef __MAXON__
2939 modeid = GetVPModeID( & ((struct IntuitionBase *)IntuitionBase)->FirstScreen->ViewPort );
2940 #else
2941 #undef IntuitionBase
2942 modeid = GetVPModeID( & ((struct IntuitionBase *)cb->cb_IntuitionBase)->FirstScreen->ViewPort );
2943 #define IntuitionBase cb->cb_IntuitionBase
2944 #endif
2945 UnlockIBase( lock );
2947 /* gfxboard */
2948 if( modeid & 0x40000000 )
2950 Forbid();
2951 if( FindTask( "Picasso96" ) )
2953 UBYTE buf[16];
2955 Permit();
2957 if( GetVar( "Picasso96/AmigaVideo", buf, sizeof( buf ), GVF_GLOBAL_ONLY ) )
2959 if( ! Strnicmp( buf, "31Khz" , 5L ) )
2961 ret = TRUE;
2965 else
2967 #ifdef __MAXON__
2968 struct copinit *ci = ((struct GfxBase *)GfxBase)->copinit;
2969 #else
2970 #undef GfxBase
2971 struct copinit *ci = ((struct GfxBase *)cb->cb_GfxBase)->copinit;
2972 #define GfxBase cb->cb_GfxBase
2973 #endif
2974 Permit();
2976 if( ( ci->fm0[ 0 ] != 0x01fc ) || ( ci->fm0[ 1 ] & 0xc000 ) )
2978 ret = TRUE;
2982 /* native screen */
2983 else
2985 struct MonitorInfo moni;
2987 if( GetDisplayInfoData( NULL, (UBYTE *) &moni, sizeof( moni ), DTAG_MNTR, modeid ) )
2989 if( moni.TotalColorClocks * moni.TotalRows / ( 2 * ( moni.TotalRows - moni.MinRow + 1 ) ) <= 64 )
2991 ret = TRUE;
2997 return ret;
2999 #endif
3000 /****************************************************************************/
3002 void __regargs CalcPanVol( UWORD overall, ULONG pan, UWORD *leftvol, UWORD *rightvol )
3004 pan = ( pan << 6 ) >> 16;
3005 *rightvol = pan ? overall / ( 64 / pan ) : 0;
3006 *leftvol = overall - *rightvol;
3009 /****************************************************************************/
3011 void __regargs RemoveRequest( struct IORequest *ior )
3013 #if !defined(__MAXON__) && !defined(__AROS__)
3014 #undef SysBase
3015 struct Library *SysBase = (*(struct Library **)4L);
3016 #endif
3017 struct Node *ln, *succ;
3019 Disable();
3020 for( ln = ior->io_Message.mn_ReplyPort->mp_MsgList.lh_Head;
3021 (succ = ln->ln_Succ); ln = succ )
3023 if( ln == &ior->io_Message.mn_Node )
3025 Remove( ln );
3026 SetSignal( 0L, 1L << ior->io_Message.mn_ReplyPort->mp_SigBit );
3027 break;
3030 Enable();
3031 #if !defined(__MAXON__) && !defined(__AROS__)
3032 #undef SysBase
3033 #define SysBase cb->cb_SysBase
3034 #endif
3037 /****************************************************************************/
3039 #define LEFT_CHANNEL_0 1
3040 #define RIGHT_CHANNEL_1 2
3041 #define RIGHT_CHANNEL_2 4
3042 #define LEFT_CHANNEL_3 8
3043 #define MAX_SAMPLE 131072
3044 #define MAX_SAMPLE_RATE 28867
3045 #define LEFT_MASK (LEFT_CHANNEL_0|LEFT_CHANNEL_3)
3046 #define RIGHT_MASK (RIGHT_CHANNEL_1|RIGHT_CHANNEL_2)
3048 enum {
3049 AUDIO_CONTROL,
3050 AUDIO_LEFT,
3051 AUDIO_LEFT2,
3052 AUDIO_RIGHT,
3053 AUDIO_RIGHT2,
3054 NUM_REQUESTS
3057 /****************************************************************************/
3059 void __regargs SetTDMode( struct ClassBase *cb, struct InstanceData *id, ULONG mode )
3061 if( id->ControlPanel )
3063 IPTR oldmode = mode;
3065 ObtainSemaphoreShared( &id->Lock );
3067 /* avoid deadlocks */
3068 GetAttr( TDECK_Mode, (Object *)id->TapeDeckGadget, &oldmode );
3069 if( oldmode != mode )
3071 SetGadgetAttrs( id->TapeDeckGadget, id->Window, id->Requester,
3072 TDECK_Mode, mode, TAG_DONE );
3075 ReleaseSemaphore( &id->Lock );
3079 /****************************************************************************/
3081 void PlayerProc( void )
3083 #if !defined(__MAXON__) && !defined(__AROS__)
3084 #undef SysBase
3085 struct Library *SysBase = *(struct Library **)4L;
3086 #endif
3087 struct Process *pr = (struct Process *) FindTask( NULL );
3088 struct MsgPort *mp, *mpaudio = NULL;
3089 struct IOAudio *ioaudio[NUM_REQUESTS] = { };
3090 struct ClassBase *cb = NULL;
3091 struct InstanceData *id = NULL;
3092 LONG numChAllocated = 0, samples = 0, buffersize = 0, length = 0, cycles = 0,
3093 loops = 0, audiompmsk = 0, mpmsk;
3094 BOOL releaseAudio = FALSE, restart = 0, paused = FALSE;
3095 BYTE *sample = NULL, *buffer[4] = {};
3097 mp = &pr->pr_MsgPort;
3098 mpmsk = 1L << mp->mp_SigBit;
3100 dbug( kprintf("child process launched\n"); )
3102 for( ;; )
3104 struct ObjectMsg *msg;
3105 LONG rcv;
3107 rcv = Wait( mpmsk | audiompmsk );
3109 if( rcv & mpmsk )
3111 while( ( msg = (struct ObjectMsg *) GetMsg( mp ) ) )
3113 switch( msg->Command )
3115 case COMMAND_NEXT_BUFFER:
3116 if( releaseAudio )
3118 ObtainSemaphoreShared( &id->Lock );
3119 sample = id->Sample;
3120 length = id->SampleLength;
3121 samples = ( length > buffersize ) ? buffersize : length;
3122 rcv = audiompmsk;
3123 ReleaseSemaphore( &id->Lock );
3125 break;
3127 case COMMAND_INIT:
3128 dbug( kprintf( "child/COMMAND_INIT\n"); )
3130 id = (struct InstanceData *) msg->Data;
3131 cb = id->ClassBase;
3133 if( ! ( msg->Data = mp = CreateMsgPort() ) )
3135 ReplyMsg( &msg->Message );
3136 return;
3139 mpmsk = 1L << mp->mp_SigBit;
3140 break;
3142 case COMMAND_EXIT:
3143 case COMMAND_STOP:
3144 dbug( kprintf( "child/COMMAND_EXIT or STOP\n"); )
3146 if( releaseAudio )
3148 LONG i;
3150 SetTDMode( cb, id, BUT_STOP );
3152 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
3154 struct IORequest *ioa = (struct IORequest *) ioaudio[ i ];
3156 if( CheckIO( ioa ) )
3158 RemoveRequest( ioa );
3160 else
3162 AbortIO( ioa );
3163 WaitIO( ioa );
3167 CloseDevice( (struct IORequest *) ioaudio[ AUDIO_CONTROL ] );
3168 DeleteMsgPort( mpaudio );
3169 audiompmsk = 0L;
3170 FreeVec( ioaudio[ AUDIO_CONTROL ] );
3171 FreeVec( buffer[0] ); buffer[0] = NULL;
3172 releaseAudio = FALSE;
3175 if( msg->Command == COMMAND_EXIT )
3177 Forbid();
3178 ReplyMsg( &msg->Message );
3179 DeleteMsgPort( mp );
3180 return;
3182 break;
3184 case COMMAND_PERVOL:
3186 dbug( kprintf( "child/COMMAND_PERVOL\n"); )
3188 if( releaseAudio )
3190 struct IOAudio *ioa = ioaudio[ AUDIO_CONTROL ];
3192 ObtainSemaphoreShared( &id->Lock );
3194 if( numChAllocated == 1L || IsStereo( id->SampleType ) )
3196 ioa->ioa_Period = Freq2Period( id->Frequency );
3197 ioa->ioa_Volume = id->Volume;
3198 ioa->ioa_Request.io_Flags = 0;
3199 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
3200 DoIO( &ioa->ioa_Request );
3202 Forbid();
3203 ioaudio[ AUDIO_LEFT ]->ioa_Volume =
3204 ioaudio[ AUDIO_LEFT2 ]->ioa_Volume =
3205 ioaudio[ AUDIO_RIGHT ]->ioa_Volume =
3206 ioaudio[ AUDIO_RIGHT2 ]->ioa_Volume = id->Volume;
3207 Permit();
3209 else
3211 UWORD leftvol, rightvol;
3212 ULONG oldmask = (ULONG)(IPTR) ioa->ioa_Request.io_Unit;
3214 CalcPanVol( id->Volume, id->Panning, &leftvol, &rightvol );
3216 ioa->ioa_Request.io_Command = CMD_STOP;
3217 DoIO( &ioa->ioa_Request );*/
3219 ioa->ioa_Request.io_Unit = (struct Unit *) (IPTR) ( oldmask & LEFT_MASK );
3220 ioa->ioa_Period = Freq2Period( id->Frequency );
3221 ioa->ioa_Volume = leftvol;
3222 ioa->ioa_Request.io_Flags = 0;
3223 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
3224 DoIO( &ioa->ioa_Request );
3226 ioa->ioa_Request.io_Unit = (struct Unit *) (IPTR) ( oldmask & RIGHT_MASK );
3227 ioa->ioa_Period = Freq2Period( id->Frequency );
3228 ioa->ioa_Volume = rightvol;
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 *) (IPTR) oldmask;
3235 Forbid();
3236 ioaudio[ AUDIO_LEFT ]->ioa_Volume =
3237 ioaudio[ AUDIO_LEFT2 ]->ioa_Volume = leftvol;
3238 ioaudio[ AUDIO_RIGHT ]->ioa_Volume =
3239 ioaudio[ AUDIO_RIGHT2 ]->ioa_Volume = rightvol;
3240 Permit();
3243 ioa->ioa_Request.io_Command = CMD_START;
3244 DoIO( &ioa->ioa_Request );*/
3247 Forbid();
3248 ioaudio[ AUDIO_LEFT ]->ioa_Period =
3249 ioaudio[ AUDIO_LEFT2 ]->ioa_Period =
3250 ioaudio[ AUDIO_RIGHT ]->ioa_Period =
3251 ioaudio[ AUDIO_RIGHT2 ]->ioa_Period = Freq2Period( id->Frequency );
3252 Permit();
3254 ReleaseSemaphore( &id->Lock );
3257 break;
3259 case COMMAND_PAUSE:
3261 dbug( kprintf( "child/COMMAND_PAUSE\n"); )
3263 if( releaseAudio )
3265 if( ! paused )
3267 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_STOP;
3268 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
3269 paused = TRUE;
3273 break;
3275 case COMMAND_PLAY:
3277 dbug( kprintf( "child/COMMAND_PLAY\n"); )
3279 ObtainSemaphoreShared( &id->Lock );
3281 if( releaseAudio )
3283 if( paused )
3285 rcv = audiompmsk;
3286 restart = TRUE;
3287 paused = FALSE;
3289 else
3291 LONG i;
3293 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
3295 struct IORequest *ioa = &ioaudio[ i ]->ioa_Request;
3297 if( CheckIO( ioa ) )
3299 RemoveRequest( ioa );
3301 else
3303 AbortIO( ioa );
3304 WaitIO( ioa );
3308 sample = id->Sample;
3309 length = id->SampleLength;
3310 samples = buffersize;
3311 if( length <= buffersize )
3313 loops = 1L;
3314 cycles = id->Cycles;
3316 else
3318 loops = id->Cycles;
3319 cycles = 1L;
3323 else
3325 UBYTE ChMap[] = {
3326 LEFT_CHANNEL_0 | RIGHT_CHANNEL_1,
3327 LEFT_CHANNEL_3 | RIGHT_CHANNEL_2,
3328 LEFT_CHANNEL_0, LEFT_CHANNEL_3,
3329 RIGHT_CHANNEL_1, RIGHT_CHANNEL_2
3331 struct IOAudio *ioa;
3332 LONG i;
3334 if( ! id->Sample || ! id->SampleLength )
3336 break;
3339 dbug( kprintf( "child/allocating requests\n" ); )
3341 /*- allocate requests and msgport -*/
3342 if( ! ( ioa = AllocVec( sizeof( *ioa ) * NUM_REQUESTS, MEMF_PUBLIC|MEMF_CLEAR ) ) ||
3343 ! ( mpaudio = CreateMsgPort() ) )
3345 FreeVec( ioa );
3346 SetTDMode( cb, id, BUT_STOP );
3347 break;
3350 for( i = 0; i < NUM_REQUESTS; i++ )
3352 ioaudio[i] = ioa++;
3355 audiompmsk = 1L << mpaudio->mp_SigBit;
3357 /*- Open audio.device and intialize requests -*/
3358 ioa = ioaudio[ AUDIO_CONTROL ];
3359 ioa->ioa_Request.io_Message.mn_ReplyPort = mpaudio;
3360 ioa->ioa_Request.io_Message.mn_Length = sizeof( *ioa );
3362 ioa->ioa_Data = ChMap;
3363 ioa->ioa_Length = sizeof( ChMap );
3365 if( ! OpenDevice( "audio.device", 0L, (struct IORequest *) ioa, 0L ) )
3367 /*- make CheckIO() work -*/
3368 ioa->ioa_Request.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
3370 for( i = 1; i < NUM_REQUESTS; i++ )
3372 CopyMem( ioa, ioaudio[i], sizeof( *ioa ) );
3375 for( i = 0; i < sizeof( ChMap ); i++ )
3377 if( (LONG) (IPTR) ioa->ioa_Request.io_Unit == (ULONG) ChMap[i] )
3379 break;
3383 if( i < 2 )
3385 dbug( kprintf( "child/got two stereo channels\n" ); )
3386 numChAllocated = 2L;
3387 /*- stop device in order to sync stereo channels -*/
3388 ioa->ioa_Request.io_Command = CMD_STOP;
3389 DoIO( &ioa->ioa_Request );
3390 restart = TRUE;
3392 else
3394 dbug( kprintf( "child/got only one channel\n" ); )
3395 numChAllocated = 1L;
3396 restart = FALSE;
3399 ioaudio[ AUDIO_LEFT ]->ioa_Request.io_Unit =
3400 ioaudio[ AUDIO_LEFT2 ]->ioa_Request.io_Unit = (struct Unit *) ( (IPTR)ioa->ioa_Request.io_Unit & LEFT_MASK );
3401 ioaudio[ AUDIO_RIGHT ]->ioa_Request.io_Unit =
3402 ioaudio[ AUDIO_RIGHT2 ]->ioa_Request.io_Unit = (struct Unit *) ( (IPTR)ioa->ioa_Request.io_Unit & RIGHT_MASK );
3404 sample = id->Sample;
3405 length = id->SampleLength;
3407 if( ( id->SampleType == SDTST_M8S ) && ( TypeOfMem( sample ) & MEMF_CHIP ) )
3409 buffersize = samples = ( length > MAX_SAMPLE ) ? MAX_SAMPLE : length;
3410 dbug( kprintf( "child/chip sample\n" ); )
3412 /*- allocate buffers -*/
3413 else
3415 ObtainSemaphoreShared( &cb->cb_LibLock ); /* determine buffersize, don't go below 1k (heavy system load) */
3416 buffersize = ( length > cb->cb_BufferSize ) ? cb->cb_BufferSize : ( ((length+1)/2) < 1024L ? length : (length+1)/2 );
3417 ReleaseSemaphore( &cb->cb_LibLock );
3419 while( ! ( buffer[0] = AllocVec( buffersize << numChAllocated, MEMF_CHIP ) ) )
3421 dbug( kprintf( "child/failed to allocate %ld bytes of buffer\n", buffersize ); )
3422 if( (buffersize /= 2) < 1024L )
3424 break;
3428 samples = buffersize;
3430 dbug( kprintf( "child/Buffer at %08lx, size %ld, num %ld\n", buffer[0], buffersize, numChAllocated*2 ); )
3432 if( buffer[0] == NULL )
3434 CloseDevice( (struct IORequest *) ioa );
3435 DeleteMsgPort( mpaudio );
3436 audiompmsk = 0L;
3437 FreeVec( ioa );
3438 SetTDMode( cb, id, BUT_STOP );
3439 break;
3442 for( i = 1; i < 4; i++ )
3444 buffer[ i ] = buffer[ i-1 ] + buffersize;
3448 if( buffersize <= length )
3450 cycles = id->Cycles;
3451 loops = 1L;
3453 else
3455 cycles = 1L;
3456 loops = id->Cycles;
3459 dbug( kprintf( "child/Sample: %08lx, Length: %ld, Cycles: %ld, Loops: %ld, Freq: %ld\n", sample, length, cycles, loops, id->Frequency ); )
3461 releaseAudio = TRUE;
3462 rcv = audiompmsk;
3463 SetTDMode( cb, id, BUT_PLAY );
3465 else
3467 dbug( kprintf("child/can't open audio.device\n"); )
3468 DeleteMsgPort( mpaudio );
3469 audiompmsk = 0L;
3470 FreeVec( ioa );
3471 SetTDMode( cb, id, BUT_STOP );
3475 ReleaseSemaphore( &id->Lock );
3477 break;
3478 } // switch
3480 if( msg->Message.mn_ReplyPort )
3482 ReplyMsg( &msg->Message );
3484 else // NT_FREEMSG
3486 FreeVec( msg );
3488 } // while
3489 } // if
3491 if( rcv & audiompmsk )
3493 ObtainSemaphoreShared( &id->Lock );
3495 if( length == 0L )
3497 LONG i;
3498 BOOL Done = TRUE;
3500 dbug( kprintf( "child/reachend end of sample\n" ); )
3502 /*- wait for any outstanding request -*/
3503 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
3505 struct IORequest *ioa = &ioaudio[i]->ioa_Request;
3507 if( ! CheckIO( ioa ) )
3509 /* don't block doing WaitIO() */
3510 Done = FALSE;
3512 else
3514 RemoveRequest( ioa );
3518 if( ! Done || id->Continuous )
3520 ReleaseSemaphore( &id->Lock );
3521 continue;
3524 if( id->Repeat || ( --loops > 0L ) )
3526 dbug( kprintf( "child/%ld loops to go\n", loops ); )
3528 sample = id->Sample;
3529 length = id->SampleLength;
3530 samples = buffersize;
3531 /*- stop device in order to sync stereo channels -*/
3532 if( numChAllocated == 2L )
3534 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_STOP;
3535 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
3536 restart = TRUE;
3538 else
3540 restart = FALSE;
3543 else
3545 dbug( kprintf("child/cleanup\n"); )
3547 /*- cleanup -*/
3548 CloseDevice( &ioaudio[AUDIO_CONTROL]->ioa_Request );
3549 FreeVec( buffer[0] ); buffer[0] = NULL;
3550 FreeVec( ioaudio[ AUDIO_CONTROL ] );
3551 DeleteMsgPort( mpaudio ); audiompmsk = 0L;
3552 releaseAudio = FALSE;
3554 SetTDMode( cb, id, BUT_STOP );
3556 if( id->SignalTask && id->SignalBit != -1 )
3558 Signal( id->SignalTask, 1L << id->SignalBit );
3563 if( length )
3565 LONG i;
3566 UWORD volleft, volright;
3568 if( numChAllocated == 1L || IsStereo( id->SampleType ) )
3570 volright =
3571 volleft = id->Volume;
3573 else
3575 CalcPanVol( id->Volume, id->Panning, &volleft, &volright );
3578 /*- we work doublebuffered -*/
3579 for( i = 0; i < 2; i++ )
3581 struct IOAudio *ioa_left = ioaudio[ i + AUDIO_LEFT ],
3582 *ioa_right = ioaudio[ i + AUDIO_RIGHT ];
3584 /*- get free audiorequest -*/
3585 if( CheckIO( (struct IORequest *) ioa_left ) && CheckIO( (struct IORequest *) ioa_right ) )
3587 BYTE *data_left, *data_right;
3589 dbug( kprintf( "child/Request pair #%ld is free\n", i ); )
3591 RemoveRequest( (struct IORequest *) ioa_left );
3592 RemoveRequest( (struct IORequest *) ioa_right );
3594 if( buffer[ 0 ] )
3596 if( IsStereo( id->SampleType ) )
3598 LONG c, add = ( id->SampleType == SDTST_S16S ) ? 2 : 1;
3600 if( numChAllocated == 2L )
3602 BYTE *buf_left = buffer[ i * 2 ],
3603 *buf_right = buffer[ i * 2 + 1 ];
3605 data_left = buf_left;
3606 data_right = buf_right;
3608 for( c = samples; c; c-- )
3610 *buf_left++ = *sample; sample += add;
3611 *buf_right++ = *sample; sample += add;
3614 else
3616 BYTE *buf = buffer[ i ];
3618 data_left =
3619 data_right = buf;
3621 for( c = samples; c; c--, sample+=(add<<1) )
3623 *buf++ = ( sample[0] + sample[add] ) >> 1;
3627 else
3629 BYTE *buf = buffer[ i ];
3631 data_left =
3632 data_right = buf;
3634 if( id->SampleType == SDTST_M8S )
3636 if( ((IPTR)sample)&3 || ((IPTR)buf)&3 || ((IPTR)samples)&3 )
3638 CopyMem( sample, buf, samples );
3640 else
3642 CopyMemQuick( sample, buf, samples );
3645 sample += samples;
3647 else
3649 LONG c;
3651 for( c = samples; c; c--, sample+=2 )
3653 *buf++ = *sample;
3658 else
3660 data_left =
3661 data_right = sample;
3662 sample += samples;
3665 ioa_left->ioa_Data = data_left;
3666 ioa_left->ioa_Length = samples;
3667 ioa_left->ioa_Cycles = cycles;
3668 ioa_left->ioa_Period = Freq2Period( id->Frequency );
3669 ioa_left->ioa_Volume = volleft;
3670 ioa_left->ioa_Request.io_Flags = ADIOF_PERVOL;
3671 ioa_left->ioa_Request.io_Command = CMD_WRITE;
3672 BeginIO( (struct IORequest *) ioa_left );
3674 if( numChAllocated == 2L )
3676 ioa_right->ioa_Data = data_right;
3677 ioa_right->ioa_Length = samples;
3678 ioa_right->ioa_Cycles = cycles;
3679 ioa_right->ioa_Period = Freq2Period( id->Frequency );
3680 ioa_right->ioa_Volume = volright;
3681 ioa_right->ioa_Request.io_Flags = ADIOF_PERVOL;
3682 ioa_right->ioa_Request.io_Command = CMD_WRITE;
3683 BeginIO( (struct IORequest *) ioa_right );
3686 if( (length-=samples) < samples )
3688 samples = length;
3689 } // if
3690 } // if
3691 else
3693 dbug( kprintf( "child/Req #%ld in use\n", i ); )
3696 if( ! length )
3698 /* a continuous stream of data? */
3699 if( id->Continuous )
3701 /* notify */
3702 if( id->SignalTask && id->SignalBit != -1 )
3704 Signal( id->SignalTask, 1L << id->SignalBit );
3708 break;
3710 } // for
3712 if( restart )
3714 dbug( kprintf( "child/starting stereo channels\n" ); )
3715 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_START;
3716 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
3717 restart = FALSE;
3718 } // if
3719 } // if
3721 ReleaseSemaphore( &id->Lock );
3722 } // if
3723 } // while
3725 #if !defined(__MAXON__) && !defined(__AROS__)
3726 #define SysBase cb->cb_SysBase
3727 #endif
3730 /****************************************************************************/
3732 void __regargs CloseAHI( struct MsgPort *mp, struct AHIRequest *ahir )
3734 #if !defined(__MAXON__) && !defined(__AROS__)
3735 #undef SysBase
3736 struct Library *SysBase = (*(struct Library **)4L);
3737 #endif
3738 CloseDevice( (struct IORequest *) ahir );
3739 DeleteIORequest( (struct IORequest *) ahir );
3740 DeleteMsgPort( mp );
3741 #if !defined(__MAXON__) && !defined(__AROS__)
3742 #define SysBase cb->cb_SysBase
3743 #endif
3746 /****************************************************************************/
3748 struct Library * __regargs OpenAHI( struct MsgPort **mpp, struct AHIRequest **iop )
3750 #if !defined(__MAXON__) && !defined(__AROS__)
3751 #undef SysBase
3752 struct Library *SysBase = (*(struct Library **)4L);
3753 #endif
3754 struct MsgPort *mp;
3755 struct AHIRequest *ahir;
3757 mp = CreateMsgPort();
3758 if( ( ahir = (struct AHIRequest *) CreateIORequest( mp, sizeof( struct AHIRequest ) ) ) )
3760 ahir->ahir_Version = 4;
3761 if( ! OpenDevice( "ahi.device", AHI_NO_UNIT, (struct IORequest *)ahir, 0L ) )
3763 *mpp = mp;
3764 *iop = ahir;
3765 return( (struct Library *) ahir->ahir_Std.io_Device );
3767 else
3769 dbug( kprintf( "Can't open ahi.device v4\n" ); )
3772 DeleteIORequest( (struct IORequest *) ahir );
3774 else
3776 dbug( kprintf( "no memory for ahirequest or msgport\n" ); )
3778 DeleteMsgPort( mp );
3780 return FALSE;
3781 #if !defined(__MAXON__) && !defined(__AROS__)
3782 #define SysBase cb->cb_SysBase
3783 #endif
3786 /****************************************************************************/
3789 struct SoundFuncData {
3790 UWORD CyclesLeft;
3791 UWORD Cycles;
3792 UWORD Channels;
3793 UWORD Sound;
3794 BOOL Continuous;
3795 BOOL Valid[2];
3796 BOOL Restart;
3797 BOOL *Repeat;
3798 struct Task *SigTask;
3799 #if !defined(__MAXON__) && !defined(__AROS__)
3800 #undef SysBase
3801 struct Library *AHIBase;
3802 struct Library *SysBase;
3803 #define AHIBase sfd->AHIBase
3804 #define SysBase sfd->SysBase
3805 #endif
3808 #ifdef __MAXON__
3809 void SoundFunc( struct Hook *h, struct AHIAudioCtrl *actrl, struct AHISoundMessage *ahism )
3810 #else
3811 void __interrupt SoundFunc( REG(a0, struct Hook *h), REG(a2, struct AHIAudioCtrl *actrl), REG(a1, struct AHISoundMessage *ahism) )
3812 #endif
3814 struct SoundFuncData *sfd = (struct SoundFuncData *) h->h_Data;
3816 dbug( kprintf( "SoundFunc\n" ); )
3818 if( ! ( *sfd->Repeat ) )
3820 if( ! ( sfd->CyclesLeft-- ) )
3822 LONG i, snd = sfd->Sound;
3824 sfd->Valid[ snd ] = FALSE;
3826 sfd->Sound = snd = ( sfd->Continuous ) ? ! snd : AHI_NOSOUND;
3827 /* no echos please */
3828 if( ! sfd->Valid[ snd ] )
3830 snd = AHI_NOSOUND;
3831 sfd->Restart = TRUE;
3834 for( i = 0; i < sfd->Channels; i++ )
3836 AHI_SetSound( i, snd, 0L, 0L, actrl, 0L );
3839 sfd->CyclesLeft = sfd->Cycles;
3841 Signal ( sfd->SigTask, SIGBREAKF_CTRL_C );
3846 #if !defined(__MAXON__) && !defined(__AROS__)
3847 #undef AHIBase
3848 #undef SysBase
3849 #define SysBase cb->cb_SysBase
3850 #endif
3852 /****************************************************************************/
3854 void PlayerProcAHI( void )
3856 #if !defined(__MAXON__) && !defined(__AROS__)
3857 struct Library *SysBase = (*(struct Library **)4L);
3858 struct Library *AHIBase = NULL;
3859 #endif
3860 struct Process *pr = (struct Process *) FindTask( NULL );
3861 struct MsgPort *mp, *AHImp;
3862 struct AHIRequest *ahir;
3863 struct AHIAudioCtrl *actrl = NULL;
3864 struct SoundFuncData *sfd = NULL;
3865 struct Hook *SoundHook = NULL;
3866 struct ClassBase *cb = NULL;
3867 struct InstanceData *id = NULL;
3868 ULONG mpmsk, numCh = 0, buffersize = 0;
3869 BOOL stereo, paused = FALSE, failed;
3870 static UBYTE sdtst2ahist[] = { AHIST_M8S, AHIST_S8S, AHIST_M16S, AHIST_S16S };
3871 BYTE *buffer = NULL;
3873 mp = &pr->pr_MsgPort;
3874 mpmsk = 1L << mp->mp_SigBit;
3876 dbug( kprintf( "child launched\n" ); )
3878 for( ;; )
3880 LONG rcv;
3881 struct ObjectMsg *msg;
3883 rcv = Wait( mpmsk | SIGBREAKF_CTRL_C );
3885 if( rcv & mpmsk )
3887 while( ( msg = (struct ObjectMsg *) GetMsg( mp ) ) )
3889 switch( msg->Command )
3891 case COMMAND_NEXT_BUFFER:
3893 dbug( kprintf( "child: COMMAND_NEXT_BUFFER\n"); )
3895 ObtainSemaphoreShared( &id->Lock );
3897 if( AHIBase )
3899 BYTE *dst = ( sfd->Sound ) ? &buffer[ buffersize ] : buffer;
3900 ULONG transfer = UMult( id->SampleLength, bytesPerPoint[ id->SampleType ] ), i;
3902 if( transfer > buffersize )
3904 transfer = buffersize;
3907 if( ((IPTR)id->Sample)&3 || ((IPTR)dst)&3 || ((IPTR)transfer)&3 )
3909 CopyMem( id->Sample, dst, transfer );
3911 else
3913 CopyMemQuick( id->Sample, dst, transfer );
3916 for( i = transfer; i < buffersize; i++ )
3918 dst[ i ] = 0;
3921 sfd->Valid[ sfd->Sound ] = TRUE;
3923 /* new sample wasn't available fast enough */
3924 if( sfd->Restart )
3926 sfd->Restart = FALSE;
3928 dbug( kprintf( "restart playback\n" ); )
3930 for( i = 0; i < numCh; i++ )
3932 AHI_SetSound( i, sfd->Sound, 0,0, actrl, AHISF_IMM );
3937 ReleaseSemaphore( &id->Lock );
3939 break;
3941 case COMMAND_INIT:
3942 dbug( kprintf("child: COMMAND_INIT\n"); )
3944 id = (struct InstanceData *) msg->Data;
3945 cb = id->ClassBase;
3947 if( ! ( mp = msg->Data = CreateMsgPort() ) )
3949 ReplyMsg( &msg->Message );
3950 return;
3953 mpmsk = 1L << mp->mp_SigBit;
3954 break;
3956 case COMMAND_EXIT:
3957 case COMMAND_STOP:
3959 dbug( kprintf("child: COMMAND_STOP/EXIT\n"); )
3961 if( AHIBase )
3963 AHI_FreeAudio( actrl );
3964 FreeVec( SoundHook );
3965 FreeVec( buffer );
3966 buffer = NULL;
3967 CloseAHI( AHImp, ahir );
3968 AHIBase = NULL;
3970 SetTDMode( cb, id, BUT_STOP );
3973 if( msg->Command == COMMAND_EXIT )
3975 Forbid();
3976 ReplyMsg( &msg->Message );
3977 DeleteMsgPort( mp );
3978 return;
3981 break;
3983 case COMMAND_PERVOL:
3984 dbug( kprintf("child: COMMAND_PERVOL\n"); )
3986 if( AHIBase )
3988 ULONG freq, vol, pan, i;
3990 ObtainSemaphoreShared( &id->Lock );
3991 pan = id->Panning;
3992 vol = ( id->Volume << 10 );
3993 freq = id->Frequency;
3994 ReleaseSemaphore( &id->Lock );
3996 for( i = 0; i < numCh; i++ )
3998 if( ! paused )
4000 AHI_SetFreq( i, freq, actrl, AHISF_IMM );
4002 AHI_SetVol( i, vol, pan, actrl, AHISF_IMM );
4005 break;
4007 case COMMAND_PAUSE:
4009 if( AHIBase )
4011 if( ! paused )
4013 LONG i;
4015 for( i = 0; i < numCh; i++ )
4017 AHI_SetFreq( i, 0L, actrl, AHISF_IMM );
4020 paused = TRUE;
4024 break;
4026 case COMMAND_PLAY:
4027 dbug( kprintf("child: COMMAND_PLAY\n"); )
4029 // ObtainSemaphoreShared( &id->Lock );
4031 if( AHIBase )
4033 if( paused )
4035 LONG i;
4037 for( i = 0; i < numCh; i++ )
4039 AHI_SetFreq( i, id->Frequency, actrl, AHISF_IMM );
4042 paused = FALSE;
4044 else
4046 LONG i;
4048 AHI_ControlAudio( actrl,
4049 AHIC_Play, FALSE,
4050 TAG_DONE );
4052 for( i = 0; i < numCh; i++ )
4054 AHI_SetSound( i, sfd->Sound, 0,0, actrl, AHISF_IMM );
4057 sfd->CyclesLeft = sfd->Cycles;
4059 AHI_ControlAudio( actrl,
4060 AHIC_Play, TRUE,
4061 TAG_DONE );
4064 else
4066 failed = TRUE;
4068 if( ( AHIBase = OpenAHI( &AHImp, &ahir ) ) )
4070 stereo = IsStereo( id->SampleType );
4072 if( ( SoundHook = (struct Hook *) AllocVec( sizeof( *SoundHook ) + sizeof( *sfd ), MEMF_CLEAR|MEMF_PUBLIC ) ) )
4074 ULONG audioID, mixfreq;
4075 #ifndef __AROS__
4076 extern void HookEntry( void );
4077 #endif
4079 numCh = stereo ? 2 : 1;
4081 sfd = (struct SoundFuncData *) (SoundHook+1);
4082 #if defined(__MAXON__) || defined(__AROS__)
4083 SoundHook->h_Entry = (HOOKFUNC) HookEntry;
4084 SoundHook->h_SubEntry = (HOOKFUNC) SoundFunc;
4085 #else
4086 SoundHook->h_Entry = (HOOKFUNC) SoundFunc;
4087 #endif
4088 SoundHook->h_Data = (APTR) sfd;
4090 sfd->SigTask = &pr->pr_Task;
4091 sfd->Channels = numCh;
4092 sfd->Cycles =
4093 sfd->CyclesLeft = UMult( id->Cycles, numCh );
4094 // sfd->Sound = 0;
4095 sfd->Continuous = id->Continuous;
4096 sfd->Valid[ 0 ] = TRUE;
4097 sfd->Repeat = (BOOL *) &id->Repeat;
4098 // sfd->Valid[ 1 ] = FALSE;
4099 // sfd->Restart = FALSE;
4100 #if !defined(__MAXON__) && !defined(__AROS__)
4101 sfd->AHIBase = AHIBase;
4102 sfd->SysBase = SysBase;
4103 #endif
4104 dbug( kprintf("child: ahi is open\n"); )
4106 ObtainSemaphoreShared( &cb->cb_LibLock );
4108 mixfreq = cb->cb_AHIMixFrequency;
4110 if( cb->cb_ForceAHIMode )
4112 audioID = cb->cb_AHIModeID;
4114 else
4116 if( ( audioID = AHI_BestAudioID(
4117 ( cb->cb_AHIModeID ? AHIDB_AudioID : TAG_IGNORE ), cb->cb_AHIModeID,
4118 AHIDB_Volume, TRUE,
4119 ( ! stereo ? TAG_IGNORE : AHIDB_Stereo ), TRUE,
4120 ( ! stereo ? AHIDB_Panning : TAG_IGNORE ), TRUE,
4121 TAG_DONE ) ) == AHI_INVALID_ID )
4123 audioID = AHI_DEFAULT_ID;
4124 dbug( kprintf("child: bestaid failed\n"); )
4128 ReleaseSemaphore( &cb->cb_LibLock );
4130 if( ( actrl = AHI_AllocAudio(
4131 AHIA_AudioID, audioID,
4132 AHIA_Channels, numCh,
4133 AHIA_Sounds, ( id->Continuous ) ? 2L : 1L,
4134 AHIA_MixFreq, mixfreq,
4135 ( id->Cycles ? AHIA_SoundFunc : TAG_IGNORE), (IPTR) SoundHook,
4136 TAG_DONE ) ) )
4138 struct AHISampleInfo sample;
4139 ULONG freq, vol;
4141 freq = id->Frequency;
4142 vol = ( id->Volume << 10 );
4144 dbug( kprintf("child: alloc audio okay\n"); )
4146 sample.ahisi_Type = sdtst2ahist[ id->SampleType ];
4147 sample.ahisi_Length = id->SampleLength;
4149 if( id->Continuous )
4151 ULONG playsamples;
4153 AHI_GetAudioAttrs( AHI_INVALID_ID, actrl, AHIDB_MaxPlaySamples,(IPTR) &playsamples, TAG_DONE );
4154 AHI_ControlAudio( actrl, AHIC_MixFreq_Query, (IPTR) &mixfreq, TAG_DONE );
4156 buffersize = UDiv( UMult( playsamples, id->Frequency ), mixfreq );
4158 if( buffersize < id->SampleLength )
4160 buffersize = id->SampleLength;
4163 buffersize = UMult( buffersize, bytesPerPoint[ id->SampleType ] );
4165 if( ( buffer = AllocVec( buffersize*2, MEMF_PUBLIC|MEMF_CLEAR ) ) )
4167 sample.ahisi_Address = buffer;
4169 if( ! AHI_LoadSound( 0, AHIST_DYNAMICSAMPLE, &sample, actrl ) )
4171 sample.ahisi_Address = &buffer[ buffersize ];
4173 failed = (BOOL) AHI_LoadSound( 1, AHIST_DYNAMICSAMPLE, &sample, actrl );
4176 CopyMem( id->Sample, buffer, UMult( id->SampleLength, bytesPerPoint[ id->SampleType ] ) );
4180 else
4182 sample.ahisi_Address = id->Sample;
4184 failed = (BOOL) AHI_LoadSound( 0, AHIST_SAMPLE, &sample, actrl );
4187 dbug( kprintf("child: loading sample\n"); )
4189 if( ! failed )
4191 failed = TRUE;
4193 if( ! AHI_ControlAudio( actrl,
4194 AHIC_Play, TRUE,
4195 TAG_DONE ) )
4197 AHI_Play( actrl,
4198 AHIP_BeginChannel, 0,
4199 AHIP_Freq, freq,
4200 AHIP_Vol, vol,
4201 AHIP_Pan, id->Panning,
4202 AHIP_Sound, 0,
4203 AHIP_EndChannel, 0,
4204 ( stereo ? TAG_IGNORE : TAG_END ), 0L,
4205 AHIP_BeginChannel, 1,
4206 AHIP_Freq, freq,
4207 AHIP_Vol, vol,
4208 AHIP_Pan, id->Panning,
4209 AHIP_Sound, 0,
4210 AHIP_EndChannel, 0,
4211 TAG_DONE );
4213 failed = FALSE;
4215 dbug( kprintf( "child: playback started, freq: %ld\n", freq ); )
4217 else
4219 dbug( kprintf( "child: CtrlAudio failed\n" ); )
4222 else
4224 dbug( kprintf( "child: loadsample failed\n" ); )
4227 else
4229 dbug( kprintf( "child: AllocAudio failed\n"); )
4232 else
4234 dbug( kprintf( "child: No free store\n" ); )
4238 if( failed )
4240 AHI_FreeAudio( actrl );
4241 FreeVec( SoundHook );
4242 FreeVec( buffer );
4243 buffer = NULL;
4244 CloseAHI( AHImp, ahir );
4245 AHIBase = NULL;
4246 SetTDMode( cb, id, BUT_STOP );
4248 else
4250 SetTDMode( cb, id, BUT_PLAY );
4254 // ReleaseSemaphore( &id->Lock );
4255 break;
4258 if( msg->Message.mn_ReplyPort )
4260 ReplyMsg( &msg->Message );
4262 else // NT_FREEMSG
4264 FreeVec( msg );
4269 if( rcv & SIGBREAKF_CTRL_C )
4271 dbug( kprintf( "child: end of sample\n" ); )
4273 if( AHIBase )
4275 ObtainSemaphoreShared( &id->Lock );
4276 if( id->SignalTask && id->SignalBit != -1 )
4278 Signal( id->SignalTask, 1L << id->SignalBit );
4280 ReleaseSemaphore( &id->Lock );
4282 if( ! id->Continuous )
4284 AHI_FreeAudio( actrl );
4285 FreeVec( SoundHook );
4286 FreeVec( buffer );
4287 buffer = NULL;
4288 CloseAHI( AHImp, ahir );
4289 AHIBase = NULL;
4290 SetTDMode( cb, id, BUT_STOP );
4296 #if !defined(__MAXON__) && !defined(__AROS__)
4297 #define SysBase cb->cb_SysBase
4298 #endif
4301 /****************************************************************************/
4303 unsigned __regargs StrLen( STRPTR str )
4305 STRPTR p = str;
4307 while( *str++ );
4309 return( ~(unsigned) (p - str) );
4312 /****************************************************************************/
4314 IPTR __regargs Sound_OBTAINDRAWINFO( Class *cl, Object *o, struct opSet *ops )
4316 struct InstanceData *id = INST_DATA( cl, o );
4318 dbug( kprintf( "DTM_OBTAINDRAWINFO\n" ); )
4320 return (IPTR)( ( id->Screen = (struct Screen *) GetTagData( PDTA_Screen, 0, ops->ops_AttrList ) ) ||
4321 ( id->DrawInfo = (struct DrawInfo *) GetTagData( GA_DrawInfo, 0, ops->ops_AttrList ) )
4325 /****************************************************************************/
4327 IPTR __regargs Sound_RELEASEDRAWINFO( Class *cl, Object *o, Msg msg )
4329 return (IPTR)0;
4332 /****************************************************************************/
4334 IPTR __regargs Sound_REMOVEDTOBJECT( Class *cl, Object *o, Msg msg )
4336 struct InstanceData *id = INST_DATA( cl, o );
4337 /* prevent other tasks (cursor- or playertask) from reading this */
4338 dbug( kprintf( "DTM_REMOVEDTOBJECT\n" ); )
4340 ObtainSemaphore( &id->Lock );
4341 id->Window = (struct Window *)NULL;
4342 id->Requester = NULL;
4343 ReleaseSemaphore( &id->Lock );
4345 if( id->ColorMap )
4347 ReleasePen( id->ColorMap, id->BackgroundPen );
4348 ReleasePen( id->ColorMap, id->WaveformPen );
4351 return (IPTR) DoSuperMethodA(cl, o, msg);