LONG WriteStream(struct IFFHandle *iff, APTR buf, LONG bytestowrite, struct IFFParseBase_intern *IFFParseBase) { LONG retval, err; struct IFFStreamCmd cmd; /* Call the custom hook with a write command */ D(bug("WriteStream(iff=%p buf=%p bytestowrite=%d)\n", iff, buf, bytestowrite)); retval = bytestowrite; if (bytestowrite) { cmd.sc_Command = IFFCMD_WRITE; cmd.sc_Buf = buf; cmd.sc_NBytes = bytestowrite; err = CallHookPkt ( GetIntIH(iff)->iff_StreamHandler, iff, &cmd ); if (err) retval = IFFERR_WRITE; } D(bug("WriteStream: return %d\n", retval)); return (retval); }
LONG InvokeHandlers(struct IFFHandle *iff, LONG mode, LONG ident, struct IFFParseBase_intern *IFFParseBase) { struct ContextNode *cn; struct HandlerInfo *hi; struct LocalContextItem *lci; LONG err; /* Either RETURN_2CLIENT or IFFERR_EOC */ LONG stepping_retval; ULONG param; D(bug("InvokeHandlers (Iff=%p, mode=%d, ident=0x%08lx\n", iff, mode, ident )); if (ident == IFFLCI_ENTRYHANDLER) stepping_retval = IFF_RETURN2CLIENT; else stepping_retval = IFFERR_EOC; /* Check for IFFPARSE_RAWSTEP *before* calling evt entryhandlers */ if (mode == IFFPARSE_RAWSTEP) ReturnInt ("InvokeHandlers(1)",LONG,stepping_retval); /* Get top of contextstack */ cn = TopChunk(iff); /* Scan downwards to find a contextnode with a matching LCI */ lci = FindLocalItem ( iff, cn->cn_Type, cn->cn_ID, ident ); if (lci) { /* Get the HandlerInfo userdata */ hi = LocalItemData(lci); /* First check if a hook really is present */ if (! hi->hi_Hook) ReturnInt ("InvokeHandlers",LONG,IFFERR_NOHOOK); /* What kind off command shall the hook receive */ if (ident == IFFLCI_ENTRYHANDLER) param = IFFCMD_ENTRY; else param = IFFCMD_EXIT; /* Call the handler */ if ( (err = CallHookPkt ( hi->hi_Hook, hi->hi_Object, (APTR)param)) ) ReturnInt ("InvokeHandlers(2)",LONG,err); } /* Check for IFFPARSE_STEP. (stepping through file WITH handlers enabled */ if (mode == IFFPARSE_STEP) ReturnInt ("InvokeHandlers(3)",LONG,stepping_retval); ReturnInt ("InvokeHandlers",LONG,0L); }
/* returns one of the standard IFF errors */ LONG ReadStream(struct IFFHandle *iff, APTR buf, LONG bytestoread, struct IFFParseBase_intern *IFFParseBase) { LONG retval, err; /* For use with custom streams */ struct IFFStreamCmd cmd; D(bug("ReadStream(iff=%p buf=%p bytestoread=%d)\n", iff, buf, bytestoread)); retval = bytestoread; if (bytestoread) { /* Now we can do the actual reading of the stream */ cmd.sc_Command = IFFCMD_READ; cmd.sc_Buf = buf; cmd.sc_NBytes = bytestoread; err = CallHookPkt ( GetIntIH(iff)->iff_StreamHandler, iff, &cmd ); if (err) retval = IFFERR_READ; } D(bug("ReadStream: return %d\n", retval)); return (retval); }
void CallSoundHook( struct AHIPrivAudioCtrl *audioctrl, void* arg ) { switch( MixBackend ) { case MB_NATIVE: CallHookPkt( audioctrl->ac.ahiac_SoundFunc, audioctrl, arg ); break; #if defined( ENABLE_WARPUP ) case MB_WARPUP: WarpUpCallSoundHook( audioctrl, arg ); break; #endif } }
VOID PurgeLCI(struct LocalContextItem *lci, struct IFFParseBase_intern *IFFParseBase) { /* Look in the RKM SetLocalItemPurge autodoc for explanation on that one below */ D(bug("PurgeLCI(lci=%p)\n", lci)); Remove((struct Node*)lci); /* Has the user specified a Purge hook ? */ if ( GetIntLCI(lci)->lci_PurgeHook) CallHookPkt ( GetIntLCI(lci)->lci_PurgeHook, lci, (APTR)IFFCMD_PURGELCI ); else FreeLocalItem(lci); }
xadUINT32 callprogressFN(const struct xadArchiveInfoP *ai, xadUINT32 stat, xadUINT32 mode, xadSTRPTR *filename, struct xadMasterBaseP * xadMasterBase) { xadUINT32 ret = XADPIF_OK; struct xadProgressInfo *pi; #ifdef AMIGA struct UtilityBase *UtilityBase = xadMasterBase->xmb_UtilityBase; #endif #ifdef DEBUG DebugRunTime("callprogressFN: hook = $%08lx", ai->xaip_ProgressHook); #endif if(ai->xaip_ProgressHook) { if((pi = (struct xadProgressInfo *) xadAllocObjectA(XADM XADOBJ_PROGRESSINFO, 0))) { pi->xpi_FileName = *filename; pi->xpi_Mode = mode; pi->xpi_Client = ai->xaip_ArchiveInfo.xai_Client; pi->xpi_DiskInfo = ai->xaip_ArchiveInfo.xai_CurDisk; pi->xpi_FileInfo = ai->xaip_ArchiveInfo.xai_CurFile; pi->xpi_CurrentSize = ai->xaip_ArchiveInfo.xai_OutSize; pi->xpi_LowCyl = ai->xaip_ArchiveInfo.xai_LowCyl; pi->xpi_HighCyl = ai->xaip_ArchiveInfo.xai_HighCyl; if(mode == XADPMODE_ERROR) { pi->xpi_Error = stat; stat = 0; } pi->xpi_Status = stat; ret = CallHookPkt(ai->xaip_ProgressHook, 0, pi); *filename = pi->xpi_NewName; xadFreeObjectA(XADM pi, 0); } } return ret; }
struct DragObj * PRIVATE CreateDragObj(struct DragGadget *dg,int x,int y) { struct Screen *scr; struct RastPort *rp; struct DragObj *gdo; ULONG line; int wordwidth; int width,height,depth; int i = 0,xpos,ypos; scr = dg->dg_Window->WScreen; rp = &scr->RastPort; if (dg->dg_Flags & DGF_IMAGES && ((struct ImageNode *)dg->dg_Object.od_Object)->in_Image) dg->dg_Image = ((struct ImageNode *)dg->dg_Object.od_Object)->in_Image; if (!dg->dg_Width || !dg->dg_Height) { if ((dg->dg_Type == LISTVIEW_KIND) && !dg->dg_Image) { dg->dg_Width = dg->dg_Gadget->Width-20; dg->dg_Height = dg->dg_ItemHeight; } else if (!dg->dg_RenderHook && dg->dg_Image) { dg->dg_Width = dg->dg_Image->Width; dg->dg_Height = dg->dg_Image->Height; } else /* be sure width & height are not zero */ { dg->dg_Width = dg->dg_Gadget->Width; dg->dg_Height = dg->dg_Gadget->Height; } } width = dg->dg_Width; height = dg->dg_Height; memset(&dm,0,sizeof(struct DropMessage)); if (dg->dg_Type == LISTVIEW_KIND) { xpos = dg->dg_Gadget->LeftEdge+2; ypos = dg->dg_Gadget->TopEdge+2; dg->dg_Object.od_Object = NULL; if (y < ypos || y > ypos+dg->dg_Gadget->Height-5) return(NULL); line = (y-ypos)/dg->dg_ItemHeight; ypos += line*dg->dg_ItemHeight; GT_GetGadgetAttrs(dg->dg_Gadget,dg->dg_Window,NULL,GTLV_Labels,&dg->dg_List,TAG_END); if (dg->dg_List && !IsListEmpty(dg->dg_List)) { GT_GetGadgetAttrs(dg->dg_Gadget,dg->dg_Window,NULL,GTLV_Top,&i,TAG_END); i += line; if (i < CountNodes(dg->dg_List)) { struct Node *ln; dm.dm_SourceEntry = i; for(ln = dg->dg_List->lh_Head;i;i--,ln = ln->ln_Succ); if (dg->dg_Flags & DGF_TREEVIEW && TREENODE(ln)->tn_Flags & TNF_STATIC) { mx = ~0L; // avoid a following drag return(NULL); } dg->dg_Object.od_Object = ln; if (dg->dg_ObjectFunc) dg->dg_ObjectFunc(dg->dg_Window,dg->dg_Gadget,&dg->dg_Object,dm.dm_SourceEntry); } } } else { if (dg->dg_ObjectFunc) dg->dg_ObjectFunc(dg->dg_Window,dg->dg_Gadget,&dg->dg_Object,0L); dm.dm_SourceEntry = dg->dg_SourceEntry; xpos = x-width/2; ypos = y-height/2; } if (!dg->dg_Object.od_Object) { mx = ~0L; // avoid a following drag return(NULL); } wordwidth = (width + 15) >> 4; depth = GetBitMapAttr(rp->BitMap,BMA_DEPTH); if (dg->dg_Object.od_Object && (gdo = AllocMem(sizeof(struct DragObj), MEMF_CLEAR | MEMF_PUBLIC))) { #ifdef LOCKLAYERS LockLayers(&scr->LayerInfo); UnlockLayer(dg->dg_Window->RPort->Layer); #endif gdo->do_Screen = scr; gdo->do_ScrRPort = rp; gdo->do_BitMap = AllocBitMap(width,height,depth,BMF_CLEAR | BMF_MINPLANES,!(GetBitMapAttr( rp->BitMap, BMA_FLAGS ) & BMF_INTERLEAVED) ? rp->BitMap : NULL); gdo->do_SaveBack = AllocBitMap(width,height,depth,BMF_CLEAR | BMF_MINPLANES,rp->BitMap); gdo->do_RefreshMap = AllocBitMap(width*2,height*2,depth,BMF_CLEAR | BMF_MINPLANES,rp->BitMap); if (GetBitMapAttr(gdo->do_BitMap,BMA_FLAGS) & BMF_STANDARD) i = MEMF_CHIP | MEMF_PUBLIC; else i = 0; gdo->do_FullShadow = AllocMem(2*wordwidth*height,i | MEMF_CLEAR); gdo->do_HalfShadow = AllocMem(2*wordwidth*height,i); if (gdo->do_BitMap && gdo->do_SaveBack && gdo->do_RefreshMap && gdo->do_FullShadow && gdo->do_HalfShadow) { InitRastPort(&gdo->do_RPort); gdo->do_RPort.BitMap = gdo->do_BitMap; InitRastPort(&gdo->do_RefreshRPort); gdo->do_RefreshRPort.BitMap = gdo->do_RefreshMap; gdo->do_DragGadget = dg; CopyMem(&dg->dg_Object,&dm.dm_Object,sizeof(struct ObjectDescription)); dm.dm_Window = dg->dg_Window; dm.dm_Gadget = dg->dg_Gadget; /*** create the drag&drop image ***/ if (dg->dg_RenderHook) { struct LVDrawMsg lvdm; SetFont(&gdo->do_RPort,scr->RastPort.Font); lvdm.lvdm_MethodID = LV_DRAW; lvdm.lvdm_RastPort = &gdo->do_RPort; lvdm.lvdm_DrawInfo = GetScreenDrawInfo(scr); lvdm.lvdm_Bounds.MinX = 0; lvdm.lvdm_Bounds.MinY = 0; lvdm.lvdm_Bounds.MaxX = width-1; lvdm.lvdm_Bounds.MaxY = height-1; lvdm.lvdm_State = LVR_SELECTED; CallHookPkt(dg->dg_RenderHook,dm.dm_Object.od_Object,&lvdm); FreeScreenDrawInfo(scr,lvdm.lvdm_DrawInfo); } else if (dg->dg_Image) DrawImage(&gdo->do_RPort,dg->dg_Image,0,0); else ClipBlit(dg->dg_Window->RPort,xpos,ypos,&gdo->do_RPort,0,0,width,height,0xc0); /*** initialize drag object structure ***/ gdo->do_X = -9999; gdo->do_Y = ypos+dg->dg_Window->TopEdge; gdo->do_PX = -9999; gdo->do_Width = width; gdo->do_Height = height; gdo->do_DeltaX = xpos-x+dg->dg_Window->LeftEdge; gdo->do_DeltaY = ypos-y+dg->dg_Window->TopEdge; gdo->do_Mask = gdo->do_FullShadow; /*** create masks (transparent and full imagery) ***/ if (CyberGfxBase && (GetBitMapAttr(gdo->do_BitMap,BMA_FLAGS) & BMF_STANDARD) == 0L) { struct BitMap tbm; ULONG col; InitBitMap(&tbm,1,width,height); tbm.Planes[0] = (UBYTE *)gdo->do_FullShadow; /* if (!GetCyberMapAttr(gdo->do_BitMap, CYBRMATTR_PIXELFMT)) */ if (GetBitMapAttr(gdo->do_BitMap, BMA_DEPTH) > 8L) { ULONG triplet[3]; GetRGB32(scr->ViewPort.ColorMap,0L,1L,triplet); col = (triplet[0] & 0xff0000) | (triplet[1] & 0xff00) | (triplet[2] & 0xff); } else col = 0; // ExtractColor(rp,&tbm,col,xpos,ypos,width,height); ExtractColor(&gdo->do_RPort,&tbm,col,0,0,width,height); BltBitMap(&tbm,0,0,&tbm,0,0,width,height,0x50,0xff,NULL); // invertieren der Maske } else { UWORD *p = gdo->do_FullShadow; for(ypos = 0;ypos < height;ypos++) { for(xpos = 0;xpos < wordwidth;xpos++,p++) { for(i = 0;i < depth;i++) *p |= *((UWORD *)gdo->do_BitMap->Planes[i]+ypos*(gdo->do_BitMap->BytesPerRow >> 1)+xpos); } } } { UWORD *p = gdo->do_HalfShadow; CopyMem(gdo->do_FullShadow,p,2*wordwidth*height); for(line = 0x5555,ypos = 0;ypos < height;ypos++) { line = ~line; for(xpos = 0;xpos < wordwidth;xpos++,p++) *p &= (UWORD)line; } } if (!boopsigad) FakeInputEvent(); UpdateDragObj(gdo,gdo->do_X,gdo->do_Y); /* show drag object */ return(gdo); }
void __asm __saveds SlaveTask(register __a2 struct AHIAudioCtrlDrv *AudioCtrl) // SlaveEntry() will set up register a2 and a6 for us. { struct EIGHTSVXheader EIGHTSVXheader = // All NULLs will be filled later. { ID_FORM, NULL, ID_8SVX, ID_VHDR, sizeof(Voice8Header), { NULL, 0, 0, NULL, 1, sCmpNone, 0x10000 }, ID_BODY, NULL }; struct AIFFheader AIFFheader = // All NULLs will be filled later. { ID_FORM, NULL, ID_AIFF, ID_COMM, sizeof(CommonChunk), { NULL, NULL, 16, { NULL } }, ID_SSND, NULL, { 0, 0 } }; struct AIFCheader AIFCheader = // All NULLs will be filled later. { ID_FORM, NULL, ID_AIFC, ID_FVER, sizeof(FormatVersionHeader), { AIFCVersion1 }, ID_COMM, sizeof(ExtCommonChunk), { NULL, NULL, 16, { NULL }, NO_COMPRESSION, sizeof("not compressed") - 1, 'n','o','t',' ','c','o','m','p','r','e','s','s','e','d' }, ID_SSND, NULL, { 0, 0 } }; struct STUDIO16FILE S16header = // All NULLs will be filled later. { S16FID, NULL, S16FINIT, S16_VOL_0, 0, 0, NULL, 0, 0, NULL, NULL, 0, NULL, 0, { 0 } }; struct EasyStruct req = { sizeof (struct EasyStruct), 0, _LibID, "Rendering finished.\nTo futher improve the quality of the sample,\n" "you can raise the volume to %ld%%%sand render again.", "OK", }; BPTR lock = NULL,cd = NULL,file = NULL, file2 = NULL; ULONG signals, i, maxVolume = 0, samplesAdd =0, samples = 0, length = 0; ULONG offset = 0, bytesInBuffer = 0, samplesWritten = 0, bytesWritten = 0; // We cannot handle stereo 8SVXs! if( (dd->fs_Format == FORMAT_8SVX) && (AudioCtrl->ahiac_Flags & AHIACF_STEREO) ) { goto quit; } if((dd->fs_DisableSignal = AllocSignal(-1)) == -1) { goto quit; } if((dd->fs_EnableSignal = AllocSignal(-1)) == -1) { goto quit; } if((dd->fs_SlaveSignal = AllocSignal(-1)) == -1) { goto quit; } if(!(lock = Lock(dd->fs_FileReq->fr_Drawer, ACCESS_READ))) { goto quit; } cd = CurrentDir(lock); switch(dd->fs_Format) { case FORMAT_8SVX: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &EIGHTSVXheader, sizeof EIGHTSVXheader); break; case FORMAT_AIFF: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &AIFFheader, sizeof AIFFheader); break; case FORMAT_AIFC: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &AIFCheader, sizeof AIFCheader); break; case FORMAT_S16: if (AudioCtrl->ahiac_Flags & AHIACF_STEREO) { char filename[256]; int len; strncpy (filename, dd->fs_FileReq->fr_File, sizeof(filename) - 3); len = strlen(filename); if(len >= 2 && filename[len - 2] == '_' && (filename[len - 1] == 'L' || filename[len - 1] == 'R')) { filename[len - 1] = 'L'; } else { strcat (filename, "_L"); } if(!(file = Open(filename, MODE_NEWFILE))) goto quit; filename[strlen(filename) - 1] = 'R'; if(!(file2 = Open(filename, MODE_NEWFILE))) goto quit; Write(file, &S16header, sizeof S16header); Write(file2, &S16header, sizeof S16header); } else { if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &S16header, sizeof S16header); } break; } // Everything set up. Tell Master we're alive and healthy. Signal((struct Task *)dd->fs_MasterTask,1L<<dd->fs_MasterSignal); for(;;) { signals = SetSignal(0L,0L); if(signals & (SIGBREAKF_CTRL_C | 1L<<dd->fs_SlaveSignal)) { break; } if(signals & (1L<<dd->fs_EnableSignal | 1L<<dd->fs_DisableSignal) == 1L<<dd->fs_DisableSignal) { Wait(1L<<dd->fs_EnableSignal); } CallHookPkt(AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL); CallHookPkt(AudioCtrl->ahiac_MixerFunc, AudioCtrl, dd->fs_MixBuffer); samplesAdd = AudioCtrl->ahiac_BuffSamples; samples = samplesAdd; if(AudioCtrl->ahiac_Flags & AHIACF_STEREO) { samples <<= 1; } // Search for loudest part in sample if(AudioCtrl->ahiac_Flags & AHIACF_HIFI) { for(i = 0; i < samples; i++) if(abs(((LONG *)dd->fs_MixBuffer)[i]) > maxVolume) maxVolume = abs(((LONG *)dd->fs_MixBuffer)[i]); } else { for(i = 0; i< samples; i++) if(abs(((WORD *)dd->fs_MixBuffer)[i]) > maxVolume) maxVolume = abs(((WORD *)dd->fs_MixBuffer)[i]); } if((AudioCtrl->ahiac_Flags & AHIACF_STEREO) && dd->fs_Format == FORMAT_S16) { samples >>= 1; // Two buffers instead } if(offset+samples >= dd->fs_SaveBufferSize) { if(Write(file, dd->fs_SaveBuffer, bytesInBuffer) != bytesInBuffer) { break; } if(file2 != NULL) { if(Write(file2, dd->fs_SaveBuffer2, bytesInBuffer) != bytesInBuffer) { break; } } offset = 0; bytesInBuffer = 0; } switch(dd->fs_Format) { case FORMAT_8SVX: if(AudioCtrl->ahiac_Flags & AHIACF_HIFI) { BYTE *dest = &((BYTE *) dd->fs_SaveBuffer)[offset]; LONG *source = dd->fs_MixBuffer; for(i = 0; i < samples; i++) *dest++ = *source++ >> 24; } else {
/*********************************************************************** Import the given 0 terminated text by invoking the given import Hook for every line ***********************************************************************/ BOOL ImportText(struct InstData *data, const char *contents, struct Hook *importHook, LONG wraplength, struct MinList *lines) { struct line_node *line; ENTER(); // make sure we start with an empty list of lines InitLines(lines); if((line = AllocVecPooled(data->mypool, sizeof(struct line_node))) != NULL) { struct ImportMessage im; memset(line, 0, sizeof(*line)); im.Data = contents; im.ImportWrap = wraplength; im.PoolHandle = data->mypool; im.ConvertTabs = data->ConvertTabs; im.TabSize = data->TabSize; while(TRUE) { struct line_node *new_line; im.linenode = &line->line; // invoke the hook, it will return NULL in case it is finished or // an error occured im.Data = (char*)CallHookPkt(importHook, NULL, &im); if(im.Data == NULL) { if(line->line.Contents != NULL) { // add the last imported line to the list AddLine(lines, line); } else { // free the line node if it didn't contain any contents if(ContainsLines(lines) == FALSE) { FreeVecPooled(data->mypool, line); } else { // if the line has nor predecessor it was obviously the first line // so we prepare a "fake" line_node to let the textEditor clear our // text if(Init_LineNode(data, line, "\n") == TRUE) AddLine(lines, line); else FreeVecPooled(data->mypool, line); } } // bail out break; } // add the imported line to the list AddLine(lines, line); if((new_line = AllocVecPooled(data->mypool, sizeof(struct line_node))) == NULL) break; // inherit the flow from the current line for the next line, // but only if the clearFlow variable is not set if(line->line.clearFlow == FALSE) new_line->line.Flow = line->line.Flow; line = new_line; } } RETURN(ContainsLines(lines)); return ContainsLines(lines); }
ENDFUNC static xadERROR skipread(xadUINT8 *buf, xadSize size, struct xadArchiveInfoP *ai, xadUINT32 skip) { #ifdef AMIGA struct xadMasterBaseP *xadMasterBase = (struct xadMasterBaseP *) ai->xaip_MasterBase; struct UtilityBase *UtilityBase = xadMasterBase->xmb_UtilityBase; #endif struct xadHookParam *ihp; struct Hook *ih; const struct xadSkipInfo *si, *si2; xadERROR ret = 0; xadSize s; ihp = &(ai->xaip_InHookParam); ih = ai->xaip_InHook; if(ai->xaip_ArchiveInfo.xai_SkipInfo && skip) { while(!ret && size) { si2 = 0; for(si = ai->xaip_ArchiveInfo.xai_SkipInfo; si; si = si->xsi_Next) { /* skip buffer at start */ if(si->xsi_Position <= ai->xaip_ArchiveInfo.xai_InPos && si->xsi_Position+si->xsi_SkipSize > ai->xaip_ArchiveInfo.xai_InPos) { ihp->xhp_Command = XADHC_SEEK; ihp->xhp_CommandData = si->xsi_Position+si->xsi_SkipSize - ai->xaip_ArchiveInfo.xai_InPos; ret = CallHookPkt(ih, ai, ihp); ai->xaip_ArchiveInfo.xai_InPos = ihp->xhp_DataPos; } else if(si->xsi_Position > ai->xaip_ArchiveInfo.xai_InPos && (!si2 || si2->xsi_Position > si->xsi_Position)) si2 = si; } if(!ret) { if(!si2 || (s = si2->xsi_Position - ai->xaip_ArchiveInfo.xai_InPos) > size) s = size; ihp->xhp_Command = XADHC_READ; ihp->xhp_BufferPtr = buf; ihp->xhp_BufferSize = s; ret = CallHookPkt(ih, ai, ihp); buf += s; ai->xaip_ArchiveInfo.xai_InPos = ihp->xhp_DataPos; size -= s; } } } else { ihp->xhp_Command = XADHC_READ; ihp->xhp_BufferPtr = buf; ihp->xhp_BufferSize = size; ret = CallHookPkt(ih, ai, ihp); ai->xaip_ArchiveInfo.xai_InPos = ihp->xhp_DataPos; } return ret; }
static void Slave( struct ExecBase* SysBase ) { struct AHIAudioCtrlDrv* AudioCtrl; struct DriverBase* AHIsubBase; struct AROSBase* AROSBase; BOOL running; ULONG signals; int bytes_in_buffer = 0; int offset_in_buffer = 0; AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData; AHIsubBase = (struct DriverBase*) dd->ahisubbase; AROSBase = (struct AROSBase*) AHIsubBase; dd->slavesignal = AllocSignal( -1 ); if( dd->slavesignal != -1 ) { // Everything set up. Tell Master we're alive and healthy. Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal ); running = TRUE; // The main playback loop follow while( running ) { signals = SetSignal(0L,0L); // KPrintF("++++ arosdriver_after signal checking\n"); if( signals & ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) ) ) { running = FALSE; } else { int skip_mix; int bytes_avail; // First Delay() until there is at least one fragment free while( TRUE ) { int frag_avail, frag_alloc, frag_size; OSS_GetOutputInfo( &frag_avail, &frag_alloc, &frag_size, &bytes_avail ); // KPrintF( "%ld fragments available, %ld alloced (%ld bytes each). %ld bytes total\n", frag_avail, frag_alloc, frag_size, bytes_avail ); if( frag_avail == 0 ) { // This is actually quite a bit too long delay :-( For // comparison, the SB Live/Audigy driver uses 1/1000 s // polling ... // KPrintF("Delay\n"); #if USE_TIMERTICK SmallDelay(SysBase); #else Delay( 1 ); #endif } else { break; } } skip_mix = 0;/*CallHookA( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 );*/ while( bytes_avail > 0 ) { // KPrintF( "%ld bytes in current buffer.\n", bytes_in_buffer ); if( bytes_in_buffer == 0 ) { int skip = 0; int offset = 0; int samples = 0; int bytes = 0; int i; WORD* src; WORD* dst; CallHookPkt( AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL ); samples = AudioCtrl->ahiac_BuffSamples; bytes = samples * 2; // one 16 bit sample is 2 bytes switch( AudioCtrl->ahiac_BuffType ) { case AHIST_M16S: skip = 1; offset = 0; break; case AHIST_M32S: skip = 2; offset = 1; break; case AHIST_S16S: skip = 1; offset = 0; samples *= 2; bytes *= 2; break; case AHIST_S32S: skip = 2; offset = 1; samples *= 2; bytes *= 2; break; } bytes_in_buffer = bytes; offset_in_buffer = 0; if( ! skip_mix ) { CallHookPkt( AudioCtrl->ahiac_MixerFunc, AudioCtrl, dd->mixbuffer ); } src = ((WORD*) dd->mixbuffer) + offset; dst = dd->mixbuffer; for( i = 0; i < samples; ++i ) { *dst++ = *src; src += skip; } // KPrintF( "Mixed %ld/%ld new bytes/samples\n", bytes, samples ); } while( bytes_in_buffer > 0 && bytes_avail > 0 ) { int written; int counter = 0; do { written = OSS_Write( dd->mixbuffer + offset_in_buffer, min( bytes_in_buffer, bytes_avail ) ); if (counter > 10) { if (written < 0) written = 0; break; } if (written < 0) KPrintF("OSS_Write returned %ld. counter %ld bytes_in_buffer %ld bytes_avail %ld\n", written, counter, bytes_in_buffer, bytes_avail); counter++; } while (written < 0); bytes_in_buffer -= written; offset_in_buffer += written; bytes_avail -= written; // KPrintF( "Wrote %ld bytes (%ld bytes in buffer, offset=%ld, %ld bytes available in OSS buffers\n", // written, bytes_in_buffer, offset_in_buffer, bytes_avail ); } } CallHookA( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 ); } } } FreeSignal( dd->slavesignal ); dd->slavesignal = -1; Forbid(); // Tell the Master we're dying Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal ); dd->slavetask = NULL; // Multitaking will resume when we are dead. }
static void Slave( struct ExecBase* SysBase ) { struct AHIAudioCtrlDrv* AudioCtrl; struct DriverBase* AHIsubBase; struct DeviceBase* DeviceBase; BOOL running; ULONG signals; AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData; AHIsubBase = (struct DriverBase*) dd->ahisubbase; DeviceBase = (struct DeviceBase*) AHIsubBase; dd->slavesignal = AllocSignal( -1 ); if( dd->slavesignal != -1 ) { struct MsgPort* ahi_mp = NULL; struct AHIRequest* ahi_iorequest = NULL; APTR ahi_iocopy = NULL; BYTE ahi_device = -1; struct AHIRequest* ahi_io[ 2 ] = { NULL, NULL }; BOOL ahi_io_used[ 2 ] = { FALSE, FALSE }; ULONG frame_length = 0; ahi_mp = CreateMsgPort(); if( ahi_mp != NULL ) { ahi_iorequest = CreateIORequest( ahi_mp, sizeof( struct AHIRequest ) ); if( ahi_iorequest != NULL ) { ahi_iorequest->ahir_Version = 4; ahi_device = OpenDevice( AHINAME, dd->unit, (struct IORequest*) ahi_iorequest, 0 ); if( ahi_device == 0 ) { struct Library* AHIBase = (struct Library*) ahi_iorequest->ahir_Std.io_Device; ahi_iocopy = AllocVec( sizeof( *ahi_iorequest ), MEMF_ANY ); if( ahi_iocopy != NULL ) { bcopy( ahi_iorequest, ahi_iocopy, sizeof( *ahi_iorequest ) ); ahi_io[ 0 ] = ahi_iorequest; ahi_io[ 1 ] = ahi_iocopy; // Everything set up. Tell Master we're alive and healthy. Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal ); running = TRUE; // The main playback loop follow while( running ) { int skip_mix; APTR tmp_buff; struct AHIRequest* tmp_io; if( ahi_io_used[ 0 ] ) { LONG err; ULONG mask = ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) | (1L << ahi_mp->mp_SigBit) ); signals = Wait( mask ); if( signals & ( SIGBREAKF_CTRL_C | (1L << dd->slavesignal) ) ) { running = FALSE; break; } err = WaitIO( (struct IORequest*) ahi_io[ 0 ] ); if( err != 0 ) { KPrintF( DRIVER ": AHI device error %ld\n", err ); // running = FALSE; break; } } skip_mix = CallHookPkt( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 ); CallHookPkt( AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL ); if( ! skip_mix ) { CallHookPkt( AudioCtrl->ahiac_MixerFunc, AudioCtrl, dd->mixbuffers[ 0 ] ); } CallHookPkt( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 ); if( frame_length == 0 ) { frame_length = AHI_SampleFrameSize( AudioCtrl->ahiac_BuffType ); } ahi_io[ 0 ]->ahir_Std.io_Command = CMD_WRITE; ahi_io[ 0 ]->ahir_Std.io_Data = dd->mixbuffers[ 0 ]; ahi_io[ 0 ]->ahir_Std.io_Length = ( AudioCtrl->ahiac_BuffSamples * frame_length ); ahi_io[ 0 ]->ahir_Std.io_Offset = 0; ahi_io[ 0 ]->ahir_Frequency = AudioCtrl->ahiac_MixFreq; ahi_io[ 0 ]->ahir_Type = AudioCtrl->ahiac_BuffType; ahi_io[ 0 ]->ahir_Volume = 0x10000; ahi_io[ 0 ]->ahir_Position = 0x08000; ahi_io[ 0 ]->ahir_Link = ( ahi_io_used[ 1 ] ? ahi_io[ 1 ] : NULL ); SendIO( (struct IORequest*) ahi_io[ 0 ] ); tmp_io = ahi_io[ 0 ]; ahi_io[ 0 ] = ahi_io[ 1 ]; ahi_io[ 1 ] = tmp_io; tmp_buff = dd->mixbuffers[ 0 ]; dd->mixbuffers[ 0 ] = dd->mixbuffers[ 1 ]; dd->mixbuffers[ 1 ] = tmp_buff; ahi_io_used[ 0 ] = ahi_io_used[ 1 ]; ahi_io_used[ 1 ] = TRUE; } if( ahi_io_used[ 0 ] ) { AbortIO( (struct IORequest*) ahi_io[ 0 ] ); WaitIO( (struct IORequest*) ahi_io[ 0 ] ); } if( ahi_io_used[ 1 ] ) { AbortIO( (struct IORequest*) ahi_io[ 1 ] ); WaitIO( (struct IORequest*) ahi_io[ 1 ] ); } FreeVec( ahi_iocopy ); } CloseDevice( (struct IORequest*) ahi_iorequest ); } DeleteIORequest( (struct IORequest*) ahi_iorequest ); } DeleteMsgPort( ahi_mp ); } } FreeSignal( dd->slavesignal ); dd->slavesignal = -1; Forbid(); // Tell the Master we're dying Signal( (struct Task*) dd->mastertask, 1L << dd->mastersignal ); dd->slavetask = NULL; // Multitaking will resume when we are dead. }
void RecSlaveEntry(void) { struct AHIAudioCtrlDrv* AudioCtrl; struct DriverBase* AHIsubBase; struct FilesaveBase* FilesaveBase; ULONG signals; BPTR lock = NULL,cd=0,file = NULL; Object *o = NULL; BYTE *samples = NULL; ULONG length = NULL; ULONG count = 0,offs = 0,i; struct AHIRecordMessage RecordMessage = { AHIST_S16S, NULL, RECBUFFERSIZE }; AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData; AHIsubBase = (struct DriverBase*) dd->fs_AHIsubBase; FilesaveBase = (struct FilesaveBase*) AHIsubBase; RecordMessage.ahirm_Buffer = dd->fs_RecBuffer; if(!(lock = Lock(dd->fs_RecFileReq->fr_Drawer,ACCESS_READ))) goto quit; cd = CurrentDir(lock); if(DataTypesBase) { struct TagItem newtags[] = { { DTA_GroupID, GID_SOUND }, { TAG_DONE, 0 } }; struct TagItem attrtags[] = { { SDTA_Sample, (ULONG) &samples }, { SDTA_SampleLength, (ULONG) &length }, { TAG_DONE, 0 } }; if (!(o = NewDTObjectA (dd->fs_RecFileReq->fr_File, newtags))) goto quit; GetDTAttrsA(o, attrtags ); } else // datatypes.library not open. Open the selected file as raw 8 bit signed instead. { if(!(file = Open(dd->fs_RecFileReq->fr_File,MODE_OLDFILE))) goto quit; Seek(file,0,OFFSET_END); length = Seek(file,0,OFFSET_BEGINNING); if(!(samples = AllocVec(length,MEMF_ANY))) goto quit; if(length != (ULONG) Read(file,samples,length)) goto quit; } if(!samples || !length ) goto quit; if((dd->fs_RecSlaveSignal = AllocSignal(-1)) == -1) goto quit; // Everything set up. Tell Master we're alive and healthy. Signal((struct Task *)dd->fs_MasterTask,1L<<dd->fs_RecMasterSignal); for(;;) { signals = SetSignal(0L,0L); if(signals & (SIGBREAKF_CTRL_C | 1L<<dd->fs_RecSlaveSignal)) break; for(;;) { if(count+RECBUFFERSIZE-offs < length) { // End of sample will not be reached; just fill to the end of dd->fs_RecBuffer. for(i = RECBUFFERSIZE-offs;i>0;i--) { dd->fs_RecBuffer[(offs)<<1] = dd->fs_RecBuffer[((offs++)<<1)+1] = samples[count++]<<8; } offs = 0; break; } else { // End of sample will be reached. Fill part of buffer, and iterate (== don't break). for(i = length-count;i>0;i--) { dd->fs_RecBuffer[(offs)<<1] = dd->fs_RecBuffer[((offs++)<<1)+1] = samples[count++]<<8; } count = 0; } } CallHookPkt(AudioCtrl->ahiac_SamplerFunc,AudioCtrl,&RecordMessage); Delay(50*RECBUFFERSIZE/AudioCtrl->ahiac_MixFreq); } quit: // Get rid of object if(DataTypesBase) { if(o) DisposeDTObject (o); } else // datatypes.library not open. { if(samples) FreeVec(samples); if(file) Close(file); } CurrentDir(cd); if(lock) UnLock(lock); Forbid(); dd->fs_RecSlaveTask = NULL; FreeSignal(dd->fs_RecSlaveSignal); dd->fs_RecSlaveSignal = -1; // Tell the Master we're dying Signal((struct Task *)dd->fs_MasterTask,1L<<dd->fs_RecMasterSignal); // Multitaking will resume when we are dead. }
ULONG HandleStrInput( struct Gadget *gad, struct GadgetInfo *ginfo, struct InputEvent *ievent, UWORD *imsgcode, struct IntuitionBase *IntuitionBase) { struct SGWork sgw; struct StringInfo *strinfo = (struct StringInfo *)gad->SpecialInfo; struct StringExtend *strext = NULL; ULONG command = 0; EnterFunc(bug("HandleStrInput(gad=%p, ginfo=%p, ievent=%p)\n", gad, ginfo, ievent)); if ((ievent->ie_Class == IECLASS_TIMER)) return 0; D(bug("Gadget text: %s\n", strinfo->Buffer)); if (!ginfo) ReturnInt("HandleStrInput", ULONG, 0UL); UpdateStringInfo(gad); /* Initialize SGWork */ sgw.Gadget = gad; sgw.StringInfo = strinfo; sgw.WorkBuffer = strinfo->Buffer; /* default */ sgw.PrevBuffer = strinfo->Buffer; sgw.Modes = 0; sgw.IEvent = ievent; sgw.Code = 0; sgw.BufferPos = strinfo->BufferPos; sgw.NumChars = strinfo->NumChars; sgw.Actions = 0; sgw.LongInt = strinfo->LongInt; sgw.GadgetInfo = ginfo; sgw.EditOp = EO_NOOP; if (gad->Flags & GFLG_STRINGEXTEND) { D(bug("HandleStrInput: Extended gadget\n")); strext = strinfo->Extension; if (strext->WorkBuffer) { sgw.WorkBuffer = strext->WorkBuffer; /* The edit hook gets *copy* of the current buffer contents */ strcpy(sgw.WorkBuffer, strinfo->Buffer); } sgw.Modes = strext->InitialModes; } switch (ievent->ie_Class) { case IECLASS_RAWMOUSE: if (ievent->ie_Code == SELECTDOWN) { command = SGH_CLICK; sgw.Actions = SGA_USE | SGA_REDISPLAY; D(bug("HandleStrInput: RAWMOUSE event\n")); } break; case IECLASS_RAWKEY: { UBYTE buf; D(bug("HandleStrInput: RAWKEY event\n")); if (ievent->ie_Code & IECODE_UP_PREFIX) { D(bug("HandleStrInput: filter UP event\n")); } else { command = SGH_KEY; sgw.Actions = SGA_USE; if (1 == MapRawKey(sgw.IEvent, &buf, 1, strinfo->AltKeyMap)) { D(bug("HandleStrInput: sgw.Code 0x%lx\n",buf)); sgw.Code = (UWORD)buf; } } break; } } if (!command) ReturnInt("HandleStrInput", ULONG , 0UL); /* Call the global editing hook */ D(bug("calling global hook, Buffer=%s, WorkBuffer=%s\n", strinfo->Buffer, sgw.WorkBuffer)); CallHookPkt(GetPrivIBase(IntuitionBase)->GlobalEditHook, &sgw, &command); /* If there is a local edit hook, run it */ if (strext) { if (strext->EditHook) { D(bug("calling local edit hook\n")); CallHookPkt(strext->EditHook, &sgw, &command); } } /* Copy possibly changed stuff into stringgad */ if (sgw.Actions & SGA_USE) { if (strext) { if (strext->WorkBuffer) strcpy(strinfo->Buffer, strext->WorkBuffer); } strinfo->BufferPos = sgw.BufferPos; strinfo->NumChars = sgw.NumChars; strinfo->LongInt = sgw.LongInt; #if 0 if (gad->Activation & GACT_LONGINT) { kprintf("strinfo->LongInt = %d\n",strinfo->LongInt); */ } else {
LONG SeekStream(struct IFFHandle *iff,LONG offset, struct IFFParseBase_intern *IFFParseBase) { /* Some different problem - situations: 1. Backwards seek in non back seekable stream. In this case the stream is buffered, and we may seek in the buffer. This is done automagically, since PushChunk then has inserted a Buffering streamhandle. 2. Forwards seek in a non - seekable stream. Simulate the seek with a bunch of ReadStream's */ struct IFFStreamCmd cmd; ULONG flags; LONG retval = 0; LONG err; UBYTE *seekbuf; D(bug("SeekStream(iff=%p offset=%d)\n", iff, offset)); flags = iff->iff_Flags; /* Problem 2. */ if ( (offset > 0) && ( !( (flags & IFFF_RSEEK) || (flags & IFFF_FSEEK) ) ) ) { /* We should use consecutive ReadStream()s to simulate a Seek */ /* Allocate a buffer to use with the read */ seekbuf = AllocMem(SEEKBUFSIZE, MEMF_ANY); if (!seekbuf) retval = IFFERR_NOMEM; else { for (; offset > SEEKBUFSIZE; offset -= SEEKBUFSIZE) { retval = ReadStream(iff, seekbuf, SEEKBUFSIZE, IFFParseBase); if (retval != SEEKBUFSIZE) retval = IFFERR_SEEK; } /* Seek what is left of offset */ retval = ReadStream(iff, seekbuf, SEEKBUFSIZE, IFFParseBase); if ( retval != SEEKBUFSIZE) retval = IFFERR_SEEK; FreeMem(seekbuf, SEEKBUFSIZE); } } else if (offset == 0) { ; /* Do nothing */ } else { /* Everything is just fine... Seek in a normal manner */ cmd.sc_Command = IFFCMD_SEEK; cmd.sc_NBytes = offset; err = CallHookPkt ( GetIntIH(iff)->iff_StreamHandler, iff, &cmd ); if (err) retval = IFFERR_SEEK; } D(bug("SeekStream: return %d\n", retval)); return (retval); }
static BOOL HandleReq( struct AHIAudioModeRequesterExt *req ) // Returns FALSE if requester was cancelled { BOOL done=FALSE,rc=TRUE; ULONG class,sec,oldsec=0,micro,oldmicro=0,oldid=AHI_INVALID_ID; UWORD code; UWORD qual; struct Gadget *pgsel; struct IntuiMessage *imsg; struct IDnode *idnode; LONG sliderlevels,sliderlevel,i,selected; struct MenuItem *item; while(!done) { Wait(1L << req->Window->UserPort->mp_SigBit); while ((imsg=GT_GetIMsg(req->Window->UserPort)) != NULL ) { if(imsg->IDCMPWindow == req->InfoWindow) { class = imsg->Class; GT_ReplyIMsg(imsg); switch(class) { case IDCMP_CLOSEWINDOW: CloseInfoWindow(req); break; case IDCMP_REFRESHWINDOW : GT_BeginRefresh(req->InfoWindow); GT_EndRefresh(req->InfoWindow,TRUE); break; } continue; // Get next IntuiMessage } else if(imsg->IDCMPWindow != req->Window) // Not my window! { if(req->IntuiMsgFunc) CallHookPkt(req->IntuiMsgFunc,req,imsg); // else what to do??? Reply and forget? FIXIT! continue; } sec=imsg->Seconds; micro=imsg->Micros; qual=imsg->Qualifier; class=imsg->Class; code=imsg->Code; pgsel=(struct Gadget *)imsg->IAddress; // pgsel illegal if not gadget GT_ReplyIMsg(imsg); switch ( class ) { case IDCMP_RAWKEY: switch (code) { case 0x4c: // Cursor Up selected=GetSelected(req); if(selected == ~0) selected=0; if(selected > 0) selected--; idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case 0x4d: // Cursor Down selected=GetSelected(req); selected++; // ~0 => 0 idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) if(idnode->node.ln_Succ->ln_Succ) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case 0x4e: // Cursor Right GetSliderAttrs(req,&sliderlevels,&sliderlevel); sliderlevel += (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1); if(sliderlevel >= sliderlevels) sliderlevel=sliderlevels-1; AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg,sliderlevel, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); SetSelected(req,FALSE); break; case 0x4f: // Cursor Left GetSliderAttrs(req,&sliderlevels,&sliderlevel); sliderlevel -= (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT) ? 10 :1); if(sliderlevel < 0) sliderlevel=0; AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg,sliderlevel, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); SetSelected(req,FALSE); break; } break; case IDCMP_GADGETUP : switch ( pgsel->GadgetID ) { case OKBUTTON: done=TRUE; break; case CANCELBUTTON: done=TRUE; rc=FALSE; break; case FREQSLIDER: AHI_GetAudioAttrs(req->tempAudioID, NULL, AHIDB_FrequencyArg,code, AHIDB_Frequency, (ULONG) &req->tempFrequency, TAG_DONE); break; case LISTVIEW: idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<code;i++) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,FALSE); // Test doubleclick and save timestamp if( (oldid == req->tempAudioID) && DoubleClick(oldsec,oldmicro,sec,micro)) done=TRUE; oldsec=sec; oldmicro=micro; oldid=req->tempAudioID; break; } break; case IDCMP_NEWSIZE: if(!(LayOutReq(req,req->TextAttr))) if(!(LayOutReq(req,&Topaz80))) { // ERROR! Quit. done=TRUE; break; } break; case IDCMP_CLOSEWINDOW: done=TRUE; rc=FALSE; break; case IDCMP_REFRESHWINDOW : GT_BeginRefresh(req->Window); GT_EndRefresh(req->Window,TRUE); break; case IDCMP_SIZEVERIFY: break; case IDCMP_MENUPICK: while((code != MENUNULL) && !done) { item=ItemAddress(req->Menu, code); switch((ULONG)GTMENUITEM_USERDATA(item)) { case LASTMODEITEM: selected=GetSelected(req); if(selected == ~0) selected=0; if(selected > 0) selected--; idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case NEXTMODEITEM: selected=GetSelected(req); selected++; // ~0 => 0 idnode=(struct IDnode *)req->list->mlh_Head; for(i=0;i<selected;i++) if(idnode->node.ln_Succ->ln_Succ) idnode=(struct IDnode *)idnode->node.ln_Succ; req->tempAudioID=idnode->ID; SetSelected(req,TRUE); break; case PROPERTYITEM: OpenInfoWindow(req); break; case RESTOREITEM: req->tempAudioID=req->Req.ahiam_AudioID; req->tempFrequency=req->Req.ahiam_MixFreq; SetSelected(req,TRUE); break; case OKITEM: done=TRUE; break; case CANCELITEM: done=TRUE; rc=FALSE; break; } code = item->NextSelect; } break; } } }
void SlaveEntry(void) { struct AHIAudioCtrlDrv* AudioCtrl; struct DriverBase* AHIsubBase; struct FilesaveBase* FilesaveBase; struct EIGHTSVXheader EIGHTSVXheader = // All 0s will be filled later. { __htobe_long(ID_FORM), 0, __htobe_long(ID_8SVX), __htobe_long(ID_VHDR), __htobe_long(sizeof(Voice8Header)), { 0, 0, 0, 0, 1, sCmpNone, __htobe_long(0x10000) }, __htobe_long(ID_BODY), 0 }; struct AIFFheader AIFFheader = // All 0s will be filled later. { __htobe_long(ID_FORM), 0, __htobe_long(ID_AIFF), __htobe_long(ID_COMM), __htobe_long(sizeof(CommonChunk)), { 0, 0, __htobe_short(16), { 0, { 0, 0 } } }, __htobe_long(ID_SSND), 0, { 0, 0 } }; struct AIFCheader AIFCheader = // All 0s will be filled later. { __htobe_long(ID_FORM), 0, __htobe_long(ID_AIFC), __htobe_long(ID_FVER), __htobe_long(sizeof(FormatVersionHeader)), { __htobe_long(AIFCVersion1) }, __htobe_long(ID_COMM), __htobe_long(sizeof(ExtCommonChunk)), { 0, 0, __htobe_short(16), { 0, { 0, 0 } }, __htobe_long(NO_COMPRESSION), { sizeof("not compressed") - 1, 'n','o','t',' ','c','o','m','p','r','e','s','s','e','d' } }, __htobe_long(ID_SSND), 0, { 0, 0 } }; struct STUDIO16FILE S16header = // All 0s will be filled later. { __htobe_long(S16FID), 0, __htobe_long(S16FINIT), __htobe_short(S16_VOL_0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } }; struct WAVEheader WAVEheader = // All 0s will be filled later. { __htobe_long(ID_RIFF), 0, __htobe_long(ID_WAVE), __htobe_long(ID_fmt), __htole_long( sizeof(FormatChunk) ), { __htole_short( WAVE_PCM ), 0, 0, 0, 0, __htole_short( 16 ) }, __htobe_long(ID_data), 0 }; BPTR lock = 0,cd = 0,file = 0, file2 = 0; LONG maxVolume = 0; ULONG signals, i, samplesAdd =0, samples = 0, length = 0; ULONG offset = 0, bytesInBuffer = 0, samplesWritten = 0, bytesWritten = 0; AudioCtrl = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData; AHIsubBase = (struct DriverBase*) dd->fs_AHIsubBase; FilesaveBase = (struct FilesaveBase*) AHIsubBase; // We cannot handle stereo 8SVXs! if( (dd->fs_Format == FORMAT_8SVX) && (AudioCtrl->ahiac_Flags & AHIACF_STEREO) ) { goto quit; } if((dd->fs_SlaveSignal = AllocSignal(-1)) == -1) { goto quit; } if(!(lock = Lock(dd->fs_FileReq->fr_Drawer, ACCESS_READ))) { goto quit; } cd = CurrentDir(lock); switch(dd->fs_Format) { case FORMAT_8SVX: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &EIGHTSVXheader, sizeof EIGHTSVXheader); break; case FORMAT_AIFF: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &AIFFheader, sizeof AIFFheader); break; case FORMAT_AIFC: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &AIFCheader, sizeof AIFCheader); break; case FORMAT_S16: if (AudioCtrl->ahiac_Flags & AHIACF_STEREO) { char filename[256]; int len; strncpy (filename, dd->fs_FileReq->fr_File, sizeof(filename) - 3); len = strlen(filename); if(len >= 2 && filename[len - 2] == '_' && (filename[len - 1] == 'L' || filename[len - 1] == 'R')) { filename[len - 1] = 'L'; } else { strcat (filename, "_L"); } if(!(file = Open(filename, MODE_NEWFILE))) goto quit; filename[strlen(filename) - 1] = 'R'; if(!(file2 = Open(filename, MODE_NEWFILE))) goto quit; Write(file, &S16header, sizeof S16header); Write(file2, &S16header, sizeof S16header); } else { if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &S16header, sizeof S16header); } break; case FORMAT_WAVE: if(!(file = Open(dd->fs_FileReq->fr_File, MODE_NEWFILE))) goto quit; Write(file, &WAVEheader, sizeof WAVEheader); break; } // Everything set up. Tell Master we're alive and healthy. Signal((struct Task *)dd->fs_MasterTask,1L<<dd->fs_MasterSignal); for(;;) { signals = SetSignal(0L,0L); if(signals & (SIGBREAKF_CTRL_C | 1L<<dd->fs_SlaveSignal)) { break; } CallHookPkt(AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL); CallHookPkt(AudioCtrl->ahiac_MixerFunc, AudioCtrl, dd->fs_MixBuffer); samplesAdd = AudioCtrl->ahiac_BuffSamples; samples = samplesAdd; if(AudioCtrl->ahiac_Flags & AHIACF_STEREO) { samples <<= 1; } // Search for loudest part in sample if(AudioCtrl->ahiac_Flags & AHIACF_HIFI) { for(i = 0; i < samples; i++) if(abs(((LONG *)dd->fs_MixBuffer)[i]) > maxVolume) maxVolume = abs(((LONG *)dd->fs_MixBuffer)[i]); } else { for(i = 0; i< samples; i++) if(abs(((WORD *)dd->fs_MixBuffer)[i]) > maxVolume) maxVolume = abs(((WORD *)dd->fs_MixBuffer)[i]); } if((AudioCtrl->ahiac_Flags & AHIACF_STEREO) && dd->fs_Format == FORMAT_S16) { samples >>= 1; // Two buffers instead } if(offset+samples >= dd->fs_SaveBufferSize) { if((ULONG) Write(file, dd->fs_SaveBuffer, bytesInBuffer) != bytesInBuffer) { break; } if(file2 != 0) { if((ULONG) Write(file2, dd->fs_SaveBuffer2, bytesInBuffer) != bytesInBuffer) { break; } } offset = 0; bytesInBuffer = 0; } switch(dd->fs_Format) { case FORMAT_8SVX: if(AudioCtrl->ahiac_Flags & AHIACF_HIFI) { BYTE *dest = &((BYTE *) dd->fs_SaveBuffer)[offset]; LONG *source = dd->fs_MixBuffer; for(i = 0; i < samples; i++) *dest++ = *source++ >> 24; } else {