build: add the SIBO SDK

This commit is contained in:
2026-07-06 18:01:36 +01:00
parent d76326729c
commit 64e484448c
757 changed files with 97167 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
@if not "%jpivid%"=="v2" set jpivid=v0
+9
View File
@@ -0,0 +1,9 @@
@echo off
call checkvid
if not exist %1.pr goto error
tscx /m %1 /%jpivid%
tscx /m %1 /%jpivid%
goto end
:error
echo Project file %1.pr does not exist
:end
+23
View File
@@ -0,0 +1,23 @@
rec3b.prj ! This list file
!
record.cat ! Cat file for application
record.re ! Hash defines from cat file needed in resource file
record.hlp ! Help text resources
record.rss ! Resource file for application
!
reccli.c ! client bordered window
reccom.c ! Command manager code
recdial.c ! Dialogs
receng.c ! Engine
recwserv.c ! Application WSERV
waveao.c ! Sound active objects
wvefile.c ! Sound file
!
record.ms ! Source for shell data on record
record.afl ! Lists the files to be built into record.img
record.pic ! Application icon
record.pr ! Project file for Record
!
VID.BAT ! Set/clear debug status
CHECKVID.BAT ! Check debug status
MAKE.BAT ! Project make file
+473
View File
@@ -0,0 +1,473 @@
/*
RECCLI.C
The record application's client window and its components
*/
#include <p_std.h>
#include <p_sys.h>
#include <p_date.h>
#include <epoc.h>
#include <p_config.h>
#include <record.g>
#include <hwim.h>
#include <record.rsg>
#include <fonts.h>
#include <olib.h>
GLREF_D PR_RECWSERV * const w_ws;
GLREF_D PR_APPMAN * const w_am;
GLREF_D PR_RECENG * const receng;
#define TIMEBAR_HEIGHT 13
#define RECBUT_HIDE_DRAW 0
#define RECBUT_HIDE_HIDE 1
#define RECBUT_HIDE_CLEAR 2
#define RECBUT_HALF_WIDTH 34
#define RECBUT_HALF_HEIGHT 10
#define RECBUT_ASCENT 16
#define RECBUT_MARGIN 20
#define RECCLI_NBUTTONS 5
#define RECCLI_3BUT_MASK 0x7 /* 1st 3 buttons */
#define RECCLI_STOP_MASK 0x8 /* 4th button */
#define RECCLI_START_MASK 0x10 /* 5th button */
LOCAL_D UBYTE recbut_hide[RECCLI_NBUTTONS]=
{RECBUT_HIDE_CLEAR,RECBUT_HIDE_HIDE,RECBUT_HIDE_CLEAR,RECBUT_HIDE_HIDE,RECBUT_HIDE_HIDE};
LOCAL_C TEXT *NextZTS(TEXT *str)
{
while (*str++);
return(str);
}
LOCAL_C VOID StartFRC(PR_TIMEBAR *self)
{
UWORD tick,mode;
mode=E_FRC_REPEATING;
tick=100;
p_iow4(self->active.pcb,P_FSTART,&mode,&tick);
}
LOCAL_C INT BarLength(PR_TIMEBAR *self)
{
INT width;
width=self->timebar.rect.br.x-self->timebar.rect.tl.x-2;
if (self->timebar.tenths0)
width-=(UINT)((width*self->timebar.tenths)/self->timebar.tenths0);
return(width);
}
LOCAL_C VOID DrawBar(PR_TIMEBAR *self,INT border,INT createGC)
{
INT x1,x2;
P_RECT r;
x1=self->timebar.x;
x2=BarLength(self);
if (x2==x1 && self->timebar.visible && !border)
return;
if (createGC)
gCreateTempGC0(self->timebar.wid);
r=self->timebar.rect;
if (!self->timebar.visible)
{
gClrRect(&r,G_TRMODE_CLR);
goto exit;
}
if (border)
gBorderRect(&r,W_BORD_CORNER_1);
p_insrec(&r,1,1);
if (x1>x2)
{
gClrRect(&r,G_TRMODE_CLR);
x1=0;
}
self->timebar.x=x2;
r.tl.x+=x1;
r.br.x=r.tl.x+x2-x1;
gFillPattern(&r,WS_BITMAP_GREY,G_TRMODE_REPL);
exit:
if (createGC)
{
gFreeTempGC();
wFlush();
}
}
LOCAL_C VOID DrawButton(PR_RECBUT *self,INT state)
{
wDrawButton2(W_BUTTON_TYPE_2,&self->recbut.rect,&self->recbut.inlabel[0],state);
}
LOCAL_C VOID PrintHeader(PR_RECCLI *self,INT y,TEXT *fmt,...)
{
INT len;
TEXT bb[256];
P_RECT rect;
rect.tl.x=8;
rect.tl.y=y;
rect.br.x=rect.tl.x+self->reccli.width-16;
rect.br.y=y+30;
if (fmt==NULL)
{
gClrRect(&rect,G_TRMODE_CLR);
return;
}
len=p_atob(&bb[0],fmt,&fmt+1);
gPrintBoxText(&rect,20,G_TEXT_ALIGN_CENTRE,0,&bb[0],len);
}
LOCAL_C VOID HideButtons(PR_RECCLI *self,INT mask)
/*
Set the hidden state of the buttons to hide depending on the bits in mask.
*/
{
INT i;
for (i=0;i<RECCLI_NBUTTONS;i++,mask>>=1)
self->reccli.recbut[i]->recbut.hide=(mask&1)?recbut_hide[i]:RECBUT_HIDE_DRAW;
}
LOCAL_C VOID DrawWin(PR_RECCLI *self)
{
G_GC gc;
gc.flags=G_GC_FLAG_BOTH_PLANES;
gCreateTempGC(self->win.id,G_GC_MASK_GREY,&gc);
p_send2(self,O_WN_DRAW);
gFreeTempGC();
}
LOCAL_C VOID PrintDuration(PR_RECCLI *self,TEXT *buf,ULONG tenths)
{
ULONG seconds;
UINT secs;
P_DAYSEC ds;
P_DATE dt;
seconds=tenths/10;
if (seconds<60)
{
secs=(UINT)seconds;
p_atos(buf,"%d.%d %s",secs,(UINT)tenths-10*secs,self->reccli.secs);
return;
}
p_sttods(&seconds,&ds);
p_dstodt(&ds,&dt);
ds.day-=25567; /* base days at Jan 1 1970 */
if (ds.day>0)
{ /* show number of days */
p_atos(buf,"%ld ",ds.day);
buf+=p_slen(buf);
}
if (dt.hour>0 || ds.day>0)
{ /* show number of hours */
p_atos(buf,"%02d%c",dt.hour,self->reccli.tsep);
buf+=p_slen(buf);
}
p_atos(buf,"%02d%c%02d",dt.minute,self->reccli.tsep,dt.second);
}
#pragma METHOD_CALL
METHOD VOID timebar_tb_draw(PR_TIMEBAR *self)
{
self->timebar.x=0;
DrawBar(self,TRUE,FALSE);
}
METHOD VOID timebar_ao_init(PR_TIMEBAR *self,INT wid,P_RECT *prect)
{
self->active.priority=PRIORITY_ACTIVE_REPEATER;
p_send3(w_am,O_AM_ADD_TASK,self);
self->timebar.wid=wid;
self->timebar.rect=*prect;
}
METHOD VOID timebar_ao_queue(PR_TIMEBAR *self)
{
p_ioc3(self->active.pcb,P_FREAD,&self->active.stat);
self->active.isactive=TRUE;
}
METHOD INT timebar_ao_run(PR_TIMEBAR *self)
{
if (self->active.stat<0)
{ /* possibly because the machine was switched off then on */
StartFRC(self); /* restart the FRC */
self->active.stat=0;
}
self->timebar.tenths-=self->active.stat;
if (self->timebar.tenths<=0)
{
self->timebar.tenths=0; /* stops re-queue */
p_close(self->active.pcb);
self->active.pcb=NULL;
}
DrawBar(self,FALSE,TRUE);
if (self->timebar.tenths)
timebar_ao_queue(self);
return(RUN_ACTIVE_USED);
}
METHOD VOID timebar_tb_start(PR_TIMEBAR *self,ULONG *tenths)
{
self->timebar.tenths0=*tenths;
self->timebar.tenths=self->timebar.tenths0;
self->timebar.x=0;
self->timebar.visible=TRUE;
if (self->timebar.tenths<10 || p_open(&self->active.pcb,"FRC:",-1)<0)
return;
StartFRC(self);
DrawBar(self,TRUE,TRUE);
timebar_ao_queue(self);
}
METHOD VOID timebar_tb_stop(PR_TIMEBAR *self)
{
p_send2(self,O_AO_CANCEL);
self->timebar.visible=FALSE;
p_close(self->active.pcb);
self->active.pcb=NULL;
}
METHOD VOID recbut_destroy(PR_RECBUT *self)
{
p_free(self->recbut.buttxt);
p_supersend2(self,O_DESTROY);
}
METHOD VOID recbut_rb_init(PR_RECBUT *self,INT wid,P_POINT *pc,INT rid)
{
self->recbut.wid=wid;
self->recbut.rect.tl.x=pc->x-RECBUT_HALF_WIDTH;
self->recbut.rect.br.x=pc->x+RECBUT_HALF_WIDTH;
self->recbut.rect.tl.y=pc->y-RECBUT_HALF_HEIGHT;
self->recbut.rect.br.y=pc->y+RECBUT_HALF_HEIGHT;
hLoadResource(rid,&self->recbut.buttxt);
self->recbut.inlabel=(TEXT *)(((WORD *)self->recbut.buttxt)+1);
self->recbut.caption=NextZTS(self->recbut.inlabel);
self->recbut.caplen=p_slen(self->recbut.caption);
}
METHOD VOID recbut_rb_draw(PR_RECBUT *self)
{
P_RECT r;
if (self->recbut.hide==RECBUT_HIDE_HIDE)
return;
r.tl.x=self->recbut.rect.tl.x-RECBUT_MARGIN;
r.br.x=self->recbut.rect.br.x+RECBUT_MARGIN;
r.br.y=self->recbut.rect.tl.y;
r.tl.y=r.br.y-(2*RECBUT_HALF_HEIGHT);
if (self->recbut.hide==RECBUT_HIDE_CLEAR)
{
gClrRect(&r,G_TRMODE_CLR);
gClrRect(&self->recbut.rect,G_TRMODE_CLR);
return;
}
DrawButton(self,0);
gPrintBoxText(&r,RECBUT_ASCENT,G_TEXT_ALIGN_CENTRE,0,self->recbut.caption,self->recbut.caplen);
}
METHOD VOID recbut_rb_depress(PR_RECBUT *self)
{
gCreateTempGC0(self->recbut.wid);
DrawButton(self,2);
wFlush();
p_sleep(2L);
DrawButton(self,0);
wFlush();
gFreeTempGC();
}
METHOD VOID recbut_rb_hide(PR_RECBUT *self,INT hide)
{
self->recbut.hide=hide;
}
METHOD VOID reccli_destroy(PR_RECCLI *self)
{
p_free(self->reccli.clitxt);
p_supersend2(self,O_DESTROY);
}
METHOD VOID reccli_wn_connect(PR_RECCLI *self,PR_WIN *par,UINT fields,W_WINDATA *pwd)
{
INT i,dx;
P_POINT c;
P_RECT rect;
E_CONFIG config;
p_getctd(&config);
self->reccli.tsep=config.timeSeparator;
self->reccli.width=pwd->extent.width;
pwd->background=W_WIN_BACK_CLR|W_WIN_BACK_GREY_CLR;
p_supersend5(self,O_WN_CONNECT,par,fields|W_WIN_BACKGROUND,pwd);
hInitVis(self);
p_send3(self,O_WN_EMPHASISE,TRUE);
rect.tl.x=12;
rect.br.x=self->reccli.width-rect.tl.x;
rect.tl.y=74;
rect.br.y=rect.tl.y+TIMEBAR_HEIGHT;
self->reccli.timebar=f_newsend(CAT_RECORD_RECORD,C_TIMEBAR,O_AO_INIT,self->win.id,&rect);
dx=(self->reccli.width-6)/6;
c.y=130;
for (i=0;i<RECCLI_NBUTTONS;i++)
{
c.x=3+dx+(((i<3)?i*dx:dx)<<1);
self->reccli.recbut[i]=f_newsend(CAT_RECORD_RECORD,C_RECBUT,O_RB_INIT,self->win.id,&c,CLIBUT_REC_NEW+i);
}
HideButtons(self,RECCLI_STOP_MASK|RECCLI_START_MASK);
hLoadResource(RECCLI_TEXT,&self->reccli.clitxt);
self->reccli.secs=(TEXT *)(((WORD *)self->reccli.clitxt)+1);
self->reccli.title=NextZTS(self->reccli.secs);
self->reccli.sub=NextZTS(self->reccli.title);
wValidateWin(self->win.id); /* saves screen flicker on startup */
}
METHOD VOID reccli_wn_draw(PR_RECCLI *self)
{
INT i,len,y;
WVEFILE_INFO info;
TEXT name[16];
TEXT duration[20],total[20];
G_GC gc;
p_supersend(self,O_WN_DRAW); /* draw border */
p_send2(self->reccli.timebar,O_TB_DRAW); /* draw time bar */
/* draw buttons */
for (i=0;i<RECCLI_NBUTTONS;recbut_rb_draw(self->reccli.recbut[i++]));
p_send3(receng,O_ENG_FILE_INFO,&info);
*p_bcpy(&name[0],info.name,len=info.nmlen)=0;
p_scap(&name[0]);
if (*info.device!='M')
{
name[len++]='[';
name[len++]=*info.device;
name[len++]=']';
}
name[len]=0;
gc.style=G_STY_BOLD;
gc.font=FONT_ID_SWISS_16;
gSetGC(0,G_GC_MASK_STYLE|G_GC_MASK_FONT,&gc);
y=8;
if (info.duration)
{
PrintDuration(self,&duration[0],(LONG)info.duration);
/* %s %s %d Kbyte */
PrintHeader(self,y,self->reccli.title,&name[0],&duration[0],(INT)(info.flen>>10));
}
else
PrintHeader(self,y,"%s",&name[0]); /* might be a % character in name[] */
y=40;
if (info.repeats<=1 && info.silence==0)
{
PrintHeader(self,y,NULL); /* clear rectangle */
return;
}
gc.style=G_STY_NORMAL;
gc.font=FONT_ID_SWISS_13;
gSetGC(0,G_GC_MASK_STYLE|G_GC_MASK_FONT,&gc);
PrintDuration(self,&duration[0],(LONG)info.silence);
PrintDuration(self,&total[0],info.total);
/* Repeats: %d Trailing silence: %s Total: %s */
PrintHeader(self,y,self->reccli.sub,info.repeats,&duration[0],&total[0]);
}
METHOD VOID reccli_cl_update(PR_RECCLI *self)
{
p_send2(self->reccli.timebar,O_TB_STOP);
self->reccli.running=FALSE;
w_ws->wserv.filter=NULL;
wDisableKeyClick(FALSE);
HideButtons(self,RECCLI_STOP_MASK|RECCLI_START_MASK);
DrawWin(self);
wFlush();
}
METHOD VOID reccli_wn_key(PR_RECCLI *self,UINT keycode,UINT modifiers)
{
switch (keycode)
{
case W_KEY_TAB:
recbut_rb_depress(self->reccli.recbut[0]);
hWservComSend(O_COM_RECORD_NEW);
break;
case ' ':
recbut_rb_depress(self->reccli.recbut[1]);
hWservComSend(O_COM_RE_RECORD);
break;
case W_KEY_RETURN:
recbut_rb_depress(self->reccli.recbut[2]);
p_send2(receng,O_ENG_SOUND_PLAY);
break;
}
}
METHOD INT reccli_cl_sound_filter(PR_RECCLI *self,UINT keycode,UINT modifiers)
{
if (keycode==W_KEY_ESCAPE)
{
p_send2(receng,O_ENG_SOUND_STOP);
recbut_rb_depress(self->reccli.recbut[3]);
}
return(WN_KEY_CHANGED);
}
METHOD INT reccli_cl_pause_filter(PR_RECCLI *self,UINT keycode,UINT modifiers)
/*
Waiting to record.
*/
{
if (keycode==W_KEY_ESCAPE)
p_send3(receng,O_ENG_OPEN_FILE,NULL);
else if (keycode==' ')
{
w_ws->wserv.filter=NULL;
p_send3(receng,O_ENG_SOUND_RECORD,self->reccli.duration);
}
return(WN_KEY_CHANGED);
}
METHOD VOID reccli_cl_begin_sound(PR_RECCLI *self,ULONG *tenths)
{
p_send3(self->reccli.timebar,O_TB_START,tenths);
self->reccli.running=TRUE;
w_ws->wserv.filter=(PR_WIN *)self;
w_ws->wserv.filmethod=-O_CL_SOUND_FILTER;
wDisableKeyClick(TRUE);
HideButtons(self,RECCLI_3BUT_MASK|RECCLI_START_MASK);
DrawWin(self);
wFlush();
}
METHOD VOID reccli_cl_pause(PR_RECCLI *self,UINT duration)
{
self->reccli.duration=duration;
w_ws->wserv.filter=(PR_WIN *)self;
w_ws->wserv.filmethod=-O_CL_PAUSE_FILTER;
HideButtons(self,RECCLI_3BUT_MASK|RECCLI_STOP_MASK);
DrawWin(self);
wFlush();
}
METHOD VOID recman_am_clean_up(PR_RECMAN *self,INT err,UBYTE *htask)
{
PR_RECCLI *cli;
cli=(PR_RECCLI *)w_ws->wserv.cli;
w_ws->wserv.filter=NULL;
wDisableKeyClick(FALSE);
p_send2(cli->reccli.timebar,O_TB_STOP);
p_supersend4(self,O_AM_CLEAN_UP,err,htask);
p_send3(receng,O_ENG_OPEN_FILE,NULL);
}
+151
View File
@@ -0,0 +1,151 @@
/*
RECCOM.C
Sound record/playback application command manager
*/
#include <record.g>
#include <record.rsg>
#include <hwim.h>
#include <s_.rsg>
GLREF_D PR_RECENG * const receng;
GLREF_D TEXT * const DatUsedPathNamePtr;
LOCAL_C INT LaunchDial(VOID *buf,INT id,INT class)
{
DL_DATA dial_data;
dial_data.id=id;
dial_data.rbuf=buf;
dial_data.pdlg=NULL;
return(hLaunchDial(CAT_RECORD_RECORD,class,&dial_data));
}
LOCAL_C VOID RecordToNewFile(TEXT *fname,INT DefaultName)
{
INT len;
P_FPARSE crk;
RECRBUF rb;
rb.duration=((RECENG_PREFS *)p_send2(receng,O_ENG_SENSE_PREFS))->duration;
f_fparse(fname,DatUsedPathNamePtr,&rb.fname[0],&crk);
len=crk.system+crk.device+crk.path;
if (DefaultName)
len+=crk.name;
rb.fname[len]=0;
if (!LaunchDial(&rb,RECORD_NEW_DL,DefaultName?C_RECNEWDEF:C_RECNEW))
p_send3(receng,O_ENG_OPEN_FILE,NULL);
}
#pragma METHOD_CALL
METHOD INT reccom_com_file_change(PR_RECCOM *self,INT command,TEXT *newname)
{
p_send2(receng,O_ENG_SOUND_STOP);
switch (command)
{
case H_COMMAND_CREATE_FILE:
p_send3(receng,O_ENG_NEW_FILE,newname);
p_send2(receng,O_ENG_VIEW_UPDATE);
RecordToNewFile((TEXT *)p_send2(receng,O_ENG_SENSE_FILE),TRUE);
break;
case H_COMMAND_OPEN_FILE:
p_send3(receng,O_ENG_OPEN_FILE,newname);
break;
}
return(0); /* no leave() */
}
METHOD VOID reccom_com_new_file(PR_RECCOM *self)
/*
Called on selecting the New file menu command.
*/
{
TEXT fspec[4];
fspec[0]=p_send2(receng,O_ENG_DEFAULT_DISK);
fspec[1]=':';
fspec[2]=0;
RecordToNewFile(&fspec[0],FALSE);
}
METHOD VOID reccom_com_record_new(PR_RECCOM *self)
/*
Called on pressing the Record new (Tab) button.
*/
{
INT i,device;
P_INFO info;
TEXT name[32];
TEXT fspec[P_FNAMESIZE];
device=p_send2(receng,O_ENG_DEFAULT_DISK);
for (i=1;i<100;i++)
{
hAtos(&name[0],DFLT_FNAME,device,i); /* "%c:RECORD%02d" */
p_fparse(&name[0],DatUsedPathNamePtr,&fspec[0],NULL);
if (p_finfo(&fspec[0],&info))
{ /* file does not exist - so use the generated name */
RecordToNewFile(&fspec[0],TRUE);
return;
}
}
RecordToNewFile("",FALSE);
}
METHOD VOID reccom_com_open_file(PR_RECCOM *self)
/*
Called on selecting the Open file menu command.
*/
{
RECRBUF rb;
p_scpy(&rb.fname[0],(TEXT *)p_send2(receng,O_ENG_SENSE_FILE));
if (!LaunchDial(&rb,OPEN_FILE_DL,C_RECOPEN))
return;
/* rb.fname[] contains file name */
p_send3(receng,O_ENG_OPEN_FILE,&rb.fname);
}
METHOD VOID reccom_com_re_record(PR_RECCOM *self)
/*
Called on pressing the Record over (Space) button.
*/
{
TEXT *fname;
WVEFILE_INFO info;
P_INFO finfo;
RECRBUF rb;
p_send3(receng,O_ENG_FILE_INFO,&info);
fname=(TEXT *)p_send2(receng,O_ENG_SENSE_FILE);
if (!info.duration)
{ /* file does not exist? */
if (p_finfo(fname,&finfo)<0)
RecordToNewFile(fname,TRUE);
return;
}
rb.duration=info.duration;
p_scpy(&rb.fname[0],fname);
if (!LaunchDial(&rb,RE_RECORD_DL,C_RECEXIST))
return;
}
METHOD VOID reccom_com_set_repeat(PR_RECCOM *self)
{
LaunchDial(NULL,SET_REP_DL,C_SETREP);
}
METHOD VOID reccom_com_rep_alarm(PR_RECCOM *self)
{
if (!hConfirm(ADJUST_ALARM_CONFIRM))
return;
p_send4(receng,O_ENG_SET_REPEATS,0,150); /* set total time to 15 seconds */
}
METHOD VOID reccom_com_preferences(PR_RECCOM *self)
{
LaunchDial(NULL,PREFERENCES_DL,C_SETPREF);
}
+190
View File
@@ -0,0 +1,190 @@
/*
RECDIAL.C
Sound record/playback command dialogs
*/
#include <record.g>
#include <record.rsg>
#include <hwim.h>
#include <p_math.h>
#include <s_.rsg>
GLREF_D PR_RECENG * const receng;
GLREF_D PR_RECWSERV * const w_ws;
LOCAL_C VOID TenthsToDouble(DOUBLE *pdbl,UINT tenths)
/*
Convert 10ths of a second to a double float.
*/
{
WORD ten,x;
DOUBLE c;
x=tenths;
p_itof(pdbl,&x);
ten=10;
p_itof(&c,&ten);
p_fdiv(pdbl,&c);
}
LOCAL_C INT DoubleToTenths(DOUBLE *pdbl)
/*
Convert a double float to 10ths of a second.
*/
{
WORD x;
DOUBLE c;
x=10;
p_itof(&c,&x);
p_fmul(&c,pdbl);
p_inti(&x,&c);
return(x);
}
LOCAL_C VOID SetTenthsFledit(INT item,UINT val)
{
DOUBLE dbl;
TenthsToDouble(&dbl,val);
hDlgSetFledit(item,&dbl);
}
LOCAL_C INT SenseTenthsFledit(INT item)
{
DOUBLE dbl;
hDlgSenseFledit(item,&dbl);
return(DoubleToTenths(&dbl));
}
#pragma METHOD_CALL
METHOD VOID setrep_dl_dyn_init(PR_SETREP *self)
/*
Dialog for setting repeat count and trailing silence.
*/
{
WVEFILE_INFO info;
p_send3(receng,O_ENG_FILE_INFO,&info);
hDlgSetNcedit(1,info.repeats);
SetTenthsFledit(2,info.silence);
}
METHOD INT setrep_dl_key(PR_SETREP *self,INT index,INT keycode)
/*
Dialog for setting repeat count and trailing silence.
*/
{
UINT repeats,silence;
repeats=hDlgSenseNcedit(1);
silence=SenseTenthsFledit(2);
p_send4(receng,O_ENG_SET_REPEATS,repeats,silence);
return(WN_KEY_CHANGED);
}
METHOD VOID setpref_dl_dyn_init(PR_SETPREF *self)
/*
Dialog for setting record/playback preferences.
*/
{
RECENG_PREFS *pprefs;
pprefs=(RECENG_PREFS *)p_send2(receng,O_ENG_SENSE_PREFS);
hDlgSetChlist(1,pprefs->volume);
SetTenthsFledit(2,pprefs->duration);
hDlgSetChlist(3,pprefs->disk);
}
METHOD INT setpref_dl_key(PR_SETPREF *self,INT index,INT keycode)
/*
Dialog for setting record/playback preferences.
*/
{
RECENG_PREFS prefs;
prefs.volume=hDlgSenseChlist(1);
prefs.disk=hDlgSenseChlist(3);
prefs.duration=SenseTenthsFledit(2);
p_send3(receng,O_ENG_SET_PREFS,&prefs);
return(WN_KEY_CHANGED);
}
METHOD VOID recnew_dl_dyn_init(PR_RECNEW *self)
/*
The dialog for recording to a new file.
*/
{
RECRBUF *prb;
prb=(RECRBUF *)self->dlgbox.rbuf;
if (prb->fname[0])
hDlgSet(1,&prb->fname[0]);
SetTenthsFledit(3,prb->duration);
}
METHOD VOID recnewdef_dl_set_size(PR_RECNEWDEF *self)
{
p_supersend2(self,O_DL_SET_SIZE);
hDlgTakeFocus(3);
}
METHOD INT recnew_dl_key(PR_RECNEW *self,INT index,INT keycode)
/*
All dialogs for recording to a new or existing file share this code.
*/
{
RECRBUF *prb;
INT MaxDuration;
prb=(RECRBUF *)self->dlgbox.rbuf;
hDlgSense(1,&prb->fname[0]);
prb->duration=SenseTenthsFledit(3);
MaxDuration=p_send3(receng,O_ENG_NEW_FILE,&prb->fname[0]);
if (MaxDuration<0)
{
if (MaxDuration==E_FILE_VOLUME)
hInfoPrint(NO_RECORD_FLASH);
else
hInfoPrintErr(MaxDuration);
return(WN_KEY_NO_CHANGE);
}
if (prb->duration/10>MaxDuration)
{
SetTenthsFledit(3,10*MaxDuration);
hInfoPrint(NO_SPACE_RESET);
return(WN_KEY_NO_CHANGE);
}
p_send3(w_ws->wserv.cli,O_CL_PAUSE,prb->duration);
return(WN_KEY_CHANGED);
}
METHOD VOID recexist_dl_dyn_init(PR_RECEXIST *self)
/*
The dialog for recording to an existing file.
*/
{
hDlgSet(1,&((RECRBUF *)self->dlgbox.rbuf)->fname[0]);
p_supersend2(self,O_DL_DYN_INIT);
}
METHOD VOID recexist_dl_set_size(PR_RECEXIST *self)
/*
The dialog for recording to an existing file.
*/
{
p_supersend2(self,O_DL_SET_SIZE);
hDlgTakeFocus(3);
}
METHOD INT recopen_dl_key(PR_RECOPEN *self,INT index,INT keycode)
/*
The dialog for opening a file.
*/
{
hDlgSense(1,&((RECRBUF *)self->dlgbox.rbuf)->fname[0]);
return(WN_KEY_CHANGED);
}
+202
View File
@@ -0,0 +1,202 @@
/*
RECENG.C
Sound record/playback application engine
*/
#include <p_std.h>
#include <p_sys.h>
#include <p_gen.h>
#include <p_file.h>
#include <epoc.h>
#include <record.g>
#include <record.rsg>
#include <hwim.h>
#include <s_.rsg>
#define RECENG_ENVNAME "REC$PREF"
#define RECENG_ENVNAMELEN 8
GLREF_D PR_HWIMMAN * const w_am;
LOCAL_C UINT ConvDurationTo2Ks(UINT tenths)
/*
Convert 10ths of a second to 2Kbyte units
*/
{
return((tenths*25+0x3f)>>6);
}
LOCAL_C INT IsDeviceSuitable(INT device)
{
P_DINFO dinfo;
TEXT dspec[16];
if (device!='M')
{
p_scpy(&dspec[0],"LOC::M:");
dspec[P_FSYSNAMESIZE]=device;
p_dinfo(&dspec[0],&dinfo);
return((dinfo.mediatype&0xff)==P_FMEDIA_RAM);
}
return(TRUE);
}
LOCAL_C INT DiskToDevice(INT disk)
{
if (disk==0)
return('A');
if (disk==1)
return('M');
if (disk==2)
return('B');
}
LOCAL_C VOID CheckSoundCompletion(INT stat)
{
if (stat==E_GEN_FAIL)
hInfoPrint(-SYS_SOUND_DISABLED);
else
f_leave(stat);
}
#pragma METHOD_CALL
METHOD VOID receng_eng_init(PR_RECENG *self,PR_ROOT *hview,UINT mupdate,UINT msound)
{
self->receng.prefs.duration=20; /* two seconds */
self->receng.prefs.disk=1; /* Internal (M:) */
self->receng.hview=hview;
self->receng.mupdate=mupdate;
self->receng.msound=msound;
self->receng.wvefile=f_new(CAT_RECORD_RECORD,C_WVEFILE);
self->receng.waveao=f_newsend(CAT_RECORD_RECORD,C_WAVEAO,O_AO_INIT,self,O_ENG_DONE_RECORD,O_ENG_DONE_PLAY);
}
METHOD TEXT *receng_eng_sense_file(PR_RECENG *self)
{
return((TEXT *)p_send2(self->receng.wvefile,O_WVE_SENSE_FNAME));
}
METHOD INT receng_eng_default_disk(PR_RECENG *self)
/*
Returns the default device letter for new recordings.
Based on the "dialog" local disk number (0:A, 1:M, 2:B).
Guaranteed to return a suitable disk.
*/
{
INT device;
TEXT fspec[P_FNAMESIZE];
p_send2(self,O_ENG_SENSE_PREFS);
device=DiskToDevice(self->receng.prefs.disk); /* try user-specified preference first */
if (!IsDeviceSuitable(device))
{ /* preference is unsuitable */
device='M'; /* fallback if the default device is unsuitable */
p_getpth(&fspec[0]);
if (IsDeviceSuitable(fspec[P_FSYSNAMESIZE]))
device=fspec[P_FSYSNAMESIZE];
}
return(device);
}
METHOD VOID receng_eng_view_update(PR_RECENG *self)
{
p_send2(self->receng.hview,self->receng.mupdate);
}
METHOD INT receng_eng_new_file(PR_RECENG *self,TEXT *pname)
{
return(p_send3(self->receng.wvefile,O_WVE_NEW,pname));
}
METHOD VOID receng_eng_open_file(PR_RECENG *self,TEXT *pname)
{
p_send3(self->receng.wvefile,O_WVE_OPEN,pname);
p_send3(w_am,O_AM_NEW_FILENAME,receng_eng_sense_file(self));
receng_eng_view_update(self);
}
METHOD VOID receng_eng_done_record(PR_RECENG *self,INT stat)
{
CheckSoundCompletion(stat);
receng_eng_open_file(self,NULL);
}
METHOD VOID receng_eng_done_play(PR_RECENG *self,INT stat)
{
CheckSoundCompletion(stat);
receng_eng_view_update(self);
}
METHOD VOID receng_eng_sound_play(PR_RECENG *self)
{
INT v;
WVEFILE_INFO info;
p_send2(self,O_ENG_SENSE_PREFS);
v=0; /* loud */
if (self->receng.prefs.volume==1)
v=2; /* medium */
else if (self->receng.prefs.volume==2)
v=5; /* quiet */
p_send3(self->receng.wvefile,O_WVE_SENSE_INFO,&info);
if (info.duration==0)
{
hInfoPrint(NO_DATA_NO_PLAY);
return;
}
p_send4(self->receng.waveao,O_WV_PLAY,p_send2(self->receng.wvefile,O_WVE_SENSE_FNAME),v);
p_send3(self->receng.hview,self->receng.msound,&info.total);
}
METHOD VOID receng_eng_sound_record(PR_RECENG *self,UINT duration)
{
UINT num2Ks;
ULONG tenths;
TEXT *name;
num2Ks=ConvDurationTo2Ks(duration);
tenths=num2Ks;
tenths=(tenths<<6)/25;
name=(TEXT *)p_send2(self->receng.wvefile,O_WVE_SENSE_FNAME);
if (name[P_FSYSNAMESIZE]=='M')
p_delete(name); /* free space for the sound server */
p_send4(self->receng.waveao,O_WV_RECORD,name,num2Ks);
p_send3(self->receng.hview,self->receng.msound,&tenths);
}
METHOD VOID receng_eng_sound_stop(PR_RECENG *self)
{
p_send2(self->receng.waveao,O_WV_STOP);
}
METHOD VOID receng_eng_set_repeats(PR_RECENG *self,UINT repeats,UINT tenths)
{
p_send4(self->receng.wvefile,O_WVE_SET_REPEATS,repeats,tenths);
receng_eng_view_update(self);
}
METHOD VOID receng_eng_file_info(PR_RECENG *self,WVEFILE_INFO *pi)
{
p_send3(self->receng.wvefile,O_WVE_SENSE_INFO,pi);
}
METHOD RECENG_PREFS *receng_eng_sense_prefs(PR_RECENG *self)
{
INT len;
TEXT bb[P_ENVMAX];
len=p_getenviron(RECENG_ENVNAME,RECENG_ENVNAMELEN,&bb[0]);
if (len==sizeof(RECENG_PREFS))
self->receng.prefs=*(RECENG_PREFS *)&bb[0];
return(&self->receng.prefs);
}
METHOD VOID receng_eng_set_prefs(PR_RECENG *self,RECENG_PREFS *new)
{
if (!p_bcmp(&self->receng.prefs,sizeof(RECENG_PREFS),new,sizeof(RECENG_PREFS)))
return; /* no change */
self->receng.prefs=*new;
f_leave(p_setenviron(RECENG_ENVNAME,RECENG_ENVNAMELEN,&self->receng.prefs,sizeof(RECENG_PREFS)));
}
+3
View File
@@ -0,0 +1,3 @@
record.pic
record.rzc
record.shd
+244
View File
@@ -0,0 +1,244 @@
IMAGE record
EXTERNAL olib
EXTERNAL hwim
INCLUDE p_std.h
INCLUDE p_gen.h
INCLUDE p_que.h
INCLUDE p_object.h
INCLUDE p_file.h
INCLUDE epoc.h
INCLUDE wlib.h
INCLUDE olib.g
INCLUDE varray.g
INCLUDE appman.g
INCLUDE timer.g
INCLUDE bwin.g
INCLUDE matcher.g
INCLUDE listbox.g
INCLUDE pulldown.g
INCLUDE hwimman.g
CLASS waveao active
Sound file record and play
{
REPLACE ao_init Queue into appman and init callback
REPLACE ao_run Call back
REPLACE ao_cancel Cancel sound
ADD wv_record Start recording a file
ADD wv_play Start playing a file
ADD wv_stop Start playing/recording a file
PROPERTY
{
WORD request; Request type
PR_ROOT *hdone; Callback handle on completion
UWORD done_record; Callback method on record completion
UWORD done_play; Callback method on playback completion
}
}
CLASS wvefile root
Sound file
{
ADD wve_new Create a new file
ADD wve_open Open an existing file
ADD wve_sense_fname Sense the file name (for reading)
ADD wve_sense_info Fill in a WVEFILE_INFO struct
ADD wve_set_repeats Set the repeat and silence
TYPES
{
typedef struct
{
TEXT *device; address of device character
TEXT *name; file name component
WORD ret; possible error return
WORD nmlen; length of file name
UWORD duration; duration in 10ths of a sec
UWORD silence; silence in 10ths of a second
UWORD repeats; number of repeats
ULONG total; total time in seconds (with repeats & silence)
ULONG samples; number of samples
ULONG flen; file length
} WVEFILE_INFO;
}
PROPERTY
{
VOID *fcb;
WORD ret;
P_FPARSE crk;
TEXT fname[P_FNAMESIZE];
P_INFO info;
SndFile head;
}
}
CLASS receng root
{
ADD eng_init
ADD eng_new_file Start a new file
ADD eng_open_file Open an existing file (close any current file)
ADD eng_sense_file Get the current file name
ADD eng_file_info Get information on the current file
ADD eng_default_disk Return default device for new file
ADD eng_view_update Call back view to update itself
ADD eng_done_record Callback from active object on record completion
ADD eng_done_play Callback from active object on play completion
ADD eng_sound_play Play the current file
ADD eng_sound_record Record to the current file
ADD eng_sound_stop Stop the current record or playback
ADD eng_set_repeats Set the number of repeats and trailing silence
ADD eng_set_prefs Set the persistent preferences
ADD eng_sense_prefs Sense the persistent preferences
TYPES
{
typedef struct
{
WORD volume; volume for playback
WORD duration; maximum duration in 10ths of a sec
WORD disk; preferred disk for new files
} RECENG_PREFS;
}
PROPERTY 2
{
PR_WVEFILE *wvefile; digital sound file
PR_WAVEAO *waveao; record/play active object
PR_ROOT *hview; callback view handle
UWORD mupdate; callback view method for update
UWORD msound; callback view method for begin sound
RECENG_PREFS prefs; persistent preferences
}
}
CLASS reccom comman
{
REPLACE com_file_change from System application
ADD com_set_repeat Set repeat menu command
ADD com_rep_alarm Repeat for alarm menu command
ADD com_preferences Set preferences menu command
ADD com_new_file New file menu command
ADD com_open_file Open file menu command
ADD com_record_new Record new (Tab) button
ADD com_re_record Record over (Space) button
TYPES
{
typedef struct
{
WORD duration;
TEXT fname[P_FNAMESIZE];
} RECRBUF;
}
}
CLASS recman hwimman
{
REPLACE am_clean_up
}
CLASS recwserv wserv
{
REPLACE ws_dyn_init
}
CLASS timebar active
{
REPLACE ao_init Queue into appman and set priority
REPLACE ao_queue Queue next read
REPLACE ao_run Update on tick
ADD tb_start Start time bar
ADD tb_stop Stop time bar
ADD tb_draw For redraw
PROPERTY
{
WORD visible; Visible if TRUE
WORD wid; Window id of landlord
LONG tenths0; Initial value of timer
LONG tenths; Counted down value of timer
WORD x; Bar value in pixels
P_RECT rect; Bar rectangle
}
}
CLASS recbut root
{
REPLACE destroy
ADD rb_init
ADD rb_draw
ADD rb_depress
ADD rb_hide
PROPERTY
{
WORD hide; Hide button if TRUE
WORD wid; Window id of landlord
P_RECT rect; Button rectangle
VOID *buttxt; As loaded from resource file
TEXT *inlabel; Button label
TEXT *caption; Caption above button
WORD caplen; Caption length
}
}
CLASS reccli bwin
{
REPLACE destroy
REPLACE wn_connect
REPLACE wn_draw
REPLACE wn_key
ADD cl_update Viewed data has changed
ADD cl_sound_filter To catch keys while recording or playing
ADD cl_pause_filter To catch keys while waiting to record
ADD cl_begin_sound
ADD cl_pause
PROPERTY 6
{
PR_TIMEBAR *timebar;
PR_RECBUT *recbut[5];
UINT duration; Stored for pause to record
WORD running; TRUE if sound record/play running
WORD width; Window width
VOID *clitxt; Allocated resource
TEXT *secs; Seconds suffix
TEXT *title; Title format string
TEXT *sub; Subtitle format string
TEXT tsep; Time separator
UBYTE spare;
}
}
CLASS setrep dlgbox
{
REPLACE dl_dyn_init
REPLACE dl_key
}
CLASS setpref dlgbox
{
REPLACE dl_dyn_init
REPLACE dl_key
}
CLASS recnew dlgbox
Record to new file dialog
{
REPLACE dl_dyn_init
REPLACE dl_key
}
CLASS recnewdef recnew
Record to new file dialog with a default name
{
REPLACE dl_set_size
}
CLASS recexist recnew
Record to existing file dialog
{
REPLACE dl_dyn_init
REPLACE dl_set_size
}
CLASS recopen dlgbox
Open file dialog
{
REPLACE dl_key
}
+60
View File
@@ -0,0 +1,60 @@
/*
RECORD.HLP
Help file for Series 3a RECORD app
*/
RESOURCE HELP_ARRAY record_help
{
topic="Record";
topic_id=record_help_index;
}
RESOURCE TOPIC_ARRAY record_help_index
{
id_lst=
{
record_alarms,
record_voice
};
}
RESOURCE HELP_ARRAY record_alarms
{
topic="Recording alarm sounds";
strlst=
{
STRING {str="Use `New file' (or Tab) to start recording to a file";},
STRING {str="Press Enter to play it back ";},
STRING {str="To try again, use Space to record to the same file";},
STRING {str="";},
STRING {str="Esc stops recording or playback";},
STRING {str="";},
STRING {str="Sound files have a built-in "<34>"number of repeats"<34>" and length";},
STRING {str="of silence between the repeats. Set these with `Set repeat'";},
STRING {str="";},
STRING {str="Sound files appear automatically in `Set alarm' dialogs";}
};
}
RESOURCE HELP_ARRAY record_voice
{
topic="Recording voice notes";
strlst=
{
STRING {str="In the System screen, move to `Record' and use";},
STRING {str="`Create new list' and change the `Directory for files'";},
STRING {str="line. Then voice recordings will not appear in the";},
STRING {str="`Set alarm' dialogs";},
STRING {str="";},
STRING {str="Use `Assign button' and make a button-press go";},
STRING {str="to this list";},
STRING {str="";},
STRING {str="Use this button-press, then Tab, Enter and Space";},
STRING {str="to record each new note";}
};
}
+3
View File
@@ -0,0 +1,3 @@
Record.WVE
\WVE\
1003
Binary file not shown.
+46
View File
@@ -0,0 +1,46 @@
#system epoc img
#set epocinit=iplib
#model small jpi
#abort on
#set version=0x118F
#set priority=0x80
#set heapsize=0x48
#compile %main.cat
#if %remake #or (%main.rg #older %main.re) #or (%main.rg #older %main.g) #then
#run "re %main" no_window no_abort
#endif
#if (%main.rsg #older %main.rss) #or (%main.rsg #older %main.rg) #then
#file delete %main.rsg
#run "rs %main" no_window no_abort
#endif
#if %main.rzc #older %main.rsg #then
#run "rch %main" no_window no_abort
#endif
#compile reccli.c
#compile reccom.c
#compile recdial.c
#compile receng.c
#compile recwserv.c
#compile waveao.c
#compile wvefile.c
#if %main.shd #older %main.ms #then
#run "makeshd %main" no_window no_abort
#file delete %main.img
#endif
#if (%main.img #older %main.afl) #or (%main.img #older %main.pic) #then
#file delete %main.img
#endif
#pragma link(olib.lib)
#pragma link(hwim.lib)
#link %main
+9
View File
@@ -0,0 +1,9 @@
#include <record.g>
_C_RECCOM
_O_COM_EXIT
_O_COM_SET_REPEAT
_O_COM_REP_ALARM
_O_COM_PREFERENCES
_O_COM_NEW_FILE
_O_COM_OPEN_FILE
+354
View File
@@ -0,0 +1,354 @@
/*
RECORD.RSS
Resource file for Sound recording Handheld Application
*/
#include <hwim.rg>
#include <hwim.rh>
#include <record.rg>
RESOURCE WSERV_INFO record_accs
{
menbar_id=record_menu;
first_com=O_COM_EXIT;
/* follows order in cat file command manager */
accel={'x', /* Exit */
'r', /* Set repeat */
'a', /* Repeat for alarm */
'q', /* Set preferences */
'n', /* New file */
'o' /* Open file */
};
}
RESOURCE MENU_BAR record_menu
{
items =
{
MENU_BAR_ITEM
{
menu_id=file_menu;
mb_item="File";
},
MENU_BAR_ITEM
{
menu_id=repeats_menu;
mb_item="Repeats";
},
MENU_BAR_ITEM
{
menu_id=special_menu;
mb_item="Special";
}
};
}
RESOURCE MENU file_menu
{
items =
{
MENU_ITEM
{
com_id=O_COM_NEW_FILE;
mn_item="New file";
},
MENU_ITEM
{
com_id=O_COM_OPEN_FILE;
mn_item="Open file";
}
};
}
RESOURCE MENU repeats_menu
{
items =
{
MENU_ITEM
{
com_id=O_COM_SET_REPEAT;
mn_item="Set repeat";
},
MENU_ITEM
{
com_id=O_COM_REP_ALARM;
mn_item="Adjust for alarm";
}
};
}
RESOURCE MENU special_menu
{
items =
{
MENU_ITEM
{
com_id=O_COM_PREFERENCES;
mn_item="Set preferences";
},
MENU_ITEM
{
com_id=O_COM_EXIT;
mn_item="Exit";
}
};
}
RESOURCE STRING dflt_fname { str="%c:RECORD%02d"; }
RESOURCE STRING no_space_reset { str="Insufficient disk space - Maximum duration reset"; }
RESOURCE STRING no_record_flash { str="Can't record to a Flash SSD"; }
RESOURCE STRING no_data_no_play { str="No sound to play"; }
RESOURCE STRING adjust_alarm_confirm { str="Adjust repeat for use as an alarm"; }
/* DIALOG RESOURCES */
RESOURCE DIALOG set_rep_dl
/* Dialog used by the "Set repeat" menu item */
{
title="Set repeat";
flags=DLGBOX_NOTIFY_ENTER;
controls=
{
CONTROL
{
class=C_NCEDIT;
prompt="Repeat count";
info=NCEDIT
{
low=1;
high=1000;
};
},
CONTROL
{
class=C_FLTEDIT;
prompt="Trailing silence (sec)";
info=FLTEDIT
{
low=0.0;
high=1000.0;
ndec=1;
};
}
};
}
RESOURCE MENU volume_list
{
items=
{
CHOICE_ITEM {str="Loud";},
CHOICE_ITEM {str="Medium";},
CHOICE_ITEM {str="Quiet";}
};
}
RESOURCE MENU disk_list
{
items=
{
CHOICE_ITEM {str="A";},
CHOICE_ITEM {str="Internal";},
CHOICE_ITEM {str="B";}
};
}
RESOURCE DIALOG preferences_dl
/* Dialog used by the "Set preferences" menu item */
{
title="Set preferences";
flags=DLGBOX_NOTIFY_ENTER;
controls=
{
CONTROL
{
class=C_CHLIST;
prompt="Playback volume";
info=CHLIST{rid=volume_list;};
},
CONTROL
{
class=C_FLTEDIT;
prompt="Default duration (sec)";
info=FLTEDIT
{
low=0.0;
high=3000.0;
ndec=1;
};
},
CONTROL
{
class=C_CHLIST;
prompt="Default disk for new files";
info=CHLIST{rid=disk_list;};
}
};
}
RESOURCE DIALOG open_file_dl
/* Dialog used by the "Open file" menu item */
{
title="Open file";
flags=DLGBOX_NOTIFY_ENTER|DLGBOX_RBUF_FILLED;
controls=
{
CONTROL
{
flags=DLGBOX_ITEM_NEEDS_PACK;
class=C_FNSELWN;
prompt="File:";
info=FNSELWN
{
flags=IN_FNSELWN_STANDARD;
fname="";
};
}
};
}
RESOURCE DIALOG record_new_dl
/* Dialog presented before recording to a new file */
{
title="Record to new file";
flags=DLGBOX_NOTIFY_ENTER|DLGBOX_RBUF_FILLED;
controls=
{
CONTROL
{
flags=DLGBOX_ITEM_NEEDS_PACK;
class=C_FNEDIT;
prompt="File:";
info=FNEDIT
{
flags=IN_FNEDIT_STANDARD;
fname="";
};
},
CONTROL
{
class=C_FLTEDIT;
prompt="Maximum duration (sec)";
info=FLTEDIT
{
low=0.0;
high=3000.0;
current=0.0;
ndec=1;
};
}
};
}
RESOURCE DIALOG re_record_dl
/* Dialog presented before recording to an existing file */
{
title="Record over existing file";
flags=DLGBOX_NOTIFY_ENTER|DLGBOX_RBUF_FILLED;
controls=
{
CONTROL
{
flags=DLGBOX_ITEM_NEEDS_PACK;
class=C_FNSELWN;
prompt="File:";
info=FNSELWN
{
flags=IN_FNSELWN_STANDARD;
fname="";
};
},
CONTROL
{
class=C_FLTEDIT;
prompt="Maximum duration (sec)";
info=FLTEDIT
{
low=0.0;
high=3000.0;
current=0.0;
ndec=1;
};
},
CONTROL
{
class=C_TEXTWIN;
flags=DLGBOX_ITEM_CENTRE|DLGBOX_ITEM_DEAD;
info=TXTMESS
{
flags=IN_TEXTWIN_AL_CENTRE;
str="The data in the existing file will be replaced";
};
}
};
}
RESOURCE STRING_ARRAY reccli_text
{
strlst=
{
STRING { str="sec"; },
STRING { str="%s %s %d Kbyte"; },
STRING { str="Repeats: %d Trailing silence: %s Total: %s"; }
};
}
/* The order of the following 5 items must not be changed */
RESOURCE STRING_ARRAY clibut_rec_new
/* "Record new" button */
{
strlst=
{
STRING {str="Tab";}, /* button text */
STRING {str="Record new";} /* button label */
};
}
RESOURCE STRING_ARRAY clibut_rec_over
/* "Record over" button */
{
strlst=
{
STRING {str="Space";}, /* button text */
STRING {str="Record over";} /* button label */
};
}
RESOURCE STRING_ARRAY clibut_play
/* "Play" button */
{
strlst=
{
STRING {str="Enter";}, /* button text */
STRING {str="Play";} /* button label */
};
}
RESOURCE STRING_ARRAY clibut_stop
/* "Stop" button */
{
strlst=
{
STRING {str="Esc";}, /* button text */
STRING {str="Stop";} /* button label */
};
}
RESOURCE STRING_ARRAY clibut_start
/* "Start recording" button */
{
strlst=
{
STRING {str="Space";}, /* button text */
STRING {str="Start recording";} /* button label */
};
}
#include "record.hlp"
+55
View File
@@ -0,0 +1,55 @@
/*
RECWSERV.C
Wserv subclass for Sound record/playback application
*/
#include <hwim.g>
#include <record.g>
#include <gate.g>
#include <hwim.h>
#include <record.rsg>
GLREF_D PR_HWIMMAN * const w_am;
GLREF_D UBYTE *DatCommandPtr;
GLREF_D UBYTE *DatUsedPathNamePtr;
GLREF_D WSERV_SPEC *wserv_channel;
GLREF_D PR_GATE *DatGate;
GLDEF_D PR_RECENG *receng;
#pragma METHOD_CALL
GLDEF_C VOID main(VOID)
{
IN_HWIMMAN app;
IN_WSERV ws;
p_linklib(0);
app.flags=FLG_APPMAN_FULLSCREEN|FLG_APPMAN_RSCFILE|FLG_APPMAN_CLEAN|
FLG_APPMAN_SRSCFILE;
app.wserv_cat=ws.com_cat=p_getlibh(CAT_RECORD_RECORD);
app.wserv_class=C_RECWSERV;
ws.com_class=C_RECCOM;
p_send4(p_new(CAT_RECORD_RECORD,C_RECMAN),O_AM_INIT,&app,&ws);
}
METHOD VOID recwserv_ws_dyn_init(PR_RECWSERV *self)
{
W_WINDATA wd;
p_setpth("\\WVE\\");
wd.extent.tl.x=0;
wd.extent.tl.y=0;
wd.extent.height=wserv_channel->conn.info.pixels.y;
wd.extent.width=wserv_channel->conn.info.pixels.x-DatGate->gate.x.bsww;
self->wserv.cli=f_newsend(CAT_RECORD_RECORD,C_RECCLI,
O_WN_CONNECT,NULL,W_WIN_EXTENT,&wd);
wsSetList(W_STATUS_WINDOW_ICON,NULL,W_STATUS_WIN_NO_DIAMOND);
wStatusWindow(W_STATUS_WINDOW_BIG);
self->wserv.help_index_id=RECORD_HELP;
receng=f_newsend(CAT_RECORD_RECORD,C_RECENG,O_ENG_INIT,self->wserv.cli,O_CL_UPDATE,O_CL_BEGIN_SOUND);
p_send4(self->wserv.com,O_COM_FILE_CHANGE,w_am->hwimman.command,
DatUsedPathNamePtr);
}
+22
View File
@@ -0,0 +1,22 @@
@echo off
goto X%1X
:Xv0X
:XoffX
set jpivid=v0
echo VID is now OFF
goto :end
:Xv2X
:XonX
set jpivid=v2
echo VID is now ON
goto :end
:XX
call checkvid
goto %jpivid%
:v0
echo VID is OFF
goto end
:v2
echo VID is ON
:end
+64
View File
@@ -0,0 +1,64 @@
/*
WAVEAO.C
Active object to record and playback sound
*/
#include <record.g>
#define WAVEAO_REQUEST_RECORD 0
#define WAVEAO_REQUEST_PLAY 1
GLREF_D PR_APPMAN * const w_am;
#pragma METHOD_CALL
METHOD VOID waveao_ao_init(PR_WAVEAO *self,PR_ROOT *hdone,UINT done_record,UINT done_play)
{
self->active.priority=PRIORITY_ACTIVE_VOICE;
p_send3(w_am,O_AM_ADD_TASK,self);
self->waveao.hdone=hdone;
self->waveao.done_record=done_record;
self->waveao.done_play=done_play;
}
METHOD INT waveao_ao_run(PR_WAVEAO *self)
{
if (self->active.stat==E_FILE_CANCEL)
self->active.stat=0;
p_send3(self->waveao.hdone,(self->waveao.request==WAVEAO_REQUEST_RECORD)?
self->waveao.done_record:self->waveao.done_play,self->active.stat);
return(RUN_ACTIVE_USED);
}
METHOD VOID waveao_ao_cancel(PR_WAVEAO *self)
{
p_playsoundcancel(); /* entirely equivalent to p_recordsoundcancel */
p_supersend2(self,O_AO_CANCEL);
}
METHOD VOID waveao_wv_play(PR_WAVEAO *self,TEXT *name,UINT volume)
{
if (!self->active.isactive)
{
p_playsounda(name,0,volume,&self->active.stat);
self->active.isactive=TRUE;
self->waveao.request=WAVEAO_REQUEST_PLAY;
}
}
METHOD VOID waveao_wv_record(PR_WAVEAO *self,TEXT *name,UINT len)
{
if (!self->active.isactive)
{
p_recordsounda(name,len,&self->active.stat);
self->active.isactive=TRUE;
self->waveao.request=WAVEAO_REQUEST_RECORD;
}
}
METHOD VOID waveao_wv_stop(PR_WAVEAO *self)
{
p_playsoundcancel(); /* entirely equivalent to p_recordsoundcancel */
}
+190
View File
@@ -0,0 +1,190 @@
/*
WVEFILE.C
Sound record/playback sound file
*/
#include <p_std.h>
#include <p_gen.h>
#include <p_que.h>
#include <p_object.h>
#include <p_file.h>
#include <wlib.h>
#include <hwim.h>
#include <record.g>
LOCAL_C ULONG SamplesToTenths(ULONG samples)
{
return((samples>>4)/50);
}
LOCAL_C ULONG EffectiveSamples(ULONG samples)
/*
Converts the number of byte samples to the effective number of
samples for playback by rounding up to the nearest 0x800 (2K)
boundary and adding another 0x600.
*/
{
return(((samples+0x7ff)&(~0x7ff))+0x600);
}
LOCAL_C VOID CloseFile(PR_WVEFILE *self)
{
p_close(self->wvefile.fcb);
self->wvefile.fcb=NULL;
}
LOCAL_C VOID StoreFileName(PR_WVEFILE *self,TEXT *fname)
{
CloseFile(self);
f_fparse(fname,NULL,&self->wvefile.fname[0],&self->wvefile.crk);
hEnsurePath(&self->wvefile.fname[0]);
}
#pragma METHOD_CALL
METHOD INT wvefile_wve_new(PR_WVEFILE *self,TEXT *fname)
/*
Return the maximum duration in seconds consistent with the space on fspec
as a positive number. Otherwise return a negative error number.
*/
{
UINT minfree;
INT SSDType;
P_DINFO dinfo;
StoreFileName(self,fname);
p_dinfo(&self->wvefile.fname[0],&dinfo);
minfree=0x1000; /* need at least approx half a seconds worth of space */
SSDType=dinfo.mediatype&0xff;
if (SSDType==P_FMEDIA_FLASH)
return(E_FILE_VOLUME);
if (SSDType==P_FMEDIA_ROM || SSDType==P_FMEDIA_WRITEPROTECTED)
return(E_FILE_PROTECT);
if (dinfo.mediatype&P_FMEDIA_INTERNAL)
minfree+=0x2800; /* since the sound server takes 0x2800 bytes to run */
if (p_finfo(&self->wvefile.fname[0],&self->wvefile.info)>=0)
{
if (!(self->wvefile.info.status&P_FAWRITE))
return(E_FILE_RDONLY);
dinfo.free+=self->wvefile.info.size; /* credit length of existing file */
}
if (dinfo.free<minfree)
return(0);
return((UINT)(SamplesToTenths(dinfo.free-minfree)/10));
}
METHOD VOID wvefile_wve_open(PR_WVEFILE *self,TEXT *fname)
/*
If fname is NULL, attempt to open the stored file name.
Otherwise, attempt to open name.
*/
{
if (fname)
StoreFileName(self,fname);
self->wvefile.ret=p_finfo(&self->wvefile.fname[0],&self->wvefile.info);
if (self->wvefile.ret<0)
return;
CloseFile(self); /* file can be open after an error in playback */
self->wvefile.ret=p_open(&self->wvefile.fcb,&self->wvefile.fname[0],P_FSHARE);
if (self->wvefile.ret<0)
return;
self->wvefile.ret=p_read(self->wvefile.fcb,&self->wvefile.head,sizeof(SndFile));
if (self->wvefile.ret<0)
{
close:
CloseFile(self);
return;
}
if (p_scmp(&self->wvefile.head.Signature[0],ALawSignature))
{
self->wvefile.ret=E_FILE_INVALID;
goto close;
}
/* Wany "bootleg" files exist with incorrect Samples field */
/* The sound system services work off the file length and not Samples */
/* So we patch Samples here to the correct value */
self->wvefile.head.Samples=self->wvefile.info.size-sizeof(SndFile);
if (self->wvefile.head.Repeats==0)
self->wvefile.head.Repeats=1;
}
METHOD TEXT *wvefile_wve_sense_fname(PR_WVEFILE *self)
{
return(&self->wvefile.fname[0]);
}
METHOD VOID wvefile_wve_sense_info(PR_WVEFILE *self,WVEFILE_INFO *pi)
/*
Write all kinds of information to *pi.
*/
{
ULONG samples;
p_bfil(pi,sizeof(WVEFILE_INFO),0);
pi->device=&self->wvefile.fname[self->wvefile.crk.system];
pi->name=pi->device+self->wvefile.crk.device+self->wvefile.crk.path;
pi->nmlen=self->wvefile.crk.name;
if (self->wvefile.fcb==NULL)
return;
pi->duration=SamplesToTenths(self->wvefile.head.Samples);
pi->silence=(WORD)(((ULONG)self->wvefile.head.SilenceInTicks*5)>>4);
samples=EffectiveSamples(self->wvefile.head.Samples);
samples+=250*(ULONG)self->wvefile.head.SilenceInTicks; /* 250 samples per tick */
if (self->wvefile.head.Repeats>1 && self->wvefile.head.SilenceInTicks<2)
samples+=500; /* the minimum silence between repeats */
pi->repeats=self->wvefile.head.Repeats;
pi->total=SamplesToTenths(samples*pi->repeats);
pi->samples=self->wvefile.head.Samples;
pi->flen=self->wvefile.info.size;
}
METHOD VOID wvefile_wve_set_repeats(PR_WVEFILE *self,UINT repeats,UINT tenths)
/*
If repeats is zero or more, set the number of repeats and the trailing silence
to tenths in 1/10s of a second.
If repeats is zero, set the silence such that the total duration with the
current number of repeats is equal to tenths.
*/
{
INT ret;
INT silence,maxrepeats;
LONG total,period;
ret=0;
if (self->wvefile.fcb==NULL)
return;
if (repeats>0)
silence=(INT)(((ULONG)tenths<<4)/5); /* convert to ticks */
else
{ /* tenths is total desired time */
repeats=self->wvefile.head.Repeats;
total=tenths;
total*=800; /* convert tenths to samples */
period=EffectiveSamples(self->wvefile.head.Samples);
maxrepeats=(INT)(total/(period+500));
if (repeats<2 || repeats>maxrepeats)
repeats=maxrepeats;
if (repeats==0)
repeats=1;
silence=0;
if (repeats>1)
silence=(INT)((total-repeats*period+249*repeats)/(250*repeats));
}
if (silence==self->wvefile.head.SilenceInTicks && repeats==self->wvefile.head.Repeats)
return; /* no change */
self->wvefile.head.SilenceInTicks=silence;
self->wvefile.head.Repeats=repeats;
CloseFile(self);
ret=p_open(&self->wvefile.fcb,&self->wvefile.fname[0],P_FUPDATE);
if (ret>=0)
{
ret=p_write(self->wvefile.fcb,&self->wvefile.head,sizeof(SndFile));
CloseFile(self);
}
wvefile_wve_open(self,NULL);
f_leave(ret);
}