4 ** © 1998-2004 by Stephan Rupprecht
9 #if !defined(__MAXON__) && !defined(__AROS__)
10 #define CLIB_ALIB_PROTOS_H
13 #include <exec/memory.h>
14 #include <exec/execbase.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>
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>
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>
63 #include "classbase.h"
66 #include "CompilerSpecific.h"
68 #include "BoopsiStubs.h"
76 #include <aros/debug.h>
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
92 #define G(x) ((struct Gadget *)(x))
93 #define MAX( a, b ) ((a) > (b) ? (a) : (b))
94 #define EXTG( x ) ((struct ExtGadget *)(x))
97 #define ID_CHAN MAKE_ID( 'C', 'H', 'A', 'N' )
100 #define ID_16SV MAKE_ID( '1', '6', 'S', 'V' )
104 #include <aros/symbolsets.h>
105 /* Optionally open tapedeck gadget */
106 ADD2LIBS("gadgets/tapedeck.gadget", -40, struct Library
*, TapeDeckBase
)
110 #define ID_PAN MAKE_ID( 'P', 'A', 'N', ' ' )
113 #define ID_ANNO MAKE_ID( 'A', 'N', 'N', 'O' )
116 #define ID_AUTH MAKE_ID( 'A', 'U', 'T', 'H' )
119 #define ID_FVER MAKE_ID( 'F', 'V', 'E', 'R' )
122 #define ID_Copyright MAKE_ID( '(', 'c', ')', ' ' )
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!)
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) )
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) )
142 #define Period2Freq( x ) ( UDiv( UMult(709379, 5L ), (x) ) )
144 #define Period2Freq( x ) ( UDiv( UMult( ((struct ExecBase *)SysBase)->ex_EClockFrequency, 5L ), (x) ) )
147 #define Freq2Period( x ) Period2Freq( x )
148 #define IsStereo( x ) ( (BOOL) ( ( x ) & 1 ) )
151 #define SHRT_MAX 0x7fff
161 /****************************************************************************/
164 IPTR
Dispatcher(REG(a0
,Class
*cl
), REG(a2
,Object
*o
), REG(a1
,Msg msg
));
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
[] =
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
},
254 #if defined(__MAXON__) || defined(__AROS__)
255 struct Library
*AHIBase
= NULL
;
258 /****************************************************************************/
261 #if !defined(__MAXON__) && !defined(__AROS__)
262 void kprintf( STRPTR FormatStr
, ... )
265 struct Library
*SysBase
= (*(struct Library
**)4L);
267 STRPTR p
= PutChData
;
269 RawDoFmt(FormatStr
, ((STRPTR
)(&FormatStr
))+4, (void (*)())"\x16\xc0\x4e\x75", PutChData
);
273 #define SysBase cb->cb_SysBase
278 /****************************************************************************/
280 IPTR
Dispatcher(REG(a0
,Class
*cl
), REG(a2
,Object
*o
), REG(a1
,Msg msg
))
282 struct ClassBase
*cb
= (struct ClassBase
*)cl
->cl_UserData
;
287 switch( msg
->MethodID
)
290 retval
= Sound_NEW( cl
, o
, (struct opSet
*)msg
);
294 retval
= Sound_GET( cl
, o
, (struct opGet
*)msg
);
298 retval
= Sound_UPDATE( cl
, o
, (struct opUpdate
*)msg
);
302 retval
= Sound_SET( cl
, o
, (struct opSet
*)msg
);
306 retval
= Sound_DISPOSE( cl
, o
, msg
);
311 retval
= Sound_HITTEST( cl
, o
, (struct gpHitTest
*) msg
);
316 retval
= Sound_HANDLEINPUT( cl
, o
, (struct gpInput
*)msg
);
320 retval
= Sound_GOINACTIVE( cl
, o
, (struct gpGoInactive
*) msg
);
324 retval
= Sound_DOMAIN( cl
, o
, (struct gpDomain
*)msg
);
329 retval
= Sound_LAYOUT( cl
, o
, (struct gpLayout
*)msg
);
333 retval
= Sound_RENDER( cl
, o
, (struct gpRender
*)msg
);
337 retval
= Sound_TRIGGER( cl
, o
, (struct dtTrigger
*)msg
);
342 retval
= Sound_WRITE( cl
, o
, (struct dtWrite
*)msg
);
346 retval
= Sound_SELECT( cl
, o
, (struct dtSelect
*) msg
);
349 case DTM_CLEARSELECTED
:
350 retval
= Sound_CLEARSELECTED( cl
, o
, (struct dtGeneral
*) msg
);
353 case DTM_OBTAINDRAWINFO
:
354 retval
= Sound_OBTAINDRAWINFO( cl
, o
, (struct opSet
*) msg
);
358 retval
= Sound_DRAW( cl
, o
, (struct dtDraw
*) msg
);
361 case DTM_RELEASEDRAWINFO
:
363 dbug( kprintf( "DTM_RELEASEDRAWINFO\n" ); )
368 case DTM_REMOVEDTOBJECT
:
369 retval
= Sound_REMOVEDTOBJECT(cl
, o
, msg
);
374 dbug( kprintf("METHOD: %08lx\n", msg
->MethodID
); )
375 retval
= (IPTR
) DoSuperMethodA(cl
, o
, msg
);
382 /****************************************************************************/
385 ULONG
NotifyAttrs( Object
*o
, struct GadgetInfo
*ginfo
, ULONG flags
, Tag tag1
, ... )
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
) ) );
398 /****************************************************************************/
400 LONG
SendObjectMsg( struct InstanceData
*id
, ULONG Command
, APTR Data
)
402 #if !defined(__MAXON__) && !defined(__AROS__)
404 struct Library
*SysBase
= (*(struct Library
**)4L);
406 struct ObjectMsg
*msg
;
408 if( ( msg
= AllocVec( sizeof( *msg
), MEMF_PUBLIC
|MEMF_CLEAR
) ) )
410 msg
->Command
= Command
;
412 PutMsg( id
->PlayerPort
, &msg
->Message
);
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
425 /****************************************************************************/
427 LONG __regargs
Sound_CLEARSELECTED( Class
*cl
, Object
*o
, struct dtGeneral
*dtg
)
430 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
431 struct ClassBase
*cb
= (struct ClassBase
*) cl
->cl_UserData
;
436 dbug( kprintf( "DTM_CLEARSELECTED\n"); )
438 /* 'magic' nothing selected value */
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
;
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
,
470 dbug( kprintf("DTM_SELECT\n"); )
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
;
492 if( samplelength
>> 17 )
497 /* get first and last sample of the marked area by
498 ** comparing the coordinates */
499 if( samplelength
<= w
)
504 sub
= 2*(dx
+1); add
= 2*(dy
+1);
508 if( x
>= minX
&& startSample
== ~0 )
512 else if( x
++ >= maxX
)
530 sub
= 2*(dy
+1); add
= 2*(dx
+1);
532 for( i
= 0; i
< samplelength
; i
+=step
)
536 if( x
>= minX
&& startSample
== ~0 )
540 else if( x
++ >= maxX
)
552 /* some corrections */
553 if( endSample
== ~0 )
555 endSample
= samplelength
;
563 id
->StartSample
= startSample
;
564 id
->EndSample
= endSample
;
566 dbug( kprintf( "%ld, %ld\n", startSample
, endSample
); )
571 /****************************************************************************/
573 void __regargs
GetSoundDTPrefs( struct ClassBase
*cb
)
578 dbug( kprintf( "GetSoundDTPrefs\n" ); )
580 ObtainSemaphore( &cb
->cb_LibLock
);
582 /* set default settings */
583 dbug( kprintf( "Setting default values\n" ); )
589 cb
->cb_AHIModeID
= AHI_DEFAULT_ID
;
590 cb
->cb_ForceAHIMode
= FALSE
;
591 cb
->cb_AHIMixFrequency
= AHI_DEFAULT_FREQ
;
593 cb
->cb_Compress
= FALSE
;
596 cb
->cb_NomWidth
= 160;
597 cb
->cb_NomHeight
= 100;
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;
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
;
630 LONG
*width
, *height
;
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" ); )
649 dbug( kprintf( "AHI\n" ); )
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" ); )
666 cb
->cb_AHIMixFrequency
= *args
.mixfreq
;
667 dbug( kprintf( "AHIMIXFREQ = %ld\n", *args
.mixfreq
); )
673 dbug( kprintf( "AIFF16\n" ); )
678 cb
->cb_Compress
= TRUE
;
679 dbug( kprintf( "COMPRESS\n" ); )
684 cb
->cb_NomWidth
= *args
.width
;
685 dbug( kprintf( "WIDTH = %ld\n", *args
.width
); )
690 cb
->cb_NomHeight
= *args
.height
;
691 dbug( kprintf( "HEIGHT = %ld\n", *args
.height
); )
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
); )
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
); )
728 cb
->cb_ControlPanel
= TRUE
;
729 dbug( kprintf( "CP=YES\n" ); )
733 cb
->cb_ControlPanel
= FALSE
;
734 dbug( kprintf( "CP=NO\n" ); )
739 cb
->cb_Volume
= *args
.volume
;
740 dbug( kprintf( "VOLUME = %ld\n", *args
.volume
); )
745 cb
->cb_NoGTSlider
= TRUE
;
746 dbug( kprintf( "NOGTSLIDER\n" ); )
749 FreeArgs( freeargs
);
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
);
766 dbug( kprintf( "AllocDosObject() failed\n" ); )
771 dbug( kprintf( "GetVar failed\n" ); )
774 ReleaseSemaphore( &cb
->cb_LibLock
);
777 /****************************************************************************/
779 LONG __regargs
hex2long(STRPTR s
)
783 if (s
&& (c
=*s
++) && (c
=='$' || (c
== '0' && *s
++ == 'x'))) {
788 if ((c
-='0')<0 || (c
>9 && (c
-=7)>15))
797 /****************************************************************************/
799 void CreateTapeDeck( struct ClassBase
*cb
, struct InstanceData
*id
, Object
*o
)
801 #if defined(__MAXON__) || defined(__AROS__)
802 extern struct Library
*TapeDeckBase
;
804 #define TapeDeckBase cb->cb_TapeDeckBase
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
,
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
,
829 if( ( id
->TapeDeckGadget
= NewObject( NULL
, "tapedeck.gadget",
833 ReleaseSemaphore( &cb
->cb_LibLock
);
837 DisposeObject( id
->VolumeSlider
);
838 id
->VolumeSlider
= NULL
;
841 ReleaseSemaphore( &cb
->cb_LibLock
);
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
;
869 ti
[3].ti_Tag
= DTA_HorizUnit
;
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 );
889 // id->SampleType = SDTST_M8S;
890 id
->Panning
= 0x8000;
891 /* 'magic' nothing selected value */
896 id
->TapeDeckHeight
= 15L; // tapedeck.gadget is currently limited to 15 pixels
898 id
->WaveformPen
= -1;
900 id
->FreeSampleData
= TRUE
;
901 // id->SyncSampleChange = FALSE;
902 InitSemaphore( &id
->Lock
);
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
,
917 msg
->Data
= (APTR
) id
;
918 msg
->Command
= COMMAND_INIT
;
919 PutMsg( &id
->PlayerProc
->pr_MsgPort
, &msg
->Message
);
920 WaitPort( replyport
);
925 id
->PlayerPort
= (struct MsgPort
*) msg
->Data
;
929 id
->PlayerProc
= NULL
;
933 ReleaseSemaphore( &cb
->cb_LibLock
);
935 DeleteIORequest( (struct IORequest
*) msg
);
939 parsetaglist( cl
, o
, ops
, NULL
);
940 CreateTapeDeck( cb
, id
, o
);
944 CoerceMethod( cl
, o
, OM_DISPOSE
);
950 dbug( kprintf( "No memory for ioreq or msgport\n" ); )
953 DeleteMsgPort( replyport
);
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"); )
967 /****************************************************************************/
969 void __regargs
SetVSlider( struct ClassBase
*cb
, struct InstanceData
*id
)
971 /* this function works aroung a "spilled register" error */
972 if( id
->ControlPanel
)
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
;
994 ObtainSemaphore( &id
->Lock
);
995 dbug( kprintf( "NextTagItem\n" ); )
996 while( ( ti
= NextTagItem( (const struct TagItem
**)&tstate
) ) )
998 IPTR data
= ti
->ti_Data
;
1000 switch( ti
->ti_Tag
)
1002 case SDTA_VoiceHeader
:
1003 id
->VoiceHeader
= *(struct VoiceHeader
*) data
;
1004 dbug( kprintf("SDTA_VoiceHeader\n"); )
1009 id
->Sample
= (BYTE
*) data
;
1010 id
->LeftSample
= FALSE
;
1011 dbug( kprintf("SDTA_Sample = %08lx\n", data
); )
1016 case SDTA_SampleLength
:
1017 id
->SampleLength
= data
;
1018 dbug( kprintf("SDTA_SampleLength = %ld\n", data
); )
1023 id
->Frequency
= (UWORD
) Period2Freq( data
);
1025 dbug( kprintf("SDTA_Period = %ld (%lDHz)\n", data
, Period2Freq(data
) ); )
1030 id
->Volume
= (UWORD
) data
;
1033 SetVSlider( cb
, id
);
1035 dbug( kprintf("SDTA_Volume = %ld\n", data
); )
1041 id
->Cycles
= (UWORD
) data
;
1042 dbug( kprintf("SDTA_Cycles = %ld\n", data
); )
1046 case SDTA_SignalTask
:
1047 id
->SignalTask
= (struct Task
*) data
;
1048 dbug( kprintf("SDTA_SignalTask = %08lx\n", data
); )
1052 case SDTA_SignalBitMask
: // aka: SDTA_SignalBit
1053 dbug( kprintf("SDTA_SignalBit(Mask) = %08lx\n", data
); )
1058 for( i
= 0; i
< 32; i
++ )
1060 if( ( 1L << i
) & data
)
1067 else id
->SignalBit
= -1;
1071 case SDTA_Continuous
:
1072 id
->Continuous
= (BOOL
) data
;
1073 dbug( kprintf("SDTA_Continuous = %ld\n", data
); )
1077 case SDTA_SampleType
:
1078 id
->SampleType
= data
;
1079 dbug( kprintf("SDTA_SampleType = %ld\n", data
); )
1087 dbug( kprintf("SDTA_Panning = %05lx\n", data
); )
1091 case SDTA_SamplesPerSec
:
1092 case SDTA_Frequency
:
1093 id
->Frequency
= data
;
1095 dbug( kprintf("SDTA_Frequency/SamplesPerSec =%ld\n", data
); )
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
); )
1111 if( ! ( id
->Immediate
= data
) )
1113 CoerceMethod( cl
, o
, DTM_TRIGGER
, 0, STM_STOP
, 0 );
1117 newSample
= ( id
->Sample
!= NULL
);
1118 id
->DelayedImmed
= TRUE
;
1120 dbug( kprintf("DTA_Immediate = %ld\n", data
); )
1125 id
->Repeat
= (BOOL
) data
;
1126 dbug( kprintf("DTA_Repeat = %ld\n", data
); )
1130 case SDTA_SyncSampleChange
:
1131 id
->SyncSampleChange
= data
;
1132 dbug( kprintf("SDTA_SyncSampleChange = %ld\n", data
); )
1136 case SDTA_FreeSampleData
:
1137 id
->FreeSampleData
= data
;
1138 dbug( kprintf("SDTA_FreeSampleData = %ld\n", data
); )
1142 case SDTA_LeftSample
:
1143 id
->LeftSample
= TRUE
;
1144 id
->Sample
= (BYTE
*) data
;
1146 dbug( kprintf("SDTA_LeftSample = %08lx\n", data
); )
1150 case SDTA_RightSample
:
1151 id
->RightSample
= (BYTE
*) data
;
1153 dbug( kprintf("SDTA_RightSample = %08lx\n", data
); )
1157 case SDTA_SignalBitNumber
:
1158 id
->SignalBit
= data
;
1159 dbug( kprintf("SDTA_SignalBitNumber = %ld\n", data
); )
1164 dbug( kprintf("Attr: %08lx\n", ti
->ti_Tag
); )
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
);
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
;
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"); )
1220 data
= (IPTR
) ( ( id
->LeftSample
) ? NULL
: id
->Sample
);
1221 dbug( kprintf("SDTA_Sample\n"); )
1224 case SDTA_SampleLength
:
1225 data
= id
->SampleLength
;
1226 dbug( kprintf("SDTA_SampleLength\n"); )
1230 data
= (IPTR
) Freq2Period( id
->Frequency
);
1231 dbug( kprintf("SDTA_Period\n"); )
1235 data
= (IPTR
) id
->Volume
;
1236 dbug( kprintf("SDTA_Volume\n"); )
1240 data
= (IPTR
) id
->Cycles
;
1241 dbug( kprintf("SDTA_Cycles\n"); )
1244 case SDTA_SignalTask
:
1245 data
= (IPTR
) id
->SignalTask
;
1246 dbug( kprintf("SDTA_SignalTask\n"); )
1249 case SDTA_SignalBitMask
: // aka SDTA_SignalBit
1250 data
= (IPTR
) ( id
->SignalBit
== -1 ) ? 0L : ( 1L << id
->SignalBit
);
1251 dbug( kprintf("SDTA_SignalBit(Mask)\n"); )
1254 case SDTA_SignalBitNumber
:
1255 data
= id
->SignalBit
;
1256 dbug( kprintf("SDTA_SignalBitNumber\n"); )
1259 case SDTA_Continuous
:
1260 data
= (IPTR
) id
->Continuous
;
1261 dbug( kprintf("SDTA_Continuous\n"); )
1267 dbug( kprintf("SDTA_Pan(ning)\n"); )
1270 case SDTA_SampleType
:
1271 data
= id
->SampleType
;
1272 dbug( kprintf("SDTA_SampleType\n"); )
1275 case SDTA_SamplesPerSec
:
1276 case SDTA_Frequency
:
1277 data
= id
->Frequency
;
1278 dbug( kprintf("SDTA_Frequency/SamplesPerSec\n"); )
1281 case DTA_TriggerMethods
:
1282 data
= (IPTR
) TriggerMethods
;
1283 dbug( kprintf("SDTA_TriggerMethods\n"); )
1286 case DTA_ControlPanel
:
1287 data
= (IPTR
) id
->ControlPanel
;
1288 dbug( kprintf("DTA_ControlPanel\n"); )
1292 data
= (IPTR
) id
->Repeat
;
1293 dbug( kprintf("DTA_Repeat\n"); )
1297 data
= (IPTR
) id
->Immediate
;
1298 dbug( kprintf("DTA_Immediate\n"); )
1303 dbug( kprintf( "DTA_Methods\n"); )
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
)
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
)
1340 *newMethods
++ = method
;
1348 data
= (ULONG
) Methods
;
1352 ReleaseSemaphore( &cb
->cb_LibLock
);
1354 ObtainSemaphore( &cb
->cb_LibLock
);
1356 if( ! ( data
= (IPTR
) cb
->cb_Methods
) )
1358 if( DataTypesBase
->lib_Version
>= 45L )
1360 ULONG
*superMethods
= NULL
;
1362 DoSuperMethod( cl
, o
, OM_GET
, DTA_Methods
, (ULONG
) &superMethods
);
1364 data
= (ULONG
) ( cb
->cb_Methods
= CopyDTMethods( superMethods
, Methods
, NULL
) );
1366 dbug( kprintf( "CopyDTMethods returned %08lx\n", data
); )
1372 data
= (IPTR
) Methods
;
1375 ReleaseSemaphore (&cb
->cb_LibLock
);
1380 case SDTA_SyncSampleChange
:
1381 data
= id
->SyncSampleChange
;
1382 dbug( kprintf("SDTA_SyncSampleChange\n"); )
1385 case SDTA_FreeSampleData
:
1386 data
= id
->FreeSampleData
;
1387 dbug( kprintf("SDTA_FreeSampleData\n"); )
1390 case SDTA_LeftSample
:
1391 data
= (IPTR
) ( ( id
->LeftSample
) ? id
->Sample
: NULL
);
1392 dbug( kprintf("SDTA_LeftSample\n"); )
1395 case SDTA_RightSample
:
1396 data
= (IPTR
) id
->RightSample
;
1397 dbug( kprintf("SDTA_RightSample\n"); )
1400 case SDTA_ReplayPeriod
:
1404 data
= (IPTR
) &id
->ReplayPeriod
;
1406 if( id
->Continuous
)
1411 else if( id
->SampleLength
)
1413 secs
= UDiv( id
->SampleLength
, id
->Frequency
);
1414 micro
= UMult( UDiv( 1000000, id
->Frequency
), ( id
->SampleLength
% id
->Frequency
) );
1422 id
->ReplayPeriod
.tv_secs
= secs
;
1423 id
->ReplayPeriod
.tv_micro
= micro
;
1425 dbug( kprintf("SDTA_ReplayPeriod %ld:%ld\n", secs
, micro
); )
1431 dbug( kprintf("Attr: %08lx\n", opg
->opg_AttrID
); )
1436 *opg
->opg_Storage
= data
;
1440 retval
= DoSuperMethodA( cl
, o
, (Msg
) opg
);
1441 dbug( kprintf("SuperAttr: %08lx, %08lx\n", opg
->opg_AttrID
, *opg
->opg_Storage
); )
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
);
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
;
1488 dbug( kprintf("OM_UPDATE\n"); )
1490 if( DoSuperMethodA( cl
, o
, (Msg
) &methodID
) )
1495 dbug( kprintf("no loop %08lx\n", (ULONG
)opu
); )
1497 return Sound_SET( cl
, o
, (struct opSet
*) opu
);
1500 /****************************************************************************/
1502 IPTR __regargs
Sound_DISPOSE( Class
*cl
, Object
*o
, Msg msg
)
1504 struct ClassBase
*cb
= (struct ClassBase
*) cl
->cl_UserData
;
1505 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
1506 struct SignalSemaphore
*lock
= &((struct DTSpecialInfo
*)G( o
)->SpecialInfo
)->si_Lock
;
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() ) )
1523 while( ! ( msg
= (struct ObjectMsg
*) CreateIORequest( replyport
, sizeof( *msg
) ) ) )
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
);
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
:
1571 gbox
->Height
= id
->TapeDeckHeight
+ 10;
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
);
1581 case GDOMAIN_MAXIMUM
:
1583 gbox
->Height
= SHRT_MAX
;
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
;
1602 dbug( kprintf( "GM_LAYOUT\n" ); )
1604 retval
= DoSuperMethodA( cl
, o
, (Msg
) gpl
);
1606 si
->si_Flags
|= DTSIF_LAYOUT
;
1607 ObtainSemaphore( &si
->si_Lock
);
1610 NotifyAttrs( o
, gi
, 0L,
1611 GA_ID
, G( o
)->GadgetID
,
1616 struct TagItem tags
[] =
1618 {GA_ID
, G( o
)->GadgetID
},
1623 DoMethod(o
, OM_NOTIFY
, (IPTR
)tags
, (IPTR
)gi
, 0);
1628 DTA_ObjName
, (IPTR
) &name
,
1629 DTA_Domain
, (IPTR
) &domain
,
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
;
1647 if( ! GetDTAttrs( o
, DTA_Name
, (IPTR
) &name
, TAG_DONE
) || ! name
)
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
);
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
},
1682 {GA_Height
, id
->TapeDeckHeight
},
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
);
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
)
1712 SetAttrsA( id
->VolumeSlider
, ti
);
1714 DoMethodA( (Object
*) id
->VolumeSlider
, (Msg
) &member_gpl
);
1716 ReleaseSemaphore( &cb
->cb_LibLock
);
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
,
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
},
1749 DoMethod(o
, OM_NOTIFY
, (IPTR
)tags
, (IPTR
)gi
, 0);
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) )
1775 /* a big sample, speed up rendering */
1776 if( samplelength
>> 17 )
1781 /* adjust ypos and height for stereo sample */
1793 for( k
= 0; k
< (stereo
?2:1); k
++ )
1795 BYTE
*sample
= &id
->Sample
[ k
];
1797 if( k
&& id
->SampleType
== SDTST_S16S
)
1804 if( samplelength
<= w
)
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 )
1820 else if( i
>= sampleEnd
&& maxX
== ~0 )
1823 sampleStart
= ~0L; // speed up
1827 Draw( rp
, x
++, y
+ ( SMult( sample
[ c
<< shift
], h
) >> 8 ) );
1841 sub
= 2*(dy
+1); add
= 2*(dx
+1);
1843 for( i
= 0; i
< samplelength
; i
+=step
)
1847 /* get minX and maxX for highlighting */
1848 if( sampleStart
!= ~0 )
1850 if( i
>= sampleStart
&& minX
== ~0 )
1854 else if( i
>= sampleEnd
&& maxX
== ~0 )
1857 sampleStart
= ~0L; // speed up
1861 Draw( rp
, x
++, y
+ ( SMult( sample
[ i
<< shift
], h
) >> 8 ) );
1872 /* something marked ? */
1880 SetDrMd( rp
, COMPLEMENT
);
1881 RectFill( rp
, minX
, oldy
, maxX
, oldy
+oldh
-1 );
1882 /* fix tapedeck.gadget bug (?) */
1883 SetDrMd( rp
, JAM1
);
1887 /****************************************************************************/
1889 IPTR __regargs
Sound_RENDER( Class
*cl
, Object
*o
, struct gpRender
*gpr
)
1891 struct ClassBase
*cb
= (struct ClassBase
*)cl
->cl_UserData
;
1892 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
1894 dbug( kprintf( "GM_RENDER\n" ); )
1896 // if( gpr->gpr_Redraw == GREDRAW_REDRAW )
1898 struct RastPort
*rp
= gpr
->gpr_RPort
;
1899 struct ColorMap
*cm
= NULL
;
1901 LONG bgpen
=id
->BackgroundPen
, wfpen
=id
->WaveformPen
;
1902 UWORD
*pens
= gpr
->gpr_GInfo
->gi_DrInfo
->dri_Pens
;
1905 gbox
= GetAbsGadgetBox( &gpr
->gpr_GInfo
->gi_Domain
, EXTG( o
), FALSE
);
1906 x
= gbox
.Left
; y
= gbox
.Top
;
1907 w
= gbox
.Width
; h
= gbox
.Height
;
1909 if( id
->ControlPanel
)
1911 h
-= ( id
->TapeDeckHeight
+ 2 );
1914 if( ( x
!= SHRT_MAX
&& y
!= SHRT_MAX
) && ( w
>=16 && h
>= 8 ) )
1916 if( gpr
->gpr_GInfo
->gi_Screen
)
1918 cm
= gpr
->gpr_GInfo
->gi_Screen
->ViewPort
.ColorMap
;
1922 SetAPen( rp
, ( bgpen
== -1 ) ? pens
[TEXTPEN
] : bgpen
);
1923 RectFill( rp
, x
,y
, w
+x
-1, h
+y
-1 );
1928 SetAPen( rp
, ( wfpen
== -1 ) ? pens
[HIGHLIGHTTEXTPEN
] : wfpen
);
1930 DrawWaveform( cb
, rp
, id
, x
, y
, w
, h
);
1933 if( id
->ControlPanel
)
1935 /* SetAPen( rp, 4L );
1936 RectFill( rp, gbox.Left, gbox.Top+=(gbox.Height-id->TapeDeckHeight-3),
1937 gbox.Left+gbox.Width-1, gbox.Top+id->TapeDeckHeight+1 );*/
1939 if( gbox
.Height
>= ( id
->TapeDeckHeight
+ 2 ) )
1941 if( gbox
.Width
>= 201)
1943 DoMethodA( (Object
*)id
->TapeDeckGadget
, (Msg
) gpr
);
1945 if( gbox
.Width
>= 220 )
1947 DoMethodA( (Object
*) id
->VolumeSlider
, (Msg
) gpr
);
1949 if( ! cb
->cb_NoGTSlider
)
1953 if( ( img
= NewObject( NULL
, FRAMEICLASS
,
1954 IA_Left
, id
->VolumeSlider
->LeftEdge
- 4,
1955 IA_Top
, id
->VolumeSlider
->TopEdge
- 2,
1956 IA_Width
, id
->VolumeSlider
->Width
+ 8,
1957 IA_Height
, id
->TapeDeckHeight
,
1958 IA_FrameType
, FRAME_BUTTON
,
1962 DrawImageState( rp
, (struct Image
*)img
, 0,0, IDS_NORMAL
, gpr
->gpr_GInfo
->gi_DrInfo
);
1963 DisposeObject( img
);
1971 if( G( o
)->Flags
& GFLG_DISABLED
)
1973 ULONG patt
= 0x11114444;
1975 SetAfPt(rp
, (UWORD
*)&patt
, 1);
1976 SetAPen( rp
, pens
[ SHADOWPEN
] );
1977 RectFill( rp
, gbox
.Left
, gbox
.Top
, gbox
.Left
+gbox
.Width
-1, gbox
.Top
+gbox
.Height
-1 );
1978 SetAfPt( rp
, NULL
, 0L );
1981 else if( gpr->gpr_Redraw == GREDRAW_UPDATE )
1988 /****************************************************************************/
1990 IPTR __regargs
Sound_DRAW( Class
*cl
, Object
*o
, struct dtDraw
*dtd
)
1992 struct InstanceData
*id
= INST_DATA( cl
, o
);
1993 struct ClassBase
*cb
= (struct ClassBase
*) cl
->cl_UserData
;
1994 struct RastPort
*rp
= dtd
->dtd_RPort
;
1995 struct DrawInfo
*dri
;
1997 struct ColorMap
*cm
= NULL
;
1998 UWORD x
= dtd
->dtd_Left
, y
= dtd
->dtd_Top
, *pens
,
1999 w
= dtd
->dtd_Width
, h
= dtd
->dtd_Height
;
2000 WORD bgpen
= -1, wfpen
= -1;
2003 dbug( kprintf( "DTM_DRAW\n" ); )
2005 if( ( scr
= id
->Screen
) )
2007 dri
= GetScreenDrawInfo( scr
);
2018 pens
= dri
->dri_Pens
;
2022 cm
= scr
->ViewPort
.ColorMap
;
2024 ObtainSemaphoreShared( &cb
->cb_LibLock
);
2025 bgpen
= ObtainBestPenA( cm
,
2026 cb
->cb_BgCol
[0], cb
->cb_BgCol
[1], cb
->cb_BgCol
[2], NULL
);
2027 wfpen
= ObtainBestPenA( cm
,
2028 cb
->cb_WfCol
[0], cb
->cb_WfCol
[1], cb
->cb_WfCol
[2], NULL
);
2029 ReleaseSemaphore( &cb
->cb_LibLock
);
2032 SetAPen( rp
, ( bgpen
== -1 ) ? pens
[TEXTPEN
] : bgpen
);
2033 RectFill( rp
, x
,y
, w
+x
-1, h
+y
-1 );
2038 SetAPen( rp
, ( wfpen
== -1 ) ? pens
[HIGHLIGHTTEXTPEN
] : wfpen
);
2040 DrawWaveform( cb
, rp
, id
, x
, y
, w
, h
);
2044 ReleasePen( cm
, bgpen
);
2045 ReleasePen( cm
, wfpen
);
2050 FreeScreenDrawInfo( scr
, dri
);
2054 return( dri
!= NULL
);
2057 /****************************************************************************/
2059 IPTR __regargs
Sound_HITTEST( Class
*cl
, Object
*o
, struct gpHitTest
*gpht
)
2061 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
2062 IPTR retval
= GMR_GADGETHIT
;
2063 WORD h
= G(o
)->Height
;
2065 dbug( kprintf( "GM_HITTEST\n" ); )
2067 if( ! ( G( o
)->Flags
& GFLG_DISABLED
) )
2069 /* calculate absolute height */
2070 if( G(o
)->Flags
& GFLG_RELHEIGHT
)
2072 h
+= gpht
->gpht_GInfo
->gi_Domain
.Height
;
2074 /* check if one of our members was hit */
2075 if( gpht
->gpht_Mouse
.Y
> ( h
- ( id
->TapeDeckHeight
+ 3 ) ) )
2077 if( id
->ControlPanel
)
2081 domain
= GetAbsGadgetBox( &gpht
->gpht_GInfo
->gi_Domain
, EXTG( o
), FALSE
);
2083 if( ! DoMemberHitTest( &domain
, (Object
*) id
->TapeDeckGadget
, gpht
) )
2085 if( ! DoMemberHitTest( &domain
, (Object
*) id
->VolumeSlider
, gpht
) )
2094 /* We were hit, change return code if it was GM_HELPTEST */
2095 if( gpht
->MethodID
== GM_HELPTEST
)
2097 retval
= GMR_HELPHIT
;
2109 /****************************************************************************/
2111 IPTR __regargs
Sound_HANDLEINPUT( Class
*cl
, Object
*o
, struct gpInput
*gpi
)
2113 struct ClassBase
*cb
= (struct ClassBase
*) cl
->cl_UserData
;
2114 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
2115 struct InputEvent
*ie
= gpi
->gpi_IEvent
;
2116 struct DTSpecialInfo
*si
= (struct DTSpecialInfo
*)G( o
)->SpecialInfo
;
2117 struct IBox gbox
= GetAbsGadgetBox( &gpi
->gpi_GInfo
->gi_Domain
, EXTG( o
), FALSE
);
2118 IPTR retval
= GMR_MEACTIVE
;
2119 WORD mx
= gpi
->gpi_Mouse
.X
, my
= gpi
->gpi_Mouse
.Y
;
2123 dbug( kprintf("GM_GOACTIVE / GM_HANDLEINPUT\n"); )
2124 /* no input processing during layout */
2125 if( si
->si_Flags
& DTSIF_LAYOUT
)
2130 /* check if we're hit or one of our members */
2131 if( gpi
->MethodID
== GM_GOACTIVE
)
2133 G( o
)->Activation
|= GACT_ACTIVEGADGET
;
2134 G( o
)->Flags
|= GFLG_SELECTED
;
2135 /* check if mousepointer is over one of our members */
2136 if( id
->ControlPanel
)
2138 if( my
> ( gbox
.Height
- id
->TapeDeckHeight
- 3 ) )
2140 struct gpHitTest gpht
= { GM_HITTEST
, gpi
->gpi_GInfo
, {mx
, my
} };
2142 if( gbox
.Width
>= 201 && DoMemberHitTest( &gbox
, (Object
*) id
->TapeDeckGadget
, &gpht
) )
2144 id
->ActiveMember
= id
->TapeDeckGadget
;
2146 else if( gbox
.Width
>= 220 && DoMemberHitTest( &gbox
, (Object
*) id
->VolumeSlider
, &gpht
) )
2148 id
->ActiveMember
= id
->VolumeSlider
;
2151 if( ! id
->ActiveMember
)
2153 retval
= GMR_NOREUSE
;
2158 /* pass input to the active member ( if there's one ) */
2159 if( id
->ActiveMember
)
2161 struct IBox domain
= gbox
;
2163 gbox
= GetAbsGadgetBox( &gpi
->gpi_GInfo
->gi_Domain
, EXTG( id
->ActiveMember
), FALSE
);
2165 (gpi
-> gpi_Mouse
. X
) -= ((gbox
. Left
) - (domain
. Left
));
2166 (gpi
-> gpi_Mouse
. Y
) -= ((gbox
. Top
) - (domain
. Top
));
2168 if( ( retval
= DoMethodA( (Object
*) id
->ActiveMember
, (Msg
) gpi
) ) & GMR_VERIFY
)
2169 { /* tapedeck.gadget doesn't send OM_UPDATE :( */
2170 if( id
->ActiveMember
== id
->TapeDeckGadget
)
2172 if( ie
->ie_Code
== IECODE_LBUTTON
)
2176 dbug( kprintf( "TapeDeck ICSPECIAL_CODE: %04lx\n", *gpi
->gpi_Termination
); )
2178 if( *gpi
->gpi_Termination
& 0x1000 )
2184 switch( *gpi
->gpi_Termination
)
2198 CoerceMethod( cl
, o
, DTM_TRIGGER
, 0, stm
, 0 );
2204 (gpi
-> gpi_Mouse
. X
) += ((gbox
. Left
) - (domain
. Left
));
2205 (gpi
-> gpi_Mouse
. Y
) += ((gbox
. Top
) - (domain
. Top
));
2208 else if( retval
== GMR_MEACTIVE
)
2212 if( ie
->ie_Class
== IECLASS_RAWMOUSE
)
2214 /* test for mark mode */
2215 if( si
->si_Flags
& DTSIF_DRAGSELECT
)
2217 struct RastPort
*rp
;
2218 WORD mx
= gpi
->gpi_Mouse
.X
, x
, y
, w
, h
;
2220 x
= gbox
.Left
; y
= gbox
.Top
+ 2;
2221 w
= gbox
.Width
- 8; h
= gbox
.Height
- 4;
2223 if( id
->ControlPanel
)
2225 h
-= ( id
->TapeDeckHeight
+ 2 );
2239 if( id
->MaxX
!= (x
+mx
) )
2241 if( ( rp
= ObtainGIRPort( gpi
->gpi_GInfo
) ) )
2245 SetDrMd( rp
, COMPLEMENT
);
2256 RectFill( rp
, minX
, y
, maxX
, y
+h
-1 );
2268 RectFill( rp
, minX
, y
, maxX
, y
+h
-1 );
2269 /* fixes a bug (?) of tapedeck.gadget */
2270 SetDrMd( rp
, JAM1
);
2272 ReleaseGIRPort( rp
);
2276 /* start mark mode */
2277 else if( ie
->ie_Code
== IECODE_LBUTTON
)
2279 if( id
->MinX
!= ~0 )
2281 DoMethod( o
, DTM_CLEARSELECTED
, (IPTR
) gpi
->gpi_GInfo
);
2284 id
->MarkMode
= TRUE
;
2290 /* not in mark mode - start or stop playing */
2291 else if( ie
->ie_Code
== IECODE_LBUTTON
)
2293 struct timeval tv
= gpi
->gpi_IEvent
->ie_TimeStamp
;
2294 STATIC ULONG stm
[] = { STM_PLAY
, STM_STOP
};
2296 CoerceMethod( cl
, o
, DTM_TRIGGER
, 0, stm
[ DoubleClick( id
->LastClick
.tv_secs
, id
->LastClick
.tv_micro
, tv
.tv_secs
, tv
.tv_micro
) ], 0L );
2301 if( ie
->ie_Code
== SELECTUP
)
2303 retval
= GMR_NOREUSE
;
2308 ie
= ie
->ie_NextEvent
;
2315 /****************************************************************************/
2317 IPTR __regargs
Sound_GOINACTIVE( Class
*cl
, Object
*o
, struct gpGoInactive
*gpgi
)
2319 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
2320 struct ClassBase
*cb
= (struct ClassBase
*) cl
->cl_UserData
;
2324 DoSuperMethodA( cl
, o
, (Msg
) gpgi
);
2326 dbug( kprintf("GOINACTIVE\n"); )
2328 if( id
->ActiveMember
)
2330 DoMethodA( (Object
*) id
->ActiveMember
, (Msg
) gpgi
);
2331 id
->ActiveMember
= NULL
;
2334 id
->MarkMode
= FALSE
;
2336 G( o
)->Activation
&= ~GACT_ACTIVEGADGET
;
2337 G( o
)->Flags
&= ~GFLG_SELECTED
;
2342 /****************************************************************************/
2344 IPTR __regargs
Sound_TRIGGER( Class
*cl
, Object
*o
, struct dtTrigger
*dtt
)
2346 struct ClassBase
*cb
= (struct ClassBase
*)cl
->cl_UserData
;
2347 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
2353 dbug( kprintf("DTM_TRIGGER\n"); )
2355 switch( dtt
->dtt_Function
)
2358 dbug( kprintf( "STM_PLAY\n" ); )
2364 dbug( kprintf( "STM_STOP\n" ); )
2369 dbug( kprintf( "STM_PAUSE\n" ); )
2370 cmd
= COMMAND_PAUSE
;
2376 SendObjectMsg( id
, cmd
, data
);
2382 /****************************************************************************/
2383 // "stolen" from embeddt
2384 IPTR __regargs
DoMemberHitTest( struct IBox
*domain
, Object
*member
, struct gpHitTest
*gpht
)
2386 struct GadgetInfo
*gi
= gpht
-> gpht_GInfo
;
2390 gbox
= GetAbsGadgetBox( &gi
->gi_Domain
, EXTG( member
), (BOOL
) ( gpht
-> MethodID
== GM_HELPTEST
) );
2392 (gpht
->gpht_Mouse
.X
) -= ((gbox
.Left
) - (domain
->Left
));
2393 (gpht
->gpht_Mouse
.Y
) -= ((gbox
.Top
) - (domain
->Top
));
2395 /* Mouse coordinates must be inside members's select box */
2396 if( ((gpht
->gpht_Mouse
. X
) >= 0) &&
2397 ((gpht
->gpht_Mouse
. Y
) >= 0) &&
2398 ((gpht
->gpht_Mouse
. X
) <= (gbox
.Width
)) &&
2399 ((gpht
->gpht_Mouse
. Y
) <= (gbox
.Height
)) )
2401 retval
= DoMethodA( member
, (Msg
)gpht
);
2404 (gpht
->gpht_Mouse
.X
) += ((gbox
.Left
) - (domain
->Left
));
2405 (gpht
->gpht_Mouse
.Y
) += ((gbox
.Top
) - (domain
->Top
));
2410 /****************************************************************************/
2412 struct IBox __regargs
GetAbsGadgetBox( struct IBox
*domain
, struct ExtGadget
*g
, BOOL useBounds
)
2414 struct IBox retbox
= { 0, 0, 0, 0 };
2418 if( ((g
->MoreFlags
) & GMORE_BOUNDS
) && useBounds
)
2420 retbox
= *((struct IBox
*)(&(g
->BoundsLeftEdge
)));
2424 retbox
= *(GADGET_BOX( g
));
2427 if( (g
->Flags
) & GFLG_RELBOTTOM
)
2429 (retbox
.Top
) += ((domain
->Top
) + (domain
->Height
));
2432 if( (g
->Flags
) & GFLG_RELRIGHT
)
2434 (retbox
.Left
) += ((domain
->Left
) + (domain
->Width
));
2437 if( (g
->Flags
) & GFLG_RELWIDTH
)
2439 (retbox
.Width
) += (domain
->Width
);
2442 if( (g
->Flags
) & GFLG_RELHEIGHT
)
2444 (retbox
.Height
) += (domain
->Height
);
2451 /****************************************************************************/
2453 void __regargs
makeqtab( BYTE
*qtab
)
2457 for( i
=0; i
< 512; i
++ )
2462 for ( i
= 1; i
< 16; i
++ )
2464 LONG j
= 256 + fibtab
[i
],
2465 k
= 256 + fibtab
[i
-1];
2484 /****************************************************************************/
2486 LONG __regargs
WriteChunk( struct ClassBase
*cb
, struct IFFHandle
*iff
, ULONG type
, ULONG id
, APTR data
, ULONG size
)
2490 if( ! ( err
= PushChunk( iff
, type
, id
, size
) ) )
2492 if( ( err
= WriteChunkBytes( iff
, data
, size
) ) == size
)
2494 err
= PopChunk( iff
);
2501 /****************************************************************************/
2503 LONG __regargs
WriteAIFF( struct ClassBase
*cb
, Object
*o
, struct IFFHandle
*iff
, struct InstanceData
*id
)
2507 if( ! ( err
= PushChunk( iff
, ID_AIFF
, ID_FORM
, IFFSIZE_UNKNOWN
) ) )
2510 UBYTE sampleType
= id
->SampleType
;
2511 ULONG sampleLength
= id
->SampleLength
;
2512 BYTE
*sample
= id
->Sample
;
2514 if( id
->StartSample
!= ~0 )
2516 sample
= &sample
[ UMult32( id
->StartSample
, bytesPerPoint
[ sampleType
] ) ];
2517 sampleLength
= id
->EndSample
- id
->StartSample
;
2520 common
.numChannels
= ( sampleType
& 1 ) + 1;
2521 common
.numSampleFrames
= sampleLength
;
2522 common
.sampleSize
= ( sampleType
>= SDTST_M16S
) ? 16 : 8;
2523 ulong2extended( id
->Frequency
, &common
.sampleRate
);
2525 if( ! ( err
= WriteChunk( cb
, iff
, ID_AIFF
, ID_COMM
, &common
, sizeof( common
) ) ) )
2527 SampledSoundHeader ssnd
= { 0L, 0L };
2529 if( ! ( err
= PushChunk( iff
, ID_AIFF
, ID_SSND
, IFFSIZE_UNKNOWN
) ) )
2531 if( ( err
= WriteChunkBytes( iff
, &ssnd
, sizeof( ssnd
) ) ) == sizeof( ssnd
) )
2533 ULONG bytes
= UMult32( sampleLength
, bytesPerPoint
[ sampleType
] );
2535 if( ( err
= WriteChunkBytes( iff
, sample
, bytes
) ) == bytes
)
2537 err
= PopChunk( iff
);
2545 err
= PopChunk( iff
);
2552 /****************************************************************************/
2554 LONG __regargs
WriteSVX( struct ClassBase
*cb
, Object
*o
, struct IFFHandle
*iff
, struct InstanceData
*id
)
2556 UBYTE sampletype
= id
->SampleType
, bps
= ( sampletype
>= SDTST_M16S
? 2 : 1 );
2557 BOOL stereo
= IsStereo( id
->SampleType
);
2558 LONG err
, type
= ( sampletype
>= SDTST_M16S
? ID_16SV
: ID_8SVX
);
2559 ULONG sampleLength
= id
->SampleLength
;
2560 BYTE
*sample
= id
->Sample
;
2561 struct VoiceHeader vhdr
;
2563 CopyMem( &id
->VoiceHeader
, &vhdr
, sizeof( vhdr
) );
2564 vhdr
.vh_Compression
= ( ( id
->VoiceHeader
.vh_Compression
== CMP_FIBDELTA
) || ( cb
->cb_Compress
) ) && ( sampletype
<= SDTST_S8S
);
2566 if( id
->StartSample
!= ~0 )
2568 sample
= &sample
[ UMult( id
->StartSample
, bytesPerPoint
[ sampletype
] ) ];
2569 sampleLength
= id
->EndSample
- id
->StartSample
;
2570 vhdr
.vh_OneShotHiSamples
= sampleLength
;
2571 vhdr
.vh_RepeatHiSamples
= 0L;
2574 if( ! ( err
= PushChunk( iff
, type
, ID_FORM
, IFFSIZE_UNKNOWN
) ) )
2576 if( ! ( err
= WriteChunk( cb
, iff
, type
, ID_VHDR
, &vhdr
, sizeof( vhdr
) ) ) )
2584 {DTA_ObjName
, ID_NAME
, NULL
},
2585 {DTA_ObjAnnotation
, ID_ANNO
, NULL
},
2586 {DTA_ObjAuthor
, ID_AUTH
, NULL
},
2587 {DTA_ObjCopyright
, ID_Copyright
, NULL
},
2588 {DTA_ObjVersion
, ID_FVER
, NULL
},
2593 for( i
= 0; ObjData
[i
].attr
; i
++ )
2595 struct ObjectData
*od
= &ObjData
[i
];
2597 if( GetDTAttrs( o
, od
->attr
, (IPTR
) &od
->data
, TAG_DONE
) && od
->data
)
2599 if( ( err
= WriteChunk( cb
, iff
, type
, od
->id
, od
->data
, StrLen( od
->data
) ) ) )
2611 err
= WriteChunk( cb
, iff
, type
, ID_CHAN
, &chan
, sizeof( ULONG
) );
2615 ULONG pan
= 0x10000 - id
->Panning
;
2616 err
= WriteChunk( cb
, iff
, type
, ID_PAN
, &pan
, sizeof( ULONG
) );
2622 if( vhdr
.vh_Compression
== CMP_FIBDELTA
)
2627 buffersize
= sampleLength
;
2629 while( ! ( buf
= AllocVec( buffersize
+ 512L, MEMF_PUBLIC
) ) )
2631 if( ( buffersize
/= 2 ) < 1024L )
2639 if( ! ( err
= PushChunk( iff
, type
, ID_BODY
, IFFSIZE_UNKNOWN
) ) )
2643 qtab
= &buf
[buffersize
];
2646 for( i
= 0; i
< (stereo
?2:1) && !err
; i
++ )
2648 LONG length
= sampleLength
, samples
= 0L;
2649 BYTE c0
= 0, *src
= &sample
[i
], add
= stereo
?2:1;
2666 c0
+= fibtab
[ n
= qtab
[256+(*src
-c0
)] ];
2672 buf
[samples
++] = o
| n
;
2679 if( samples
== buffersize
|| length
== 0L )
2681 if( ( err
= WriteChunkBytes( iff
, buf
, samples
) ) != samples
)
2692 err
= PopChunk( iff
);
2700 err
= ERROR_NO_FREE_STORE
;
2704 ** write uncompressed svx file
2709 ** create a stereo BODY
2713 if( ! ( err
= PushChunk( iff
, type
, ID_BODY
, IFFSIZE_UNKNOWN
) ) )
2716 LONG bufsize
= sampleLength
;
2718 while( ! ( buf
= AllocVec( UMult( bufsize
, bps
), MEMF_PUBLIC
) ) )
2720 if( ( bufsize
/= 2 ) < 1024L )
2730 for( i
= 0; i
< 2 && ! err
; i
++, sample
+=bps
)
2732 LONG samples
= bufsize
, length
= sampleLength
;
2737 ULONG bytes
= UMult( samples
, bps
);
2739 if( sampletype
== SDTST_S16S
)
2741 WORD
*dst
= (WORD
*)buf
,
2742 *src_p
= (WORD
*)src
;
2745 for( c
= samples
; c
; c
--, src_p
+=2 )
2750 src
= (BYTE
*) src_p
;
2757 for( c
= samples
; c
; c
--, src
+=2 )
2763 if( ( err
= WriteChunkBytes( iff
, buf
, bytes
) ) != bytes
)
2768 if( (length
-=samples
) < samples
)
2780 err
= ERROR_NO_FREE_STORE
;
2785 err
= PopChunk( iff
);
2790 ** write uncompressed mono sample
2794 err
= WriteChunk( cb
, iff
, type
, ID_BODY
, sample
, UMult( sampleLength
, bps
) );
2802 err
= PopChunk( iff
);
2809 /****************************************************************************/
2811 IPTR __regargs
Sound_WRITE( Class
*cl
, Object
*o
, struct dtWrite
*dtw
)
2813 struct ClassBase
*cb
= (struct ClassBase
*)cl
->cl_UserData
;
2814 struct InstanceData
*id
= (struct InstanceData
*) INST_DATA( cl
, o
);
2815 struct IFFHandle
*iff
;
2816 struct SignalSemaphore
*lock
= &((struct DTSpecialInfo
*)G( o
)->SpecialInfo
)->si_Lock
;
2819 dbug( kprintf( "DTM_WRITE / DTM_COPY\n" ); )
2821 ObtainSemaphoreShared( &cb
->cb_LibLock
);
2825 ObtainSemaphoreShared( lock
);
2827 if( ( iff
= AllocIFF() ) )
2829 if( dtw
->MethodID
== DTM_WRITE
)
2831 dbug( kprintf( "DTWM_RAW\n" ); )
2833 if( ( iff
->iff_Stream
= (IPTR
)dtw
->dtw_FileHandle
) )
2835 InitIFFasDOS( iff
);
2839 dbug( kprintf( "NULL filehandle\n"); )
2840 err
= ERROR_INVALID_LOCK
;
2845 dbug( kprintf( "DTM_COPY\n" ); )
2847 if( ( iff
->iff_Stream
= (IPTR
) OpenClipboard( PRIMARY_CLIP
) ) )
2849 InitIFFasClip( iff
);
2853 dbug( kprintf( "Cant open clipboard\n" ); )
2854 err
= ERROR_OBJECT_IN_USE
;
2860 if( ( err
= OpenIFF( iff
, IFFF_WRITE
) ) )
2862 err
= ifferr2doserr
[-err
-1];
2863 dbug( kprintf( "OpenIFF() failed\n" ); )
2869 err
= ERROR_NO_FREE_STORE
;
2870 dbug( kprintf( "AllocIFF failed\n" ); )
2875 dbug( kprintf( "Everything fine so far ...\n" ); )
2877 if( id
->SampleType
>= SDTST_M16S
&& cb
->cb_AIFF
)
2879 err
= WriteAIFF( cb
, o
, iff
, id
);
2883 err
= WriteSVX( cb
, o
, iff
, id
);
2888 err
= ifferr2doserr
[-err
-1];
2893 dbug( kprintf( "Something failed\n" ); )
2896 dbug( kprintf( "closing iff stream\n" ); )
2900 if( dtw
->MethodID
== DTM_COPY
)
2902 CloseClipboard( (struct ClipboardHandle
*)iff
->iff_Stream
);
2907 ReleaseSemaphore( lock
);
2911 err
= ERROR_REQUIRED_ARG_MISSING
;
2914 ReleaseSemaphore( &cb
->cb_LibLock
);
2917 return( err
? FALSE
: TRUE
);
2920 /****************************************************************************/
2923 ** test if dblscan screenmode
2924 ** taken from the ahi paula driver by Martin Blom
2927 BOOL
Is31Khz( struct ClassBase
*cb
)
2933 extern struct Library
*GfxBase
, *IntuitionBase
;
2935 if( ((struct GfxBase
*)GfxBase
)->ChipRevBits0
& ( GFXF_HR_DENISE
|GFXF_AA_LISA
) )
2938 if( ((struct GfxBase
*)cb
->cb_GfxBase
)->ChipRevBits0
& ( GFXF_HR_DENISE
|GFXF_AA_LISA
) )
2939 #define GfxBase cb->cb_GfxBase
2944 lock
= LockIBase( 0L );
2946 modeid
= GetVPModeID( & ((struct IntuitionBase
*)IntuitionBase
)->FirstScreen
->ViewPort
);
2948 #undef IntuitionBase
2949 modeid
= GetVPModeID( & ((struct IntuitionBase
*)cb
->cb_IntuitionBase
)->FirstScreen
->ViewPort
);
2950 #define IntuitionBase cb->cb_IntuitionBase
2952 UnlockIBase( lock
);
2955 if( modeid
& 0x40000000 )
2958 if( FindTask( "Picasso96" ) )
2964 if( GetVar( "Picasso96/AmigaVideo", buf
, sizeof( buf
), GVF_GLOBAL_ONLY
) )
2966 if( ! Strnicmp( buf
, "31Khz" , 5L ) )
2975 struct copinit
*ci
= ((struct GfxBase
*)GfxBase
)->copinit
;
2978 struct copinit
*ci
= ((struct GfxBase
*)cb
->cb_GfxBase
)->copinit
;
2979 #define GfxBase cb->cb_GfxBase
2983 if( ( ci
->fm0
[ 0 ] != 0x01fc ) || ( ci
->fm0
[ 1 ] & 0xc000 ) )
2992 struct MonitorInfo moni
;
2994 if( GetDisplayInfoData( NULL
, (UBYTE
*) &moni
, sizeof( moni
), DTAG_MNTR
, modeid
) )
2996 if( moni
.TotalColorClocks
* moni
.TotalRows
/ ( 2 * ( moni
.TotalRows
- moni
.MinRow
+ 1 ) ) <= 64 )
3007 /****************************************************************************/
3009 void __regargs
CalcPanVol( UWORD overall
, ULONG pan
, UWORD
*leftvol
, UWORD
*rightvol
)
3011 pan
= ( pan
<< 6 ) >> 16;
3012 *rightvol
= pan
? overall
/ ( 64 / pan
) : 0;
3013 *leftvol
= overall
- *rightvol
;
3016 /****************************************************************************/
3018 void __regargs
RemoveRequest( struct IORequest
*ior
)
3020 #if !defined(__MAXON__) && !defined(__AROS__)
3022 struct Library
*SysBase
= (*(struct Library
**)4L);
3024 struct Node
*ln
, *succ
;
3027 for( ln
= ior
->io_Message
.mn_ReplyPort
->mp_MsgList
.lh_Head
;
3028 (succ
= ln
->ln_Succ
); ln
= succ
)
3030 if( ln
== &ior
->io_Message
.mn_Node
)
3033 SetSignal( 0L, 1L << ior
->io_Message
.mn_ReplyPort
->mp_SigBit
);
3038 #if !defined(__MAXON__) && !defined(__AROS__)
3040 #define SysBase cb->cb_SysBase
3044 /****************************************************************************/
3046 #define LEFT_CHANNEL_0 1
3047 #define RIGHT_CHANNEL_1 2
3048 #define RIGHT_CHANNEL_2 4
3049 #define LEFT_CHANNEL_3 8
3050 #define MAX_SAMPLE 131072
3051 #define MAX_SAMPLE_RATE 28867
3052 #define LEFT_MASK (LEFT_CHANNEL_0|LEFT_CHANNEL_3)
3053 #define RIGHT_MASK (RIGHT_CHANNEL_1|RIGHT_CHANNEL_2)
3064 /****************************************************************************/
3066 void __regargs
SetTDMode( struct ClassBase
*cb
, struct InstanceData
*id
, ULONG mode
)
3068 if( id
->ControlPanel
)
3070 IPTR oldmode
= mode
;
3072 ObtainSemaphoreShared( &id
->Lock
);
3074 /* avoid deadlocks */
3075 GetAttr( TDECK_Mode
, (Object
*)id
->TapeDeckGadget
, &oldmode
);
3076 if( oldmode
!= mode
)
3078 SetGadgetAttrs( id
->TapeDeckGadget
, id
->Window
, id
->Requester
,
3079 TDECK_Mode
, mode
, TAG_DONE
);
3082 ReleaseSemaphore( &id
->Lock
);
3086 /****************************************************************************/
3088 void PlayerProc( void )
3090 #if !defined(__MAXON__) && !defined(__AROS__)
3092 struct Library
*SysBase
= *(struct Library
**)4L;
3094 struct Process
*pr
= (struct Process
*) FindTask( NULL
);
3095 struct MsgPort
*mp
, *mpaudio
= NULL
;
3096 struct IOAudio
*ioaudio
[NUM_REQUESTS
] = { };
3097 struct ClassBase
*cb
;
3098 struct InstanceData
*id
;
3099 LONG numChAllocated
, samples
, buffersize
, length
, cycles
,
3100 loops
, audiompmsk
= 0, mpmsk
;
3101 BOOL releaseAudio
= FALSE
, restart
, paused
= FALSE
;
3102 BYTE
*sample
, *buffer
[4] = {};
3104 mp
= &pr
->pr_MsgPort
;
3105 mpmsk
= 1L << mp
->mp_SigBit
;
3107 dbug( kprintf("child process launched\n"); )
3111 struct ObjectMsg
*msg
;
3114 rcv
= Wait( mpmsk
| audiompmsk
);
3118 while( ( msg
= (struct ObjectMsg
*) GetMsg( mp
) ) )
3120 switch( msg
->Command
)
3122 case COMMAND_NEXT_BUFFER
:
3125 ObtainSemaphoreShared( &id
->Lock
);
3126 sample
= id
->Sample
;
3127 length
= id
->SampleLength
;
3128 samples
= ( length
> buffersize
) ? buffersize
: length
;
3130 ReleaseSemaphore( &id
->Lock
);
3135 dbug( kprintf( "child/COMMAND_INIT\n"); )
3137 id
= (struct InstanceData
*) msg
->Data
;
3140 if( ! ( msg
->Data
= mp
= CreateMsgPort() ) )
3142 ReplyMsg( &msg
->Message
);
3146 mpmsk
= 1L << mp
->mp_SigBit
;
3151 dbug( kprintf( "child/COMMAND_EXIT or STOP\n"); )
3157 SetTDMode( cb
, id
, BUT_STOP
);
3159 for( i
= AUDIO_LEFT
; i
< NUM_REQUESTS
; i
++ )
3161 struct IORequest
*ioa
= (struct IORequest
*) ioaudio
[ i
];
3163 if( CheckIO( ioa
) )
3165 RemoveRequest( ioa
);
3174 CloseDevice( (struct IORequest
*) ioaudio
[ AUDIO_CONTROL
] );
3175 DeleteMsgPort( mpaudio
);
3177 FreeVec( ioaudio
[ AUDIO_CONTROL
] );
3178 FreeVec( buffer
[0] ); buffer
[0] = NULL
;
3179 releaseAudio
= FALSE
;
3182 if( msg
->Command
== COMMAND_EXIT
)
3185 ReplyMsg( &msg
->Message
);
3186 DeleteMsgPort( mp
);
3191 case COMMAND_PERVOL
:
3193 dbug( kprintf( "child/COMMAND_PERVOL\n"); )
3197 struct IOAudio
*ioa
= ioaudio
[ AUDIO_CONTROL
];
3199 ObtainSemaphoreShared( &id
->Lock
);
3201 if( numChAllocated
== 1L || IsStereo( id
->SampleType
) )
3203 ioa
->ioa_Period
= Freq2Period( id
->Frequency
);
3204 ioa
->ioa_Volume
= id
->Volume
;
3205 ioa
->ioa_Request
.io_Flags
= 0;
3206 ioa
->ioa_Request
.io_Command
= ADCMD_PERVOL
;
3207 DoIO( &ioa
->ioa_Request
);
3210 ioaudio
[ AUDIO_LEFT
]->ioa_Volume
=
3211 ioaudio
[ AUDIO_LEFT2
]->ioa_Volume
=
3212 ioaudio
[ AUDIO_RIGHT
]->ioa_Volume
=
3213 ioaudio
[ AUDIO_RIGHT2
]->ioa_Volume
= id
->Volume
;
3218 UWORD leftvol
, rightvol
;
3219 ULONG oldmask
= (ULONG
) ioa
->ioa_Request
.io_Unit
;
3221 CalcPanVol( id
->Volume
, id
->Panning
, &leftvol
, &rightvol
);
3223 ioa->ioa_Request.io_Command = CMD_STOP;
3224 DoIO( &ioa->ioa_Request );*/
3226 ioa
->ioa_Request
.io_Unit
= (struct Unit
*) ( oldmask
& LEFT_MASK
);
3227 ioa
->ioa_Period
= Freq2Period( id
->Frequency
);
3228 ioa
->ioa_Volume
= leftvol
;
3229 ioa
->ioa_Request
.io_Flags
= 0;
3230 ioa
->ioa_Request
.io_Command
= ADCMD_PERVOL
;
3231 DoIO( &ioa
->ioa_Request
);
3233 ioa
->ioa_Request
.io_Unit
= (struct Unit
*) ( oldmask
& RIGHT_MASK
);
3234 ioa
->ioa_Period
= Freq2Period( id
->Frequency
);
3235 ioa
->ioa_Volume
= rightvol
;
3236 ioa
->ioa_Request
.io_Flags
= 0;
3237 ioa
->ioa_Request
.io_Command
= ADCMD_PERVOL
;
3238 DoIO( &ioa
->ioa_Request
);
3240 ioa
->ioa_Request
.io_Unit
= (struct Unit
*) oldmask
;
3243 ioaudio
[ AUDIO_LEFT
]->ioa_Volume
=
3244 ioaudio
[ AUDIO_LEFT2
]->ioa_Volume
= leftvol
;
3245 ioaudio
[ AUDIO_RIGHT
]->ioa_Volume
=
3246 ioaudio
[ AUDIO_RIGHT2
]->ioa_Volume
= rightvol
;
3250 ioa->ioa_Request.io_Command = CMD_START;
3251 DoIO( &ioa->ioa_Request );*/
3255 ioaudio
[ AUDIO_LEFT
]->ioa_Period
=
3256 ioaudio
[ AUDIO_LEFT2
]->ioa_Period
=
3257 ioaudio
[ AUDIO_RIGHT
]->ioa_Period
=
3258 ioaudio
[ AUDIO_RIGHT2
]->ioa_Period
= Freq2Period( id
->Frequency
);
3261 ReleaseSemaphore( &id
->Lock
);
3268 dbug( kprintf( "child/COMMAND_PAUSE\n"); )
3274 ioaudio
[ AUDIO_CONTROL
]->ioa_Request
.io_Command
= CMD_STOP
;
3275 DoIO( &ioaudio
[ AUDIO_CONTROL
]->ioa_Request
);
3284 dbug( kprintf( "child/COMMAND_PLAY\n"); )
3286 ObtainSemaphoreShared( &id
->Lock
);
3300 for( i
= AUDIO_LEFT
; i
< NUM_REQUESTS
; i
++ )
3302 struct IORequest
*ioa
= &ioaudio
[ i
]->ioa_Request
;
3304 if( CheckIO( ioa
) )
3306 RemoveRequest( ioa
);
3315 sample
= id
->Sample
;
3316 length
= id
->SampleLength
;
3317 samples
= buffersize
;
3318 if( length
<= buffersize
)
3321 cycles
= id
->Cycles
;
3333 LEFT_CHANNEL_0
| RIGHT_CHANNEL_1
,
3334 LEFT_CHANNEL_3
| RIGHT_CHANNEL_2
,
3335 LEFT_CHANNEL_0
, LEFT_CHANNEL_3
,
3336 RIGHT_CHANNEL_1
, RIGHT_CHANNEL_2
3338 struct IOAudio
*ioa
;
3341 if( ! id
->Sample
|| ! id
->SampleLength
)
3346 dbug( kprintf( "child/allocating requests\n" ); )
3348 /*- allocate requests and msgport -*/
3349 if( ! ( ioa
= AllocVec( sizeof( *ioa
) * NUM_REQUESTS
, MEMF_PUBLIC
|MEMF_CLEAR
) ) ||
3350 ! ( mpaudio
= CreateMsgPort() ) )
3353 SetTDMode( cb
, id
, BUT_STOP
);
3357 for( i
= 0; i
< NUM_REQUESTS
; i
++ )
3362 audiompmsk
= 1L << mpaudio
->mp_SigBit
;
3364 /*- Open audio.device and intialize requests -*/
3365 ioa
= ioaudio
[ AUDIO_CONTROL
];
3366 ioa
->ioa_Request
.io_Message
.mn_ReplyPort
= mpaudio
;
3367 ioa
->ioa_Request
.io_Message
.mn_Length
= sizeof( *ioa
);
3369 ioa
->ioa_Data
= ChMap
;
3370 ioa
->ioa_Length
= sizeof( ChMap
);
3372 if( ! OpenDevice( "audio.device", 0L, (struct IORequest
*) ioa
, 0L ) )
3374 /*- make CheckIO() work -*/
3375 ioa
->ioa_Request
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
3377 for( i
= 1; i
< NUM_REQUESTS
; i
++ )
3379 CopyMem( ioa
, ioaudio
[i
], sizeof( *ioa
) );
3382 for( i
= 0; i
< sizeof( ChMap
); i
++ )
3384 if( (ULONG
) ioa
->ioa_Request
.io_Unit
== (ULONG
) ChMap
[i
] )
3392 dbug( kprintf( "child/got two stereo channels\n" ); )
3393 numChAllocated
= 2L;
3394 /*- stop device in order to sync stereo channels -*/
3395 ioa
->ioa_Request
.io_Command
= CMD_STOP
;
3396 DoIO( &ioa
->ioa_Request
);
3401 dbug( kprintf( "child/got only one channel\n" ); )
3402 numChAllocated
= 1L;
3406 ioaudio
[ AUDIO_LEFT
]->ioa_Request
.io_Unit
=
3407 ioaudio
[ AUDIO_LEFT2
]->ioa_Request
.io_Unit
= (struct Unit
*) ( (ULONG
) ioa
->ioa_Request
.io_Unit
& LEFT_MASK
);
3408 ioaudio
[ AUDIO_RIGHT
]->ioa_Request
.io_Unit
=
3409 ioaudio
[ AUDIO_RIGHT2
]->ioa_Request
.io_Unit
= (struct Unit
*) ( (ULONG
) ioa
->ioa_Request
.io_Unit
& RIGHT_MASK
);
3411 sample
= id
->Sample
;
3412 length
= id
->SampleLength
;
3414 if( ( id
->SampleType
== SDTST_M8S
) && ( TypeOfMem( sample
) & MEMF_CHIP
) )
3416 buffersize
= samples
= ( length
> MAX_SAMPLE
) ? MAX_SAMPLE
: length
;
3417 dbug( kprintf( "child/chip sample\n" ); )
3419 /*- allocate buffers -*/
3422 ObtainSemaphoreShared( &cb
->cb_LibLock
); /* determine buffersize, don't go below 1k (heavy system load) */
3423 buffersize
= ( length
> cb
->cb_BufferSize
) ? cb
->cb_BufferSize
: ( ((length
+1)/2) < 1024L ? length
: (length
+1)/2 );
3424 ReleaseSemaphore( &cb
->cb_LibLock
);
3426 while( ! ( buffer
[0] = AllocVec( buffersize
<< numChAllocated
, MEMF_CHIP
) ) )
3428 dbug( kprintf( "child/failed to allocate %ld bytes of buffer\n", buffersize
); )
3429 if( (buffersize
/= 2) < 1024L )
3435 samples
= buffersize
;
3437 dbug( kprintf( "child/Buffer at %08lx, size %ld, num %ld\n", buffer
[0], buffersize
, numChAllocated
*2 ); )
3439 if( buffer
[0] == NULL
)
3441 CloseDevice( (struct IORequest
*) ioa
);
3442 DeleteMsgPort( mpaudio
);
3445 SetTDMode( cb
, id
, BUT_STOP
);
3449 for( i
= 1; i
< 4; i
++ )
3451 buffer
[ i
] = buffer
[ i
-1 ] + buffersize
;
3455 if( buffersize
<= length
)
3457 cycles
= id
->Cycles
;
3466 dbug( kprintf( "child/Sample: %08lx, Length: %ld, Cycles: %ld, Loops: %ld, Freq: %ld\n", sample
, length
, cycles
, loops
, id
->Frequency
); )
3468 releaseAudio
= TRUE
;
3470 SetTDMode( cb
, id
, BUT_PLAY
);
3474 dbug( kprintf("child/can't open audio.device\n"); )
3475 DeleteMsgPort( mpaudio
);
3478 SetTDMode( cb
, id
, BUT_STOP
);
3482 ReleaseSemaphore( &id
->Lock
);
3487 if( msg
->Message
.mn_ReplyPort
)
3489 ReplyMsg( &msg
->Message
);
3498 if( rcv
& audiompmsk
)
3500 ObtainSemaphoreShared( &id
->Lock
);
3507 dbug( kprintf( "child/reachend end of sample\n" ); )
3509 /*- wait for any outstanding request -*/
3510 for( i
= AUDIO_LEFT
; i
< NUM_REQUESTS
; i
++ )
3512 struct IORequest
*ioa
= &ioaudio
[i
]->ioa_Request
;
3514 if( ! CheckIO( ioa
) )
3516 /* don't block doing WaitIO() */
3521 RemoveRequest( ioa
);
3525 if( ! Done
|| id
->Continuous
)
3527 ReleaseSemaphore( &id
->Lock
);
3531 if( id
->Repeat
|| ( --loops
> 0L ) )
3533 dbug( kprintf( "child/%ld loops to go\n", loops
); )
3535 sample
= id
->Sample
;
3536 length
= id
->SampleLength
;
3537 samples
= buffersize
;
3538 /*- stop device in order to sync stereo channels -*/
3539 if( numChAllocated
== 2L )
3541 ioaudio
[ AUDIO_CONTROL
]->ioa_Request
.io_Command
= CMD_STOP
;
3542 DoIO( &ioaudio
[ AUDIO_CONTROL
]->ioa_Request
);
3552 dbug( kprintf("child/cleanup\n"); )
3555 CloseDevice( &ioaudio
[AUDIO_CONTROL
]->ioa_Request
);
3556 FreeVec( buffer
[0] ); buffer
[0] = NULL
;
3557 FreeVec( ioaudio
[ AUDIO_CONTROL
] );
3558 DeleteMsgPort( mpaudio
); audiompmsk
= 0L;
3559 releaseAudio
= FALSE
;
3561 SetTDMode( cb
, id
, BUT_STOP
);
3563 if( id
->SignalTask
&& id
->SignalBit
!= -1 )
3565 Signal( id
->SignalTask
, 1L << id
->SignalBit
);
3573 UWORD volleft
, volright
;
3575 if( numChAllocated
== 1L || IsStereo( id
->SampleType
) )
3578 volleft
= id
->Volume
;
3582 CalcPanVol( id
->Volume
, id
->Panning
, &volleft
, &volright
);
3585 /*- we work doublebuffered -*/
3586 for( i
= 0; i
< 2; i
++ )
3588 struct IOAudio
*ioa_left
= ioaudio
[ i
+ AUDIO_LEFT
],
3589 *ioa_right
= ioaudio
[ i
+ AUDIO_RIGHT
];
3591 /*- get free audiorequest -*/
3592 if( CheckIO( (struct IORequest
*) ioa_left
) && CheckIO( (struct IORequest
*) ioa_right
) )
3594 BYTE
*data_left
, *data_right
;
3596 dbug( kprintf( "child/Request pair #%ld is free\n", i
); )
3598 RemoveRequest( (struct IORequest
*) ioa_left
);
3599 RemoveRequest( (struct IORequest
*) ioa_right
);
3603 if( IsStereo( id
->SampleType
) )
3605 LONG c
, add
= ( id
->SampleType
== SDTST_S16S
) ? 2 : 1;
3607 if( numChAllocated
== 2L )
3609 BYTE
*buf_left
= buffer
[ i
* 2 ],
3610 *buf_right
= buffer
[ i
* 2 + 1 ];
3612 data_left
= buf_left
;
3613 data_right
= buf_right
;
3615 for( c
= samples
; c
; c
-- )
3617 *buf_left
++ = *sample
; sample
+= add
;
3618 *buf_right
++ = *sample
; sample
+= add
;
3623 BYTE
*buf
= buffer
[ i
];
3628 for( c
= samples
; c
; c
--, sample
+=(add
<<1) )
3630 *buf
++ = ( sample
[0] + sample
[add
] ) >> 1;
3636 BYTE
*buf
= buffer
[ i
];
3641 if( id
->SampleType
== SDTST_M8S
)
3643 if( (ULONG
) sample
&3 || (ULONG
) buf
&3 || samples
&3 )
3645 CopyMem( sample
, buf
, samples
);
3649 CopyMemQuick( sample
, buf
, samples
);
3658 for( c
= samples
; c
; c
--, sample
+=2 )
3668 data_right
= sample
;
3672 ioa_left
->ioa_Data
= data_left
;
3673 ioa_left
->ioa_Length
= samples
;
3674 ioa_left
->ioa_Cycles
= cycles
;
3675 ioa_left
->ioa_Period
= Freq2Period( id
->Frequency
);
3676 ioa_left
->ioa_Volume
= volleft
;
3677 ioa_left
->ioa_Request
.io_Flags
= ADIOF_PERVOL
;
3678 ioa_left
->ioa_Request
.io_Command
= CMD_WRITE
;
3679 BeginIO( (struct IORequest
*) ioa_left
);
3681 if( numChAllocated
== 2L )
3683 ioa_right
->ioa_Data
= data_right
;
3684 ioa_right
->ioa_Length
= samples
;
3685 ioa_right
->ioa_Cycles
= cycles
;
3686 ioa_right
->ioa_Period
= Freq2Period( id
->Frequency
);
3687 ioa_right
->ioa_Volume
= volright
;
3688 ioa_right
->ioa_Request
.io_Flags
= ADIOF_PERVOL
;
3689 ioa_right
->ioa_Request
.io_Command
= CMD_WRITE
;
3690 BeginIO( (struct IORequest
*) ioa_right
);
3693 if( (length
-=samples
) < samples
)
3700 dbug( kprintf( "child/Req #%ld in use\n", i
); )
3705 /* a continuous stream of data? */
3706 if( id
->Continuous
)
3709 if( id
->SignalTask
&& id
->SignalBit
!= -1 )
3711 Signal( id
->SignalTask
, 1L << id
->SignalBit
);
3721 dbug( kprintf( "child/starting stereo channels\n" ); )
3722 ioaudio
[ AUDIO_CONTROL
]->ioa_Request
.io_Command
= CMD_START
;
3723 DoIO( &ioaudio
[ AUDIO_CONTROL
]->ioa_Request
);
3728 ReleaseSemaphore( &id
->Lock
);
3732 #if !defined(__MAXON__) && !defined(__AROS__)
3733 #define SysBase cb->cb_SysBase
3737 /****************************************************************************/
3739 void __regargs
CloseAHI( struct MsgPort
*mp
, struct AHIRequest
*ahir
)
3741 #if !defined(__MAXON__) && !defined(__AROS__)
3743 struct Library
*SysBase
= (*(struct Library
**)4L);
3745 CloseDevice( (struct IORequest
*) ahir
);
3746 DeleteIORequest( (struct IORequest
*) ahir
);
3747 DeleteMsgPort( mp
);
3748 #if !defined(__MAXON__) && !defined(__AROS__)
3749 #define SysBase cb->cb_SysBase
3753 /****************************************************************************/
3755 struct Library
* __regargs
OpenAHI( struct MsgPort
**mpp
, struct AHIRequest
**iop
)
3757 #if !defined(__MAXON__) && !defined(__AROS__)
3759 struct Library
*SysBase
= (*(struct Library
**)4L);
3762 struct AHIRequest
*ahir
;
3764 mp
= CreateMsgPort();
3765 if( ( ahir
= (struct AHIRequest
*) CreateIORequest( mp
, sizeof( struct AHIRequest
) ) ) )
3767 ahir
->ahir_Version
= 4;
3768 if( ! OpenDevice( "ahi.device", AHI_NO_UNIT
, (struct IORequest
*)ahir
, 0L ) )
3772 return( (struct Library
*) ahir
->ahir_Std
.io_Device
);
3776 dbug( kprintf( "Can't open ahi.device v4\n" ); )
3779 DeleteIORequest( (struct IORequest
*) ahir
);
3783 dbug( kprintf( "no memory for ahirequest or msgport\n" ); )
3785 DeleteMsgPort( mp
);
3788 #if !defined(__MAXON__) && !defined(__AROS__)
3789 #define SysBase cb->cb_SysBase
3793 /****************************************************************************/
3796 struct SoundFuncData
{
3805 struct Task
*SigTask
;
3806 #if !defined(__MAXON__) && !defined(__AROS__)
3808 struct Library
*AHIBase
;
3809 struct Library
*SysBase
;
3810 #define AHIBase sfd->AHIBase
3811 #define SysBase sfd->SysBase
3816 void SoundFunc( struct Hook
*h
, struct AHIAudioCtrl
*actrl
, struct AHISoundMessage
*ahism
)
3818 void __interrupt
SoundFunc( REG(a0
, struct Hook
*h
), REG(a2
, struct AHIAudioCtrl
*actrl
), REG(a1
, struct AHISoundMessage
*ahism
) )
3821 struct SoundFuncData
*sfd
= (struct SoundFuncData
*) h
->h_Data
;
3823 dbug( kprintf( "SoundFunc\n" ); )
3825 if( ! ( *sfd
->Repeat
) )
3827 if( ! ( sfd
->CyclesLeft
-- ) )
3829 LONG i
, snd
= sfd
->Sound
;
3831 sfd
->Valid
[ snd
] = FALSE
;
3833 sfd
->Sound
= snd
= ( sfd
->Continuous
) ? ! snd
: AHI_NOSOUND
;
3834 /* no echos please */
3835 if( ! sfd
->Valid
[ snd
] )
3838 sfd
->Restart
= TRUE
;
3841 for( i
= 0; i
< sfd
->Channels
; i
++ )
3843 AHI_SetSound( i
, snd
, 0L, 0L, actrl
, 0L );
3846 sfd
->CyclesLeft
= sfd
->Cycles
;
3848 Signal ( sfd
->SigTask
, SIGBREAKF_CTRL_C
);
3853 #if !defined(__MAXON__) && !defined(__AROS__)
3856 #define SysBase cb->cb_SysBase
3859 /****************************************************************************/
3861 void PlayerProcAHI( void )
3863 #if !defined(__MAXON__) && !defined(__AROS__)
3864 struct Library
*SysBase
= (*(struct Library
**)4L);
3865 struct Library
*AHIBase
= NULL
;
3867 struct Process
*pr
= (struct Process
*) FindTask( NULL
);
3868 struct MsgPort
*mp
, *AHImp
;
3869 struct AHIRequest
*ahir
;
3870 struct AHIAudioCtrl
*actrl
;
3871 struct SoundFuncData
*sfd
;
3872 struct Hook
*SoundHook
= NULL
;
3873 struct ClassBase
*cb
;
3874 struct InstanceData
*id
;
3875 ULONG mpmsk
, numCh
, buffersize
;
3876 BOOL stereo
, paused
= FALSE
, failed
;
3877 static UBYTE sdtst2ahist
[] = { AHIST_M8S
, AHIST_S8S
, AHIST_M16S
, AHIST_S16S
};
3878 BYTE
*buffer
= NULL
;
3880 mp
= &pr
->pr_MsgPort
;
3881 mpmsk
= 1L << mp
->mp_SigBit
;
3883 dbug( kprintf( "child launched\n" ); )
3888 struct ObjectMsg
*msg
;
3890 rcv
= Wait( mpmsk
| SIGBREAKF_CTRL_C
);
3894 while( ( msg
= (struct ObjectMsg
*) GetMsg( mp
) ) )
3896 switch( msg
->Command
)
3898 case COMMAND_NEXT_BUFFER
:
3900 dbug( kprintf( "child: COMMAND_NEXT_BUFFER\n"); )
3902 ObtainSemaphoreShared( &id
->Lock
);
3906 BYTE
*dst
= ( sfd
->Sound
) ? &buffer
[ buffersize
] : buffer
;
3907 ULONG transfer
= UMult( id
->SampleLength
, bytesPerPoint
[ id
->SampleType
] ), i
;
3909 if( transfer
> buffersize
)
3911 transfer
= buffersize
;
3914 if( (ULONG
)id
->Sample
&3 || (ULONG
)dst
&3 || transfer
&3 )
3916 CopyMem( id
->Sample
, dst
, transfer
);
3920 CopyMemQuick( id
->Sample
, dst
, transfer
);
3923 for( i
= transfer
; i
< buffersize
; i
++ )
3928 sfd
->Valid
[ sfd
->Sound
] = TRUE
;
3930 /* new sample wasn't available fast enough */
3933 sfd
->Restart
= FALSE
;
3935 dbug( kprintf( "restart playback\n" ); )
3937 for( i
= 0; i
< numCh
; i
++ )
3939 AHI_SetSound( i
, sfd
->Sound
, 0,0, actrl
, AHISF_IMM
);
3944 ReleaseSemaphore( &id
->Lock
);
3949 dbug( kprintf("child: COMMAND_INIT\n"); )
3951 id
= (struct InstanceData
*) msg
->Data
;
3954 if( ! ( mp
= msg
->Data
= CreateMsgPort() ) )
3956 ReplyMsg( &msg
->Message
);
3960 mpmsk
= 1L << mp
->mp_SigBit
;
3966 dbug( kprintf("child: COMMAND_STOP/EXIT\n"); )
3970 AHI_FreeAudio( actrl
);
3971 FreeVec( SoundHook
);
3974 CloseAHI( AHImp
, ahir
);
3977 SetTDMode( cb
, id
, BUT_STOP
);
3980 if( msg
->Command
== COMMAND_EXIT
)
3983 ReplyMsg( &msg
->Message
);
3984 DeleteMsgPort( mp
);
3990 case COMMAND_PERVOL
:
3991 dbug( kprintf("child: COMMAND_PERVOL\n"); )
3995 ULONG freq
, vol
, pan
, i
;
3997 ObtainSemaphoreShared( &id
->Lock
);
3999 vol
= ( id
->Volume
<< 10 );
4000 freq
= id
->Frequency
;
4001 ReleaseSemaphore( &id
->Lock
);
4003 for( i
= 0; i
< numCh
; i
++ )
4007 AHI_SetFreq( i
, freq
, actrl
, AHISF_IMM
);
4009 AHI_SetVol( i
, vol
, pan
, actrl
, AHISF_IMM
);
4022 for( i
= 0; i
< numCh
; i
++ )
4024 AHI_SetFreq( i
, 0L, actrl
, AHISF_IMM
);
4034 dbug( kprintf("child: COMMAND_PLAY\n"); )
4036 // ObtainSemaphoreShared( &id->Lock );
4044 for( i
= 0; i
< numCh
; i
++ )
4046 AHI_SetFreq( i
, id
->Frequency
, actrl
, AHISF_IMM
);
4055 AHI_ControlAudio( actrl
,
4059 for( i
= 0; i
< numCh
; i
++ )
4061 AHI_SetSound( i
, sfd
->Sound
, 0,0, actrl
, AHISF_IMM
);
4064 sfd
->CyclesLeft
= sfd
->Cycles
;
4066 AHI_ControlAudio( actrl
,
4075 if( ( AHIBase
= OpenAHI( &AHImp
, &ahir
) ) )
4077 stereo
= IsStereo( id
->SampleType
);
4079 if( ( SoundHook
= (struct Hook
*) AllocVec( sizeof( *SoundHook
) + sizeof( *sfd
), MEMF_CLEAR
|MEMF_PUBLIC
) ) )
4081 ULONG audioID
, mixfreq
;
4083 extern void HookEntry( void );
4086 numCh
= stereo
? 2 : 1;
4088 sfd
= (struct SoundFuncData
*) (SoundHook
+1);
4089 #if defined(__MAXON__) || defined(__AROS__)
4090 SoundHook
->h_Entry
= (HOOKFUNC
) HookEntry
;
4091 SoundHook
->h_SubEntry
= (HOOKFUNC
) SoundFunc
;
4093 SoundHook
->h_Entry
= (HOOKFUNC
) SoundFunc
;
4095 SoundHook
->h_Data
= (APTR
) sfd
;
4097 sfd
->SigTask
= &pr
->pr_Task
;
4098 sfd
->Channels
= numCh
;
4100 sfd
->CyclesLeft
= UMult( id
->Cycles
, numCh
);
4102 sfd
->Continuous
= id
->Continuous
;
4103 sfd
->Valid
[ 0 ] = TRUE
;
4104 sfd
->Repeat
= (BOOL
*) &id
->Repeat
;
4105 // sfd->Valid[ 1 ] = FALSE;
4106 // sfd->Restart = FALSE;
4107 #if !defined(__MAXON__) && !defined(__AROS__)
4108 sfd
->AHIBase
= AHIBase
;
4109 sfd
->SysBase
= SysBase
;
4111 dbug( kprintf("child: ahi is open\n"); )
4113 ObtainSemaphoreShared( &cb
->cb_LibLock
);
4115 mixfreq
= cb
->cb_AHIMixFrequency
;
4117 if( cb
->cb_ForceAHIMode
)
4119 audioID
= cb
->cb_AHIModeID
;
4123 if( ( audioID
= AHI_BestAudioID(
4124 ( cb
->cb_AHIModeID
? AHIDB_AudioID
: TAG_IGNORE
), cb
->cb_AHIModeID
,
4126 ( ! stereo
? TAG_IGNORE
: AHIDB_Stereo
), TRUE
,
4127 ( ! stereo
? AHIDB_Panning
: TAG_IGNORE
), TRUE
,
4128 TAG_DONE
) ) == AHI_INVALID_ID
)
4130 audioID
= AHI_DEFAULT_ID
;
4131 dbug( kprintf("child: bestaid failed\n"); )
4135 ReleaseSemaphore( &cb
->cb_LibLock
);
4137 if( ( actrl
= AHI_AllocAudio(
4138 AHIA_AudioID
, audioID
,
4139 AHIA_Channels
, numCh
,
4140 AHIA_Sounds
, ( id
->Continuous
) ? 2L : 1L,
4141 AHIA_MixFreq
, mixfreq
,
4142 ( id
->Cycles
? AHIA_SoundFunc
: TAG_IGNORE
), (IPTR
) SoundHook
,
4145 struct AHISampleInfo sample
;
4148 freq
= id
->Frequency
;
4149 vol
= ( id
->Volume
<< 10 );
4151 dbug( kprintf("child: alloc audio okay\n"); )
4153 sample
.ahisi_Type
= sdtst2ahist
[ id
->SampleType
];
4154 sample
.ahisi_Length
= id
->SampleLength
;
4156 if( id
->Continuous
)
4160 AHI_GetAudioAttrs( AHI_INVALID_ID
, actrl
, AHIDB_MaxPlaySamples
,(IPTR
) &playsamples
, TAG_DONE
);
4161 AHI_ControlAudio( actrl
, AHIC_MixFreq_Query
, (IPTR
) &mixfreq
, TAG_DONE
);
4163 buffersize
= UDiv( UMult( playsamples
, id
->Frequency
), mixfreq
);
4165 if( buffersize
< id
->SampleLength
)
4167 buffersize
= id
->SampleLength
;
4170 buffersize
= UMult( buffersize
, bytesPerPoint
[ id
->SampleType
] );
4172 if( ( buffer
= AllocVec( buffersize
*2, MEMF_PUBLIC
|MEMF_CLEAR
) ) )
4174 sample
.ahisi_Address
= buffer
;
4176 if( ! AHI_LoadSound( 0, AHIST_DYNAMICSAMPLE
, &sample
, actrl
) )
4178 sample
.ahisi_Address
= &buffer
[ buffersize
];
4180 failed
= (BOOL
) AHI_LoadSound( 1, AHIST_DYNAMICSAMPLE
, &sample
, actrl
);
4183 CopyMem( id
->Sample
, buffer
, UMult( id
->SampleLength
, bytesPerPoint
[ id
->SampleType
] ) );
4189 sample
.ahisi_Address
= id
->Sample
;
4191 failed
= (BOOL
) AHI_LoadSound( 0, AHIST_SAMPLE
, &sample
, actrl
);
4194 dbug( kprintf("child: loading sample\n"); )
4200 if( ! AHI_ControlAudio( actrl
,
4205 AHIP_BeginChannel
, 0,
4208 AHIP_Pan
, id
->Panning
,
4211 ( stereo
? TAG_IGNORE
: TAG_END
), 0L,
4212 AHIP_BeginChannel
, 1,
4215 AHIP_Pan
, id
->Panning
,
4222 dbug( kprintf( "child: playback started, freq: %ld\n", freq
); )
4226 dbug( kprintf( "child: CtrlAudio failed\n" ); )
4231 dbug( kprintf( "child: loadsample failed\n" ); )
4236 dbug( kprintf( "child: AllocAudio failed\n"); )
4241 dbug( kprintf( "child: No free store\n" ); )
4247 AHI_FreeAudio( actrl
);
4248 FreeVec( SoundHook
);
4251 CloseAHI( AHImp
, ahir
);
4253 SetTDMode( cb
, id
, BUT_STOP
);
4257 SetTDMode( cb
, id
, BUT_PLAY
);
4261 // ReleaseSemaphore( &id->Lock );
4265 if( msg
->Message
.mn_ReplyPort
)
4267 ReplyMsg( &msg
->Message
);
4276 if( rcv
& SIGBREAKF_CTRL_C
)
4278 dbug( kprintf( "child: end of sample\n" ); )
4282 ObtainSemaphoreShared( &id
->Lock
);
4283 if( id
->SignalTask
&& id
->SignalBit
!= -1 )
4285 Signal( id
->SignalTask
, 1L << id
->SignalBit
);
4287 ReleaseSemaphore( &id
->Lock
);
4289 if( ! id
->Continuous
)
4291 AHI_FreeAudio( actrl
);
4292 FreeVec( SoundHook
);
4295 CloseAHI( AHImp
, ahir
);
4297 SetTDMode( cb
, id
, BUT_STOP
);
4303 #if !defined(__MAXON__) && !defined(__AROS__)
4304 #define SysBase cb->cb_SysBase
4308 /****************************************************************************/
4310 unsigned __regargs
StrLen( STRPTR str
)
4316 return( ~(unsigned) (p
- str
) );
4319 /****************************************************************************/
4321 IPTR __regargs
Sound_OBTAINDRAWINFO( Class
*cl
, Object
*o
, struct opSet
*ops
)
4323 struct InstanceData
*id
= INST_DATA( cl
, o
);
4325 dbug( kprintf( "DTM_OBTAINDRAWINFO\n" ); )
4327 return (IPTR
)( ( id
->Screen
= (struct Screen
*) GetTagData( PDTA_Screen
, 0, ops
->ops_AttrList
) ) ||
4328 ( id
->DrawInfo
= (struct DrawInfo
*) GetTagData( GA_DrawInfo
, 0, ops
->ops_AttrList
) )
4332 /****************************************************************************/
4334 IPTR __regargs
Sound_RELEASEDRAWINFO( Class
*cl
, Object
*o
, Msg msg
)
4339 /****************************************************************************/
4341 IPTR __regargs
Sound_REMOVEDTOBJECT( Class
*cl
, Object
*o
, Msg msg
)
4343 struct InstanceData
*id
= INST_DATA( cl
, o
);
4344 /* prevent other tasks (cursor- or playertask) from reading this */
4345 dbug( kprintf( "DTM_REMOVEDTOBJECT\n" ); )
4347 ObtainSemaphore( &id
->Lock
);
4348 id
->Window
= (struct Window
*)NULL
;
4349 id
->Requester
= NULL
;
4350 ReleaseSemaphore( &id
->Lock
);
4354 ReleasePen( id
->ColorMap
, id
->BackgroundPen
);
4355 ReleasePen( id
->ColorMap
, id
->WaveformPen
);
4358 return (IPTR
) DoSuperMethodA(cl
, o
, msg
);