home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Audio 4.94 - Over 11,000 Files
/
audio-11000.iso
/
amiga
/
midi
/
med210.lhw
/
in.adf
/
Source
/
med210src.lzh
/
med-pathlist.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-27
|
17KB
|
654 lines
/* MED - music editor ⌐ 1989, 1990 by Teijo Kinnunen */
/* med-pathlist.c: pathlist handling.. */
#include <ctype.h>
#include <dos.h>
#include "med.h"
#include "medproto.h"
#define DIRSIZE (sizeof(struct PSDir))
#define NAMESIZE (sizeof(struct PSName))
extern struct Task *maintsk;
extern struct Window *window;
extern struct Kappale far song;
extern struct Soitin *sample[];
extern UBYTE samplenum,hakemisto[];
extern UWORD nykyinenosio,chip mouse0[],chip mouse1[];
extern struct RastPort *wrp;
extern struct FData *firstfd;
extern BPTR fh;
static struct PSDir *firstdir = NULL,*lastdir = NULL,*dispdir = NULL;
static struct PSName *dispname = NULL;
static UBYTE *spaces = " ",cdirn = 0,dirs = 0;
static UWORD centr = 0;
UWORD lastrep,lastreplen;
UBYTE lastmidic,lastmidip;
static UWORD __regargs Getposnum(struct PSName *,struct PSName *);
static struct PSDir * __regargs MakeNewDir(char *);
static struct PSName * __regargs MakeNewEntry(char *);
static void __regargs InsertSampleName(struct PSName *,struct PSDir *);
static BOOL __regargs DirAvailable(char *);
static void __regargs FindAvailDirs(void);
static void __regargs RemoveDir(struct PSDir *);
static void __regargs RemoveName(void);
static void __regargs AddName(void);
static void __regargs AddDir(void);
static void __regargs GetRepVals(struct PSName *);
static void __regargs StripRepNums(char *,char *);
static char * __regargs SavePathFile(char *);
static void __regargs DispEntry(UWORD);
static BOOL __regargs SearchFromDir(struct PSDir *,char *);
static struct PSDir * __regargs SearchDirNum(UBYTE);
static BOOL __regargs ConstrName(char *,char *,BOOL,struct PSDir **);
static UWORD __regargs Getposnum(struct PSName *ptr,struct PSName *this)
{
register UWORD pos = 0;
if(!ptr || !this) return(0);
while(ptr && ptr != this) { pos++; ptr = ptr->next; }
return(pos);
}
static struct PSDir * __regargs MakeNewDir(char *name)
{
UWORD dirlen = DIRSIZE + strlen(name) + 1;
struct PSDir *newdir = malloc(dirlen);
if(!newdir) return(0L);
newdir->namelen = strlen(name);
newdir->entries = newdir->diravail = 0;
strcpy((char *)newdir+DIRSIZE,name);
newdir->prev = newdir->next = 0L;
newdir->first = newdir->last = 0L;
dirs++;
return(newdir);
}
static struct PSName * __regargs MakeNewEntry(char *name)
{
UWORD entrylen = NAMESIZE + strlen(name) + 1;
struct PSName *newentry = malloc(entrylen);
if(!newentry) return(0L);
newentry->namelen = strlen(name);
newentry->firstletter = toupper(*name);
strcpy((char *)newentry+NAMESIZE,name);
return(newentry);
}
static void __regargs InsertSampleName(struct PSName *entr,struct PSDir *dir)
{
register struct PSName *first = dir->first;
dir->entries++;
if(!first) {
dir->first = dir->last = entr;
entr->next = entr->prev = 0L;
return;
}
for(;stricmp((char *)first + NAMESIZE,
(char *)entr + NAMESIZE) <= 0 && first->next;
first = first->next);
if(!first->next && stricmp((char *)first + NAMESIZE,
(char *)entr + NAMESIZE) < 0) {
entr->next = 0L;
first->next = entr;
entr->prev = first;
dir->last = entr;
return;
}
entr->next = first;
if(entr->prev = first->prev) entr->prev->next = entr;
else dir->first = entr;
first->prev = entr;
}
static BOOL __regargs DirAvailable(char *name)
{
BPTR lock;
char tstname[120];
APTR prevwptr;
struct Process *tpr = (struct Process *)maintsk;
prevwptr = tpr->pr_WindowPtr;
tpr->pr_WindowPtr = (APTR)-1;
strcpy(tstname,name);
if(tstname[strlen(name) - 1] == '/') tstname[strlen(name) - 1] = 0;
lock = Lock(tstname,ACCESS_READ);
tpr->pr_WindowPtr = prevwptr;
if(lock) {
UnLock(lock);
return(TRUE);
}
return(FALSE);
}
static void __regargs FindAvailDirs()
{
struct PSDir *dir = firstdir,*dir2 = dir;
char thisdskname[FMSIZE],cmpdskname[FMSIZE];
while(dir2) { dir2->diravail = 2; /* 2=don't know */ dir2 = dir2->next; }
while(dir) {
if(dir->diravail == 2) {
if(DirAvailable((char *)dir + DIRSIZE)) {
dir->diravail = 1;
strsfn((char *)dir + DIRSIZE,thisdskname,
NULL,NULL,NULL);
dir2 = dir->next;
while(dir2) {
strsfn((char *)dir2 + DIRSIZE,
cmpdskname,NULL,NULL,NULL);
if(!strcmp(thisdskname,cmpdskname))
dir2->diravail = 1;
dir2 = dir2->next; /* ^disk is available */
}
} else dir->diravail = 0;
}
dir = dir->next;
}
}
void LoadPathFile()
{
UBYTE *scanptr,*pathlist;
ULONG pathlistlen;
BPTR fh;
struct PSDir *currentdir;
struct PSName *currname;
fh = Open("MED_paths",MODE_OLDFILE);
if(!fh) fh = Open("S:MED_paths",MODE_OLDFILE);
if(!fh) {
Ilmoita("MED_paths not found.");
return; /* ei l÷ytynyt */
}
Seek(fh,0,OFFSET_END);
pathlistlen = Seek(fh,0,OFFSET_BEGINNING);
if(!(pathlist = malloc(pathlistlen))) {
Close(fh);
fh = NULL;
Ilmoita("No memory for path list.");
return;
}
StartLoad();
Ilmoita("Loading MED_paths...");
Read(fh,pathlist,pathlistlen);
Close(fh);
fh = NULL;
Ilmoita("Sorting MED_paths...");
for(scanptr = pathlist;scanptr < pathlist+pathlistlen; scanptr++)
if(*scanptr == '\n') *scanptr = '\0';
/* and now begin to translate the information to structures */
scanptr = pathlist;
while(scanptr < pathlist + pathlistlen) {
if(*scanptr == '*') {
if(!(currentdir = MakeNewDir(scanptr+1))) goto lpferr;
if(!firstdir) firstdir = lastdir = currentdir;
else {
lastdir->next = currentdir;
currentdir->prev = lastdir;
lastdir = currentdir;
}
scanptr += strlen(scanptr+1) + 1;
}
else if(currentdir) {
if(!(currname = MakeNewEntry(scanptr))) goto lpferr;
InsertSampleName(currname,currentdir);
scanptr += strlen(scanptr);
}
scanptr++;
}
lpferr: free(pathlist);
dispdir = firstdir;
if(firstdir) dispname = firstdir->first;
StopLoad();
Ilmoita(NULL);
return;
}
static void __regargs AddDir()
{
struct PSDir *newdir;
struct PSName *newname;
struct FData *scanptr;
char newdirname[FMSIZE],fc;
strcpy(newdirname,hakemisto);
if(!(fc = strlen(newdirname))) return;
fc = newdirname[fc - 1];
if(fc != ':') strcat(newdirname,"/");
if(!(newdir = MakeNewDir(newdirname))) return;
newdir->next = dispdir;
if(dispdir) {
if(dispdir->prev) {
newdir->prev = dispdir->prev;
dispdir->prev->next = newdir;
}
dispdir->prev = newdir;
}
if(firstdir == dispdir) firstdir = newdir;
dispdir = newdir;
dirs++;
for(scanptr = firstfd; scanptr; scanptr = scanptr->next) {
if(scanptr->type > 0) continue;
if(!(newname = MakeNewEntry(scanptr->fname))) break;
InsertSampleName(newname,newdir);
}
cdirn = Getposnum((struct PSName *)firstdir,(struct PSName *)dispdir);
dispname = dispdir ? dispdir->first : 0L;
centr = 0;
DisplayPathList();
DisplayDirName();
}
static char * __regargs SavePathFile(char *name)
{
struct PSDir *wrdir = firstdir;
struct PSName *wrname;
char *wptr,wsiz;
if(!firstdir) return("No path list!!");
if(!(fh = Open2(name,MODE_NEWFILE))) return(DISKERR);
Ilmoita("Saving path list...");
while(wrdir) {
wptr = (char *)wrdir + DIRSIZE;
wsiz = strlen(wptr);
if(Write(fh,"*",1) != 1) return(DISKERR);
if(Write(fh,wptr,wsiz) != wsiz) return(DISKERR);
if(Write(fh,"\n",1) != 1) return(DISKERR);
wrname = wrdir->last;
while(wrname) { /* write in Z - A order: it's faster to load */
wptr = (char *)wrname + NAMESIZE;
wsiz = strlen(wptr);
if(Write(fh,wptr,wsiz) != wsiz) return(DISKERR);
if(Write(fh,"\n",1) != 1) return(DISKERR);
wrname = wrname->prev;
}
wrdir = wrdir->next;
}
if(fh) { Close(fh); fh = 0L; }
Ilmoita("Saved.");
return(NOERR);
}
static void __regargs RemoveDir(struct PSDir *dir)
{
struct PSName *delname,*del2;
if(!dir) return;
delname = dir->first;
if(dir->next) dir->next->prev = dir->prev;
if(dir->prev) dir->prev->next = dir->next;
if(firstdir == dir) firstdir = dir->next;
dirs--;
if(dispdir == dir)
if(dispdir = (dir->next ? dir->next : dir->prev))
dispname = dispdir->first;
else dispname = 0L;
while(delname) {
del2 = delname->next;
free((char *)delname);
delname = del2;
}
free((char *)dir);
cdirn = Getposnum((struct PSName *)firstdir,(struct PSName *)dispdir);
}
void FreePaths()
{
struct PSDir *deldir = firstdir,*ndeld;
Ilmoita("Freeing path list...");
while(deldir) {
ndeld = deldir->next;
RemoveDir(deldir);
deldir = ndeld;
}
}
static void __regargs AddName()
{
char newentry[100],*ptr;
struct PSName *newname;
struct SongSample *ss = &song.sample[samplenum];
if(!dispdir) return;
ptr = stpcpy(newentry,ss->sname);
if(ss->midich) {
*ptr++ = ':'; *ptr++ = ':'; *ptr++ = 'M';
ptr += stcu_d(ptr,ss->midich);
*ptr++ = '/';
ptr += stcu_d(ptr,ss->midipreset);
} else if(ss->rep || ss->replen > 1) {
*ptr++ = ':'; *ptr++ = ':';
ptr += stcu_d(ptr,ss->rep << 1);
*ptr++ = '/';
stcu_d(ptr,ss->replen << 1);
}
if(!(newname = MakeNewEntry(newentry))) return;
InsertSampleName(newname,dispdir);
dispname = newname;
DisplayPathList();
}
static void __regargs RemoveName()
{
struct PSDir *remdir = dispdir;
struct PSName *remptr = dispname;
if(!remptr || !remdir) return;
if(remptr->prev) remptr->prev->next = remptr->next;
if(remptr->next) {
remptr->next->prev = remptr->prev;
dispname = remptr->next;
} else dispname = remptr->prev;
remdir->entries--;
if(remdir->first == remptr) remdir->first = remptr->next;
if(remdir->last == remptr) remdir->last = remptr->prev;
free((char *)remptr);
centr = Getposnum(remdir->first,dispname);
}
void DisplayDirName()
{
UBYTE txt[2] = { '0','0' },*dspdirn,*dspdirs,ddnl;
if(nykyinenosio != 0xB) return;
SetAPen(wrp,1);
SetBPen(wrp,3);
Move(wrp,147,26);
if(!dispdir) {
Text(wrp,"----------",10);
txt[0] = txt[1] = '-';
} else {
dspdirs = dspdirn = (char *)dispdir + DIRSIZE;
dspdirn += strlen(dspdirn) - 2;
while(dspdirn >= dspdirs && *dspdirn != '/' && *dspdirn != ':')
dspdirn--;
dspdirn++;
if((ddnl = strlen(dspdirn)) >= 10)
Text(wrp,dspdirn,10);
else {
Text(wrp,dspdirn,ddnl);
Text(wrp,spaces,10 - ddnl);
}
}
Move(wrp,211,37);
txt[0] += cdirn /á10;
txt[1] += cdirn % 10;
Text(wrp,txt,2);
}
void DisplayPathList()
{
struct PSName *dptr;
UBYTE dispcnt;
if(nykyinenosio != 0xB) return;
SetAPen(wrp,0);
SetBPen(wrp,3);
wrp->Mask = 0x3;
if(!dispname || !dispdir) for(dispcnt = 0; dispcnt < 5; dispcnt++) {
Move(wrp,7,26 + 8 * dispcnt);
Text(wrp,spaces,16);
} else for(dispcnt = 0; dispcnt < 5; dispcnt++) {
Move(wrp,7,26 + 8 * dispcnt);
switch(dispcnt) {
case 0: if(dptr = dispname->prev) dptr = dptr->prev;
break;
case 1: dptr = dispname->prev; break;
case 2: dptr = dispname; SetBPen(wrp,1); break;
case 3: dptr = dispname->next; SetBPen(wrp,3); break;
case 4: if(dptr = dispname->next) dptr = dptr->next;
}
if(!dptr) Text(wrp,spaces,16);
else {
if(dptr->namelen >= 16) Text(wrp,(char *)dptr +
NAMESIZE,16);
else {
Text(wrp,(char *)dptr + sizeof(struct
PSName),dptr->namelen);
Text(wrp,spaces,16 - dptr->namelen);
}
dptr = dptr->next;
}
}
wrp->Mask = 0xff;
}
static void __regargs GetRepVals(struct PSName *name)
{
UBYTE *tstchr,midi = 0;
ULONG rvals[2] = { 0,0 },*numptr = rvals;
if(!name) return;
lastrep = lastreplen = 0;
lastmidic = lastmidip = 0;
tstchr = (UBYTE *)name + NAMESIZE;
while(*tstchr && *tstchr != ':') tstchr++;
if(!(*tstchr) || *(tstchr+1) != ':') return;
tstchr += 2;
if(*tstchr == 'm' || *tstchr == 'M') { midi = 1; tstchr++; }
while(*tstchr) {
if(*tstchr == '/') numptr = &rvals[1]; /* now coming length */
if(isdigit(*tstchr)) {
*numptr *= 10;
*numptr += ((*tstchr) - '0');
}
tstchr++;
}
if(midi) { /* these numbers are not repeat/length, instead they */
/* are now midi channel and preset number */
if(lastrep <= 16) lastmidic = (UBYTE)rvals[0];
if(lastreplen <= 128) lastmidip = (UBYTE)rvals[1];
} else {
lastrep = (UWORD)(rvals[0] >> 1);
lastreplen = (UWORD)(rvals[1] >> 1);
}
}
static void __regargs StripRepNums(char *name,char *to)
{
while(*name && *name != ':') *to++ = *name++;
*to = 0;
}
void LoadSelectedSample()
{
char fullname[150],*nameptr;
if(!dispname || !dispdir) return;
StartLoad();
strcpy(fullname,(char *)dispdir + DIRSIZE);
nameptr = fullname + strlen(fullname);
StripRepNums((char *)dispname + NAMESIZE,nameptr);
GetRepVals(dispname);
strcpy(song.sample[samplenum].sname,nameptr);
nameptr = LoadInstrument(fullname,FALSE);
PaivitaSoittimennimi();
StopLoad();
if(nameptr == NOERR) SampleLoaded();
diskerr(nameptr);
}
static void __regargs DispEntry(UWORD num)
{
dispname = dispdir->first;
centr = 0;
while(num-- && dispname->next) { dispname = dispname->next; centr++; }
DisplayPathList();
}
void ScrollSLUp(BYTE steps)
{
if(!dispname) return;
if(steps < 0) {
dispname = dispdir->first;
centr = 0;
}
else while(centr && steps--) { dispname = dispname->prev; centr--; }
DisplayPathList();
}
void ScrollSLDown(BYTE steps)
{
if(!dispname) return;
if(steps < 0) {
dispname = dispdir->last;
centr = dispdir->entries - 1;
} else while(centr < (dispdir->entries - 1) && steps--) {
dispname = dispname->next; centr++;
}
DisplayPathList();
}
void HandleB(UWORD gid)
{
switch(gid) {
case 0xB00: ScrollSLUp(1); break;
case 0xB02: ScrollSLDown(1); break;
case 0xB03: case 0xB04:
if(!dispdir) break;
if(gid == 0xB03) {
if(dispdir->prev) {
dispdir = dispdir->prev;
cdirn--;
}
} else {
if(dispdir->next) {
dispdir = dispdir->next;
cdirn++;
}
}
dispname = dispdir->first;
centr = 0;
DisplayPathList();
DisplayDirName();
break;
case 0xB01: ScrollSLUp((BYTE)-1); break;
case 0xB0C: ScrollSLDown((BYTE)-1); break;
case 0xB05: LoadSelectedSample(); break;
case 0xB0A: RemoveName(); DisplayPathList(); break;
case 0xB0B: RemoveDir(dispdir);
DisplayPathList(); DisplayDirName(); break;
case 0xB08: AddName(); break;
case 0xB09: AddDir(); break;
case 0xB06: case 0xB07:
StartLoad();
diskerr(SavePathFile(gid == 0xB06 ? "MED_paths" :
"S:MED_paths"));
StopLoad();
}
}
static BOOL __regargs SearchFromDir(struct PSDir *dir,char *name)
{
UBYTE matchletter = toupper(*name),name2[110];
struct PSName *searchptr = (dir ? dir->first : 0L);
while(searchptr) {
if(searchptr->firstletter >= matchletter) {
if(searchptr->firstletter > matchletter) return(FALSE);
StripRepNums((char *)searchptr+NAMESIZE,name2);
if(!stricmp(name2,name)) {
GetRepVals(searchptr);
return(TRUE);
}
}
searchptr = searchptr->next;
}
return(FALSE);
}
static struct PSDir * __regargs SearchDirNum(UBYTE num)
{
struct PSDir *ptr = firstdir;
while(ptr && num--) ptr = ptr->next;
return(ptr);
}
static BOOL __regargs ConstrName(char *fname,char *tname,
BOOL mustfind,struct PSDir **founddir)
{
UBYTE dircnt;
char fpath[FMSIZE];
struct PSDir *tstdir,*found = 0L;
*tname = 0;
*founddir = 0L;
if(stcgfp(fpath,fname)) {
if(DirAvailable(fpath) || mustfind) {
strcpy(tname,fname);
return(TRUE);
}
return(FALSE);
}
for(dircnt = 0; dircnt < dirs; dircnt++) {
tstdir = SearchDirNum(dircnt);
if(tstdir->diravail && SearchFromDir(tstdir,fname)) {
found = tstdir;
break;
}
}
if(mustfind && !found) {
for(dircnt = 0; dircnt < dirs; dircnt++) {
tstdir = SearchDirNum(dircnt);
if(!tstdir->diravail && SearchFromDir(tstdir,fname)) {
found = tstdir;
break;
}
}
}
if(found) strcpy(tname,(char *)found + DIRSIZE);
*founddir = found;
strcat(tname,fname);
return((BOOL)found);
}
void ConstructDirName(char *from,char *to)
{
struct PSDir *dir = firstdir,*here = NULL;
while(dir) {
if(SearchFromDir(dir,from)) {
here = dir;
if(DirAvailable((char *)dir + DIRSIZE)) break;
}
dir = dir->next;
}
if(here) strcpy(to,(char *)here + DIRSIZE);
else *to = '\0';
strcat(to,from);
}
char *LoadSongSamples() /* the intelligent sample loader */
{
UBYTE samplelist[63],cnt,stl = 0,fullname[FMSIZE];
char *res = NOERR;
struct PSDir *dir;
FindAvailDirs();
for(cnt = 0; cnt < 63; cnt++) /* Find number of samples to load */
if(song.sample[cnt].sname[0] && !song.sample[cnt].midich
&& !sample[cnt] && stcgfn(fullname,song.sample[cnt].sname)) {
samplelist[cnt] = 1;
stl++;
} else samplelist[cnt] = 0;
while(stl) {
for(cnt = 0; cnt < 63; cnt++) {
if(samplelist[cnt] == 1) {
if(ConstrName(song.sample[cnt].sname,
/* load everything that can be */ fullname,FALSE,&dir)) {
/* loaded without disk swapping */ samplenum = cnt;
PaivitaSoittimennimi();
stl--;
samplelist[cnt] = 0;
if(res = LoadInstrument(fullname,FALSE)) {
diskerr(res);
if(!Continue()) goto stop;
}
}
}
}
for(cnt = 0; cnt < 63; cnt++) {
if(samplelist[cnt] == 1) {
/* then load a sample which */ ConstrName(song.sample[cnt].sname,
/* needs disk swapping */ fullname,TRUE,&dir);
samplenum = cnt;
PaivitaSoittimennimi();
stl--;
samplelist[cnt] = 0;
if(res = LoadInstrument(fullname,FALSE)) {
diskerr(res);
if(!Continue()) goto stop;
}
if(dir) dir->diravail = 1;
/* try again load without.. */ break; /* ..swapping */
}
}
}
return(NOERR);
stop: return("Loading aborted.");
}