2 * Amiga Generic Set - set of libraries and includes to ease sw development for all Amiga platforms
3 * Copyright (C) 2001-2011 Tomasz Wiszkowski Tomasz.Wiszkowski at gmail.com.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "LibrarySpool.h"
24 #include <libclass/exec.h>
25 #include <exec/ports.h>
26 #include <devices/ahi.h>
28 #include <LibC/LibC.h>
30 using namespace GenNS
;
32 AHI::AHI(short channels
)
37 numChannels
= channels
;
41 for (int i
=0; i
<256; i
++)
46 for (int i
=0; i
<32; i
++)
52 hHkProc
.Initialize(this, &AHI::subProcess
);
53 hHkCmd
.Initialize(this, &AHI::procCommand
);
54 hHkSound
.Initialize(this, &AHI::procSoundMessage
);
55 hHkMusic
.Initialize(this, &AHI::procMusicMessage
);
57 pThread
= new Thread("AHI Process", hHkProc
.GetHook(), NULL
);
58 pThread
->SetHandler(hHkCmd
.GetHook());
59 // ensure everything is up and running
60 pThread
->DoSync(cmd_NoOp
, 0);
71 hModes
.ForEach(&freeAudioID
);
74 bool AHI::freeAudioID(AudioID
* const &id
)
80 unsigned long AHI::GetModeCount()
82 return hModes
.Count();
85 const AHI::AudioID
*AHI::GetMode(unsigned long id
)
90 bool AHI::SetAudioMode(const AHI::AudioID
*id
)
92 return (bool)pThread
->DoSync(cmd_SetAudio
, const_cast<AudioID
*>(id
));
95 AHI::AudioID
*AHI::GetAudioMode()
100 void AHI::FreeAudio()
102 pThread
->DoAsync(cmd_FreeAudio
, 0);
105 unsigned short AHI::CreateDynamicSample(AHISampleType type
, int freq
, const Hook
* func
, int bufflen
)
107 ahi_CreateDynamicSample dyn
= { type
, freq
, func
, bufflen
};
108 return pThread
->DoSync(cmd_CreateDynamicSample
, &dyn
);
111 unsigned short AHI::CreateStaticSample(AHISampleType type
, int freq
, void* buffer
, int length
)
113 ahi_CreateStaticSample stat
= { type
, freq
, buffer
, length
};
114 return pThread
->DoSync(cmd_CreateStaticSample
, &stat
);
117 void AHI::FreeSample(unsigned short idx
)
119 ahi_FreeSample fre
= { idx
};
120 pThread
->DoSync(cmd_FreeSample
, &fre
);
123 bool AHI::PlaySample(unsigned short idx
)
125 ahi_PlaySample fre
= { idx
};
126 return pThread
->DoSync(cmd_PlaySample
, &fre
);
129 const AHI::AudioID
*AHI::FindMode(unsigned long id
)
132 for (idx
=0; idx
<GetModeCount(); idx
++)
134 if (GetMode(idx
)->id
== id
)
140 unsigned long AHI::subProcess(Thread
*pThis
, void*)
142 pAHI
= AHIIFace::GetInstance();
146 for (unsigned long i
= pAHI
->AHI_NextAudioID(AHI_INVALID_ID
);
148 i
= pAHI
->AHI_NextAudioID(i
))
150 AudioID
*pID
= new AudioID
;
152 pAHI
->AHI_GetAudioAttrsA(i
, 0, (TagItem
*)ARRAY(
153 AHIDB_Name
, (int)&pID
->name
,
163 pThis
->HandleSignals(0xffffffff);
167 pAHI
->FreeInstance();
171 unsigned long AHI::procCommand(AHICommand aCmd
, void* pData
)
179 return do_SetAudio((AudioID
*)pData
);
185 case cmd_CreateDynamicSample
:
186 return do_CreateDynamicSample((ahi_CreateDynamicSample
*)pData
);
188 case cmd_CreateStaticSample
:
189 return do_CreateStaticSample((ahi_CreateStaticSample
*)pData
);
192 do_FreeSample(((ahi_FreeSample
*)pData
)->sample
);
196 return do_PlaySample((ahi_PlaySample
*)pData
);
199 do_SoundStop((ahi_SoundInfo
*)pData
);
203 do_SoundLoop((ahi_SoundInfo
*)pData
);
209 unsigned long AHI::procSoundMessage(AHIAudioCtrl
* pCtl
, AHISoundMessage
*msg
)
211 ExtAHISampleInfo
*pExt
= smpChan
[msg
->ahism_Channel
];
213 // if this is not true we started nosound
216 if (pExt
->dynamic
== true)
218 if (pExt
->fndsample
->ahisi_Length
)
220 pThread
->DoAsync(cmd_SoundLoop
, new ahi_SoundInfo(msg
->ahism_Channel
));
224 pThread
->DoAsync(cmd_SoundStop
, new ahi_SoundInfo(msg
->ahism_Channel
));
229 pThread
->DoAsync(cmd_SoundStop
, new ahi_SoundInfo(msg
->ahism_Channel
));
235 unsigned long AHI::procMusicMessage(long cmd
, ExtAHISampleInfo
* pExt
)
240 pExt
->ahisi_Length
= pExt
->hData(pExt
->ahisi_Address
, pExt
->maxlen
);// / pExt->bps;
241 //Generic::MessageBox("Info", "Passing data\n%ld bytes requested,\n%ld bytes received.", "Ok", ARRAY(pExt->maxlen, pExt->ahisi_Length));
248 bool AHI::do_SetAudio(AudioID
* newID
)
250 AHIAudioCtrl
*pCtl
= 0;
253 if ((pCurrentMode
!=0) && (pCurrentMode
->id
== newID
->id
))
261 pCtl
= pAHI
->AHI_AllocAudioA((TagItem
*)ARRAY(
262 AHIA_AudioID
, newID
->id
,
264 AHIA_Channels
, numChannels
,
266 AHIA_SoundFunc
, (int)hHkSound
.GetHook(),
273 pCurrentMode
= newID
;
274 err
= pAHI
->AHI_ControlAudioA(pCtl
, (TagItem
*)ARRAY(AHIC_Play
, true, 0, 0));
277 request("Error", "Unable to start audio device.\nError code %ld", "Proceed", ARRAY(err
));
284 void AHI::do_FreeAudio()
286 AHIAudioCtrl
*pCtl
= 0;
288 if (pCurrentMode
== 0)
293 pCtl
= pAudio
.Assign(0);
296 for (int i
=0; i
<256; i
++)
298 if (0 != smpSample
[i
])
303 pAHI
->AHI_FreeAudio(pCtl
);
308 unsigned short AHI::do_CreateDynamicSample(ahi_CreateDynamicSample
*dat
)
310 ExtAHISampleInfo
*pExt1
= do_AllocSample(true, dat
->type
, 0, dat
->buflen
);
311 ExtAHISampleInfo
*pExt2
= do_AllocSample(true, dat
->type
, 0, dat
->buflen
);
317 do_FreeSample(pExt1
->id
);
319 do_FreeSample(pExt2
->id
);
324 pExt1
->fndsample
= pExt2
;
325 pExt2
->fndsample
= pExt1
;
327 pExt1
->freq
= dat
->freq
;
328 pExt2
->freq
= dat
->freq
;
330 pExt1
->update
= new Thread("AHI Music");
331 pExt2
->update
= pExt1
->update
;
333 pExt1
->update
->SetHandler(hHkMusic
.GetHook());
335 pExt1
->hData
= dat
->func
;
336 pExt2
->hData
= dat
->func
;
341 unsigned short AHI::do_CreateStaticSample(ahi_CreateStaticSample
*dat
)
343 ExtAHISampleInfo
*pExt
= do_AllocSample(false, dat
->type
, dat
->buffer
, dat
->buflen
);
346 pExt
->freq
= dat
->freq
;
352 AHI::ExtAHISampleInfo
*AHI::do_AllocSample(bool dynamic
, AHISampleType type
, void* buffer
, int buflen
)
359 ExtAHISampleInfo
*pInfo
= 0;
361 AHIAudioCtrl
*pCtl
= 0;
363 for (i
=0; i
<256; i
++)
365 if (smpSample
[i
] == 0)
371 pInfo
= new ExtAHISampleInfo
;
375 buffer
= new char[buflen
];
401 pInfo
->ahisi_Address
= buffer
;
402 pInfo
->ahisi_Length
= buflen
/ pInfo
->bps
;
403 pInfo
->ahisi_Type
= type
;
406 pInfo
->dynamic
= dynamic
;
407 pInfo
->fndsample
= 0;
409 pInfo
->maxlen
= buflen
;
411 pCtl
= pAudio
.ObtainRead();
414 pAHI
->AHI_LoadSound(i
, (dynamic
? AHIST_DYNAMICSAMPLE
: AHIST_SAMPLE
), pInfo
, pCtl
);
418 smpSample
[i
] = pInfo
;
426 void AHI::do_FreeSample(short idx
)
435 if (0 != smpSample
[idx
])
437 ExtAHISampleInfo
*pExt1
= smpSample
[idx
];
438 ExtAHISampleInfo
*pExt2
= pExt1
->fndsample
;
440 // 1 CLEAR SAMPLE AND ITS FRIEND
443 smpSample
[pExt2
->id
] = 0;
445 delete pExt1
->update
;
449 // 2 UNLOAD SAMPLE AND ITS FRIEND
450 AHIAudioCtrl
*pCtl
= pAudio
.ObtainRead();
453 pAHI
->AHI_UnloadSound(idx
, pCtl
);
455 pAHI
->AHI_UnloadSound(pExt2
->id
, pCtl
);
459 // 3 FREE MEMORY BUFFER FOR SAMPLE AND ITS FRIEND
460 if (pExt1
->dynamic
== true)
461 delete [] ((char*)pExt1
->ahisi_Address
);
462 if ((NULL
!= pExt2
) &&
463 (pExt2
->dynamic
== true))
464 delete [] ((char*)pExt2
->ahisi_Address
);
466 // 4 FREE SAMPLE AND ITS FRIEND
474 bool AHI::do_PlaySample(ahi_PlaySample
*dat
)
476 int idx
= dat
->sample
;
487 if (0 == smpSample
[idx
])
490 pCtl
= pAudio
.ObtainRead();
493 for (chan
=0; chan
<numChannels
; chan
++)
495 if (smpChan
[chan
] == 0)
499 if (chan
!= numChannels
)
501 smpChan
[chan
] = smpSample
[idx
];
503 if (smpSample
[idx
]->dynamic
!= false)
505 memset(smpSample
[idx
]->ahisi_Address
, 0, smpSample
[idx
]->maxlen
);
506 memset(smpSample
[idx
]->fndsample
->ahisi_Address
, 0, smpSample
[idx
]->maxlen
);
509 err
= pAHI
->AHI_PlayA(pCtl
, (TagItem
*)ARRAY(
510 AHIP_BeginChannel
, chan
,
511 AHIP_Freq
, smpSample
[idx
]->freq
,
534 void AHI::do_SoundStop(ahi_SoundInfo
* dat
)
536 int chan
= dat
->channel
;
541 if (chan
> numChannels
)
547 pCtl
= pAudio
.ObtainRead();
552 pAHI
->AHI_PlayA(pCtl
, (TagItem
*)ARRAY(
553 AHIP_BeginChannel
, chan
,
554 AHIP_Sound
, AHI_NOSOUND
,
560 pAHI
->AHI_SetSound(chan
, AHI_NOSOUND
, 0, 0, pCtl
, 0);
562 if (smpWaits
[chan
] != NULL
)
564 Exec
->Signal(smpWaits
[chan
], 1 << (smpSignals
[chan
]));
572 void AHI::WaitSample(unsigned short sample
)
575 int sig
= Exec
->AllocSignal(-1);
579 for (int i
=0; i
<numChannels
; i
++)
581 if ((smpChan
[i
] != 0) &&
582 (smpChan
[i
]->id
== sample
))
584 smpWaits
[i
] = Exec
->FindTask(0);
594 Exec
->Wait(1 << sig
);
596 Exec
->FreeSignal(sig
);
599 void AHI::do_SoundLoop(ahi_SoundInfo
* info
)
601 ExtAHISampleInfo
*pExt
= smpChan
[info
->channel
];
602 AHIAudioCtrl
*pCtl
= pAudio
.ObtainRead();
604 smpChan
[info
->channel
] = pExt
->fndsample
;
605 pExt
->update
->DoAsync(cmd_SoundLoop
, pExt
->fndsample
);
606 pAHI
->AHI_SetSound(info
->channel
, pExt
->fndsample
->id
, 0, 0, pCtl
, 0);