home *** CD-ROM | disk | FTP | other *** search
- /*
- * MultiPlayer
- * Copyright (C) 1992 Bryan Ford
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * See "Player.doc" for information on contacting the author.
- *
- * $Id: main.c,v 5.1 92/09/14 18:42:11 BAF Exp $
- *
- * $Log: main.c,v $
- * Revision 5.1 92/09/14 18:42:11 BAF
- * Fixed progload() to deal with NULL filedir's
- * Added nasty_audio support in prefschanged()
- *
- * Revision 4.7 92/08/21 06:18:09 BAF
- * Put initrexx() back in
- *
- * Revision 4.6 92/07/19 22:16:22 BAF
- * Calling format for progload() and progsave() changed
- * Fixed nasty progwin hanging bug
- *
- * Revision 4.5 92/07/19 18:10:20 BAF
- * Adjustment for putting localdata back into RemindNodes
- * Added support for separate cont/play gadgets on main window (added gui_play())
- *
- * Revision 4.4 92/07/12 08:25:22 BAF
- * shutdown() can no longer fail
- *
- * Revision 4.3 92/07/11 11:20:19 BAF
- * Protracker tempo commands now *really* default to on
- * DiskObject now parsed even if it's read from CLI mode
- *
- * Revision 4.2 92/06/21 11:12:46 BAF
- * Migrated regargs to stdargs
- *
- * Revision 4.1 92/06/06 19:56:18 BAF
- * Major_code_cleanup
- *
- * Revision 3.3 92/05/25 08:22:04 BAF
- * Forgot to bump version number to 1.30
- *
- * Revision 3.2 92/05/25 07:53:17 BAF
- * GNU-ized.
- *
- */
-
-
- #define VERSIONTEXT "1.32"
- #define REVISIONTEXT "5"
-
- #include <exec/types.h>
- #include <exec/interrupts.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <devices/inputevent.h>
- #include <hardware/intbits.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <intuition/intuitionbase.h>
- #include <workbench/startup.h>
- #include <workbench/workbench.h>
- #include <workbench/icon.h>
- #include <libraries/commodities.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/graphics.h>
- #include <proto/commodities.h>
- #include <proto/icon.h>
- #include <proto/wb.h>
- #include <proto/diskfont.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "bry/macros.h"
- #include "bry/bovs.h"
- #include "bry/remind.h"
- #include "bry/misc.h"
- #include "guido.h"
-
- #include "player.h"
-
- /* This text is displayed in the screen titlebar of every MultiPlayer window. */
- char copyright[] = "MultiPlayer " VERSIONTEXT " - Copyright 1992 Bryan Ford";
-
-
- /* Startup info for Bovs */
- char *progname = "MultiPlayer";
- long stack = 4096;
- long priority = 1;
-
- char *argtemplate = "DIR=DIRECTORY,PLAY=MODULES/M,PROG=PROGRAM/K,SCREEN/K,NOREQUEST/S,NOWINDOW/S,NOREXX/S,NODETACH/S";
- char *argexthelp =
- "Usage: Player [[DIRECTORY] dir [modules ...]]|[PLAY modules ...]|[PROG program]\n"
- " [SCREEN pubscreen] [NOREQUEST] [NOWINDOW] [NOREXX] [NODETACH]\n"
- "\n"
- " dir [modules ...] Plays [modules] which must be in directory [dir].\n"
- " PLAY modules ... Plays [modules] which must be in current directory.\n"
- " PROG program Loads [program] without playing anything immediately.\n"
- " SCREEN pubscreen Opens MultiPlayer on a public screen named [pubscreen].\n"
- " NOREQUEST Disables opening the file requester on startup.\n"
- " NOWINDOW Opens MultiPlayer in the background, without any window.\n"
- " NOREXX Disables the ARexx port.\n"
- " NODETACH Causes MultiPlayer to run in the original CLI window.\n";
- struct PlayerArgs argarray;
-
- /* System base pointers */
- extern struct ExecBase *SysBase;
- struct GfxBase *GfxBase;
- struct IntuitionBase *IntuitionBase;
- struct Library *GadToolsBase;
- struct Library *WorkbenchBase;
- struct Library *IconBase;
- struct Library *AslBase;
- struct Library *ArpBase;
- struct Library *XpkBase;
- struct Library *CxBase;
- struct Library *DiskfontBase;
- struct Resource *BattMemBase;
-
-
- /* Pointer to our own (main) process */
- struct Process *procpt;
-
-
- /* This is here for the version command to pick up. */
- char versiontag[] = "$VER: MultiPlayer " VERSIONTEXT;
-
-
- /* These contain simple system state flags; the values are defined in
- player.h and player.i. */
- char sysflags, sysflags2;
-
- struct MsgPort *wbappport;
-
-
- /* The TextAttrs hold the current font specs for the user interface fonts set
- in prefs. The TextFont pointers are used only to lock the specified fonts
- in memory - they are not actually passed to Guido or the operating system
- directly. (If the fonts were not locked, memory crunches would expunge
- them and you'd start seeing some very strange results next time something
- is redrawn...) */
- struct TextAttr mainattr, listattr;
- static struct TextFont *mainfont, *listfont;
-
-
- /* Various RemindLists used throughout the user interface system */
-
- /* The dolist is destructively called (destructively means using
- remind_callrem()) after any event. It is normally used by external
- modules to "remember" operations that must be done soon, but not yet. For
- example, closing windows is handled this way: in general, closing a window
- in the basic handling routine is not a good idea, because that window may
- be accessed in previous call levels. Instead, the action is put on the
- dolist, and the window is only closed when we get clear back to the main
- loop, which is considered the only truly 'safe' territory for such
- state changes to occur in. Nodes on the DoList must return zero.
-
- Besides being called from the main loop, the dolist is called in the
- shutdown routine at an appropriate point, so if you add something to the
- dolist, it is *guaranteed* to be called before the system exits.
- */
- struct RemindList dolist;
-
-
- /* The checklist is called non-destructively after any event
- (signal). The global parameter is the mask of signals received from the
- last Wait() call. RemindNodes use this value to see if their signal was
- activated, and if not, return immediately to avoid wasting time
- performing useless checks. Nodes must return zero. */
- struct RemindList checklist;
-
-
- /* The updatelist holds a list of routines that want to be called when the
- SF_WINDOWUP flag is set in sysflags. Nodes must always return 0. This
- is a rather ugly hack: windows and such need to do their own private
- updating. As such, this RemindList is being phased out. */
- struct RemindList updatelist;
-
-
- /* The timerlist is called whenever the SF_SECOND flag gets set, usually
- by the vblank interrupt. It is used mainly to update the clock on the
- main control panel. This should not be used by new code: the whole
- timer system badly needs rewriting. */
- struct RemindList timerlist;
-
-
- /* The snaplist is called by the save() function in prefswin.c, to snapshot
- current window positions (and sizes, if necessary) before saving the
- preferences file. All nodes must return 0. */
- struct RemindList snaplist;
-
-
- /* The closelist is called by window.c to close all user interface windows
- (either when terminating MultiPlayer completely, or when simply going
- into the 'hidden' state). It is also used to remake the user interface
- windows after a font change. The global parameter is 0 to simply close
- the windows, or 1 to close and try to re-open it.
-
- This list is always called destructively, even for a remake operation.
- If a given node succeeds in re-opening its window, it must manually add
- itself back onto the closelist. (This is typically done by openmpwin().)
-
- Nodes on this list are expected to close their windows immediately,
- rather than triggering a 'delayed close'. Calls through this list is
- 'defined' as being safe territory for closing windows. In fact, delayed
- closing is typically implemented by removing a window's closelist node
- and moving it to the dolist.
-
- Nodes must return zero. */
- struct RemindList closelist;
-
-
- /* The endlist is called destructively when MultiPlayer is about to terminate.
- It and the dolist are called alternately until both lists are completely
- empty. Only then will MultiPlayer terminate. Nodes usually return zero...
-
- Icky hack: If a node returns a positive number, the termination is
- aborted, a "Can't exit at this point" error message is displayed on the
- window, and life returns to normal. This is because Commodore, in its
- infinite wisdom, forgot to allow ASL requesters to be closed by the
- program (as well as by the user). Any node that returns -1 must re-add
- its own endnode to the endlist before returning, if it wants to continue
- to be called. */
- struct RemindList endlist;
-
-
- /* Commodities-Exchange objects */
- static struct MsgPort *brokerport;
- static CxObj *broker, *cxfilter, *cxsender, *cxtranslate;
-
-
- /* This always contains the icon we started from, if available. It is
- used to find ToolTypes, as well as to provide imagery for MultiPlayer's
- AppIcons. */
- static struct DiskObject *dob;
-
-
- /* Currently activated AppIcons: Dropping stuff into appi is like dropping
- it into the main window; dropping stuff into appia is like dropping stuff
- into the program window. */
- static struct AppIcon *appi, *appia;
-
-
- #define errgoto(mes,lab) { err = mes; goto lab; }
-
-
- /* This function is called from all over; it displays the given error message
- (if non-null) in the window if the window is open, otherwise it ignores
- it. It always returns what it was called with. */
- char *
- showerr(char *mes)
- {
- extern void windowerror(char *mes);
-
- if(mes)
- windowerror(mes);
- return(mes);
- }
-
-
- /* This variable always contains the "official" current directory (default
- directory for modules and such). If nonzero, it must be freed at
- some point. */
- static BPTR dirlock;
-
- static void
- unlockcurdir(void)
- {
- UnLock(dirlock);
- dirlock = 0L;
- }
-
- char *
- setdir(BPTR newdir)
- {
- BPTR dir;
-
- if(((dir = newdir) == 0) || (dir = DupLock(newdir)))
- {
- UnLock(dirlock);
- CurrentDir(dirlock = dir);
- return(0L);
- }
- else
- return("Directory not found");
- }
-
- char *
- setdirname(char *name)
- {
- BPTR dir;
-
- if(!(name) || !(*name))
- return(0L);
- if(dir = Lock(name,ACCESS_READ))
- {
- UnLock(dirlock);
- CurrentDir(dirlock = dir);
- return(0L);
- }
- else
- return("Directory not found");
- }
-
- /* 1.3 kludges */
-
- #pragma libcall ArpBase CompareLock 1C8 1002
- ULONG CompareLock (BPTR, BPTR);
-
- int
- samelock(BPTR a,BPTR b)
- {
- struct FileLock *aa, *bb;
-
- if(SysBase->LibNode.lib_Version >= 36)
- return(SameLock(a,b) == LOCK_SAME);
- if(ArpBase)
- return(CompareLock(a,b) == 0);
- aa = BADDR(a);
- bb = BADDR(b);
- return((aa) && (bb) && (aa->fl_Task == bb->fl_Task) && (aa->fl_Key == bb->fl_Key));
- }
-
- #pragma libcall ArpBase PathName 14A 18003
- int PathName (BPTR, char *,LONG);
-
- int
- namefromlock(BPTR lock,char *buf,int len)
- {
- if(SysBase->LibNode.lib_Version >= 36)
- return(NameFromLock(lock,buf,len));
- if(ArpBase)
- return(PathName(lock,buf,len));
- return(0);
- }
-
- /* Programs */
-
- static void att(void) {GlobPostMod(&modlist,0);}
- static void det(void) {GlobPreMod(&modlist,0);}
-
- void
- programcurmodchanged(void)
- {
- void programsettingschanged(void);
- extern short volume, balance, speed;
- extern char modflags, filter;
- extern long songendtime;
-
- if(curmod)
- {
- GlobSetLong(&volume,
- ((unsigned long)curmod->volume<<16)+(unsigned long)((unsigned short)curmod->balance),
- programsettingschanged);
- GlobSetWord(&speed,curmod->speed,programsettingschanged);
- GlobSetByte(&modflags,curmod->flags,programsettingschanged);
- GlobSetByte(&filter,curmod->filter,programsettingschanged);
- songendtime = curmod->endtime;
- }
- else
- {
- GlobSetLong(&volume,-1L,programsettingschanged);
- GlobSetWord(&speed,0,programsettingschanged);
- GlobSetByte(&modflags,0,programsettingschanged);
- GlobSetByte(&filter,(char)-1,programsettingschanged);
- songendtime = 0;
- }
- }
-
- void
- programsettingschanged(void)
- {
- void programcurmodchanged(void);
- extern short volume, balance, speed;
- extern char modflags, filter;
- short mod;
-
- if(!curmod)
- return;
- if(curmod->volume != volume)
- mod = 1,curmod->volume = volume;
- if(curmod->balance != balance)
- mod = 1,curmod->balance = balance;
- if(curmod->speed != speed)
- mod = 1,curmod->speed = speed;
- if(curmod->flags != modflags)
- mod = 1,curmod->flags = modflags;
- if(curmod->filter != filter)
- mod = 1,curmod->filter = filter;
- if(mod)
- GlobPostMod(&curmod,programcurmodchanged);
- }
-
- static void
- freemodnode(struct ModNode *node)
- {
- UnLock(node->dir);
- FreeMem(node,node->size);
- }
-
- static struct ModNode *
- progminadd(BPTR dir,char *name)
- {
- struct ModNode *node;
- int size = sizeof(*node)+strlen(name);
-
- if(!(node = AllocMem(size,MEMF_CLEAR)))
- return(0L);
- strcpy(node->name,name);
- node->nameptr = toupperlong(((long*)(node->name))[0]) == 'MOD.' ?
- node->name+4 : node->name;
- node->dir = DupLock(dir ? dir : procpt->pr_CurrentDir);
- node->size = size;
-
- node->volume = 100; /* Pull some default settings out of the hat */
- node->speed = 50;
- node->flags = MNF_PTTEMPO;
-
- AddTail(&modlist,node);
- return(node);
- }
-
- static char *
- progquickadd(BPTR dir,char *name)
- {
- struct ModNode *node;
-
- if(!(node = progminadd(dir,name)))
- return("Not enough memory");
-
- if(curmod) /* Use the current module's settings if possible */
- {
- if(curmod->volume >= 0)
- node->volume = curmod->volume,
- node->balance = curmod->balance;
- if(curmod->speed)
- node->speed = curmod->speed;
- if(curmod->filter >= 0)
- node->filter = curmod->filter;
- node->flags = MNF_PTTEMPO;
- }
-
- return(0L);
- }
-
- char *
- progadd(BPTR dir,char *name)
- {
- struct FileInfoBlock __aligned FIB;
- BPTR olddir = 0L, lock = 0L;
- char *err = 0L;
- char flag = 1;
- char chdir = 0;
-
- /* Collect all modules in subdirectories */
- if((name) && (name[0]))
- {
- if(dir)
- olddir = CurrentDir(dir), chdir = 1;
- lock = Lock(name,ACCESS_READ);
- }
- else
- lock = DupLock(dir);
- if((lock) && (Examine(lock,&FIB)) && (FIB.fib_DirEntryType > 0))
- {
- flag = 0;
- while(ExNext(lock,&FIB))
- {
- if(strcmp(".info",FIB.fib_FileName+strlen(FIB.fib_FileName)-5) == 0)
- continue;
- if(err = progadd(lock,FIB.fib_FileName))
- break;
- }
- }
- UnLock(lock);
- if(chdir)
- CurrentDir(olddir);
-
- /* Not a directory - just add to the list */
- if((flag) && (!err))
- {
- det();
- err = progquickadd(dir,name);
- att();
- }
- return(err);
- }
-
- char *
- progaddargs(int args,struct WBArg *arg)
- {
- char *err;
-
- while(args-- > 0)
- {
- if(err = progadd(arg->wa_Lock,arg->wa_Name))
- return(err);
- arg++;
- }
- return(0L);
- }
-
- char *
- progact(struct ModNode *node)
- {
- char *err;
-
- GlobSetLong(&curmod,node,0L);
- if((err = setdir(node->dir)) ||
- (err = startmod(node->name,-1)))
- return(err);
- return(0L);
- }
-
- static char *
- progfind(struct ModNode *node,int backwards)
- {
- struct ModNode *onode;
- short cnt;
- long randomlong(void);
-
- if(!modlist.mlh_Head->mln_Succ) /* No modules */
- return("No modules in program");
- if(!modlist.mlh_Head->mln_Succ->mln_Succ) /* Only one module */
- {
- dofirst:
- return(progact(modlist.mlh_Head));
- }
- if(!node)
- {
- if(playmode == PM_RANDOM)
- node = modlist.mlh_Head;
- else
- goto dofirst;
- }
- onode = node;
- tryagain:
- cnt = playmode == PM_RANDOM ? randomlong() & 0xf : 0;
- do
- {
- if(!backwards)
- {
- node = node->node.mln_Succ;
- if(!node->node.mln_Succ)
- node = modlist.mlh_Head;
- }
- else
- {
- node = node->node.mln_Pred;
- if(!node->node.mln_Pred)
- node = modlist.mlh_TailPred;
- }
- }
- while(--cnt >= 0);
- if(node == onode)
- goto tryagain;
- return(progact(node));
- }
-
- char *
- progstart(void)
- {
- return(progfind(0L,0));
- }
-
- char *
- prognext(void)
- {
- return(progfind(curmod,0));
- }
-
- char *
- progprev(void)
- {
- return(progfind(curmod,1));
- }
-
- void
- progdel(struct ModNode *node)
- {
- det();
- if(curmod == node)
- GlobSetLong(&curmod,0,0);
- if(selmod == node)
- GlobSetLong(&selmod,0,0);
- Remove(node);
- freemodnode(node);
- att();
- }
-
- void
- progclear(void)
- {
- struct ModNode *node;
-
- det();
- while(node = RemTail(&modlist))
- freemodnode(node);
- GlobSetLong(&curmod,0,0);
- GlobSetLong(&selmod,0,0);
- att();
- }
-
- static char *
- writeval2(char *b,unsigned long n)
- {
- if(n >= 10)
- b = writeval2(b,n/10), n%=10;
- *b = '0'+n;
- return(b+1);
- }
-
- static char *
- writeval(char *b,char i,long n)
- {
- *b++ = i;
- if(n<0)
- *b++ = '-', n = -n;
- return(writeval2(b,n));
- }
-
- char *
- progsave(BPTR filedir,char *filename)
- {
- static char hdr[] = "PROGRAM\nDIR ";
- BPTR han, dir = 0L;
- struct ModNode *node = modlist.mlh_Head;
- char *err = "Error saving program";
- char buf[32], *b;
- BPTR olddir;
-
- if(!node->node.mln_Succ)
- return("Nothing to save");
- olddir = CurrentDir(filedir);
- han = Open(filename,MODE_NEWFILE);
- CurrentDir(olddir);
- if(!han)
- goto err1;
- if(Write(han,&hdr[0],7) <= 0)
- goto err2;
- while(node->node.mln_Succ)
- {
- if(!samelock(dir,node->dir))
- {
- char buf[256];
-
- dir = node->dir;
- if(!namefromlock(dir,buf,255))
- errgoto("Can't find directory name",err2);
- if((Write(han,&hdr[7],5) <= 0) ||
- (Write(han,buf,strlen(buf)) <= 0))
- goto err2;
- }
- if((Write(han,&hdr[7],1) <= 0) ||
- (Write(han,node->name,strlen(node->name)) <= 0))
- goto err2;
-
- b = buf;
- *b++ = '\n';
- *b++ = '\t';
- if(node->volume != 100)
- b = writeval(b,'V',node->volume);
- if(node->volume >= 0)
- {
- if(node->balance)
- b = writeval(b,'B',node->balance);
- if(node->flags & MNF_ENDFADE)
- *b++ = 'A';
- }
- if(node->speed != 50)
- b = writeval(b,'S',node->speed);
- if(node->filter)
- b = writeval(b,'F',node->filter);
- if(node->endtime)
- b = writeval(b,'E',node->endtime);
- if(node->flags & MNF_NOTPROTRACKER)
- *b++ = 'N';
- else if(node->flags & MNF_PTTEMPO)
- *b++ = 'T';
- if(b != &buf[2])
- {
- if(Write(han,buf,(long)b-(long)buf) <= 0)
- goto err2;
- }
-
- node = node->node.mln_Succ;
- }
- err = 0L;
- err2:
- Close(han);
- err1:
- return(err);
- }
-
- char *
- progload(BPTR filedir,char *filename,int start)
- {
- static char hdr[] = "PROGRAM\nDIR ";
- BPTR han, dir = 0L;
- char *mem, *p, *ep;
- long size, v;
- char *err = "Error reading program";
- struct ModNode *node = 0L;
- BPTR olddir;
-
- progclear();
- if(filedir)
- {
- olddir = CurrentDir(filedir);
- han = Open(filename,MODE_OLDFILE);
- CurrentDir(olddir);
- }
- else
- han = Open(filename,MODE_OLDFILE);
- if(!han)
- goto err1;
- if((Seek(han,0,OFFSET_END) < 0) ||
- ((size = Seek(han,0,OFFSET_BEGINNING)) < 0))
- goto err2;
- size += 1;
- if(!(mem = AllocMem(size,0)))
- errgoto("Not enough memory",err2);
- if(Read(han,mem,size-1) <= 0)
- goto err3;
- if((size <= 8) || memcmp(mem,&hdr[0],8))
- errgoto("Not a program file",err3);
- ep = mem+size-1;
- for(p = mem+8;p < ep;p++)
- if(*p == '\n')
- *p = 0;
- *p = 0;
- p = mem+8;
- det();
- while(p < ep)
- {
- if((*p) && (*p != '#') && (*p != '*') && (*p != '/'))
- {
- if(p[0] == '\t')
- {
- if(node)
- {
- p++;
- node->flags = 0;
- while(*p != 0)
- {
- switch(*p++)
- {
- case 'V':
- v = atol(p);
- if((v <= 100) && (v >= -1))
- node->volume = v;
- break;
- case 'B':
- v = atol(p);
- if((v <= 50) && (v >= -50))
- node->balance = v;
- break;
- case 'S':
- v = atol(p);
- if((v == 0) || ((v <= 200) && (v >= 10)))
- node->speed = v;
- break;
- case 'F':
- v = atol(p);
- if((v <= 2) && (v >= -1))
- node->filter = v;
- break;
- case 'E':
- v = atol(p);
- if(v > 0)
- node->endtime = v;
- break;
- case 'A':
- node->flags |= MNF_ENDFADE;
- break;
- case 'T':
- node->flags |= MNF_PTTEMPO;
- break;
- case 'N':
- node->flags |= MNF_NOTPROTRACKER;
- break;
- }
- }
- }
- }
- else if(memcmp(p,&hdr[8],4) == 0)
- {
- p += 4;
- UnLock(dir);
- if(!(dir = Lock(p,ACCESS_READ)))
- errgoto("Directory not found",err3);
- }
- else
- {
- if(!(node = progminadd(dir,p)))
- errgoto("Not enough memory",err4);
- }
- }
- p += strlen(p)+1;
- }
- err = start ? progstart() : 0L;
- err4:
- att();
- UnLock(dir);
- err3:
- FreeMem(mem,size);
- err2:
- Close(han);
- err1:
- return(err);
- }
-
- void
- addcalls(struct RemindNode *check,
- struct RemindNode *update,
- struct RemindNode *timer,
- struct RemindNode *end)
- {
- if(check)
- remind_add(&checklist,check);
- if(update)
- remind_add(&updatelist,update);
- if(timer)
- remind_add(&timerlist,timer);
- if(end)
- remind_add(&endlist,end);
- }
-
-
- static long sigmask = SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F;
-
- void
- addsigs(long newsigs)
- {
- sigmask |= newsigs;
- }
-
- void
- remsigs(long oldsigs)
- {
- sigmask &= ~oldsigs;
- }
-
-
- void
- gui_play(void)
- {
- showerr(playmod(-1));
- }
-
-
- char *
- fadecont(void)
- {
- extern short fadevol, fadeinc;
- extern char pausefade, playing;
- char *err;
-
- if(pausefade
- && ((!playing) || (sysflags & SF_FADEPAUSE))
- && (curmod)
- && (curmod->volume >= 0))
- {
- sysflags &= ~SF_FADEPAUSE;
- fadeinc = 1;
- if(fadevol <= 0)
- fadevol = 1;
- if(err = contplaymod())
- fadevol = -1;
- }
- else
- err = contplaymod();
- return(err);
- }
-
-
- void
- gui_cont(void)
- {
- showerr(fadecont());
- }
-
-
-
- void
- fadestop(void)
- {
- extern short fadevol, fadeinc;
- extern char pausefade, playing;
-
- if(pausefade && playing && curmod && (curmod->volume >= 0))
- {
- sysflags |= SF_FADEPAUSE;
- fadeinc = -1;
- if(fadevol < 0)
- fadevol = 128;
- }
- else
- stopmod();
- }
-
- void
- gui_stop(void)
- {
- fadestop();
- }
-
-
- void
- windowkey(int code,int context)
- {
- extern void gui_windowzoom(void);
- extern char *gui_progwinopenclose(void);
- extern char *gui_prefswinopenclose(void);
- extern char *gui_settingswinopenclose(void);
- extern char *gui_infowinopenclose(void);
- extern char *gui_flashywinopenclose(void);
-
- extern long cursong, numsongs;
- extern char playing;
- extern char prefsglob[];
-
- char *err = 0L;
-
- switch(code)
- {
- case RawESC:
- sysflags |= SF_KILL;
- break;
- case RawF1:
- gui_windowzoom();
- break;
- case RawF2:
- gui_progwinopenclose();
- break;
- case RawF3:
- gui_prefswinopenclose();
- break;
- case RawF4:
- gui_settingswinopenclose();
- break;
- case RawF5:
- gui_infowinopenclose();
- break;
- case RawF6: /* Silly, ain't it? ... */
- flashflags ^= FF_SPECTRUM|FF_NOTES;
- case RawF7:
- flashflags ^= FF_NOTES|FF_SCOPE;
- case RawF8:
- flashflags ^= FF_SCOPE|FF_QSCOPE;
- case RawF9:
- flashflags ^= FF_QSCOPE;
- GlobPostMod(prefsglob,0);
- break;
- case RawSpace:
- if((playing) && !(sysflags & SF_FADEPAUSE))
- fadestop();
- else
- fadecont();
- break;
- case RawDel:
- endmod();
- break;
- case RawDown:
- err = prognext();
- break;
- case RawUp:
- err = progprev();
- break;
- case RawRight:
- setsong(cursong+1);
- break;
- case RawLeft:
- setsong(cursong > 0 ? cursong-1 : numsongs-1);
- break;
- }
- showerr(err);
- }
-
-
- void
- standardcallback(struct GuidoMessage *im)
- {
- if(im->Class == IDCMP_RAWKEY)
- windowkey(im->Code,PREFSWINCONTEXT);
- else if(im->Class == IDCMP_MOUSEBUTTONS)
- windowclick(im->Code);
- }
-
-
- static void
- closefonts(void)
- {
- if(mainfont)
- CloseFont(mainfont), mainfont = 0;
- if(listfont)
- CloseFont(listfont), listfont = 0;
- }
-
-
- static struct TextFont *
- openfont(struct TextAttr *attr,char *name,short size)
- {
- attr->ta_Name = name;
- attr->ta_YSize = size;
- if(DiskfontBase)
- return(OpenDiskFont(attr));
- return(OpenFont(attr));
- }
-
- void
- mainprefschanged(void)
- {
- { /* Set our hotkey string */
- extern char hotkey[];
- IX ix;
-
- if(!cxfilter)
- return;
- RemoveCxObj(cxfilter);
- if(hotkey[0])
- {
- ix.ix_Version = IX_VERSION;
- if(ParseIX(hotkey,&ix) >= 0)
- {
- SetFilterIX(cxfilter,&ix);
- AttachCxObj(broker,cxfilter);
- }
- else
- showerr("Can't decipher hot key string");
- }
- }
-
- { /* Add or remove our AppIcon */
- extern char appicon, appicona;
-
- if(appicon && !appi && wbappport && dob)
- appi = AddAppIconA(1,0,"Play",wbappport,0,dob,0);
- else if(!appicon && appi)
- RemoveAppIcon(appi), appi = 0;
-
- if(appicona && !appia && wbappport && dob)
- appia = AddAppIconA(0,0,"Add",wbappport,0,dob,0);
- else if(!appicona && appia)
- RemoveAppIcon(appia), appia = 0;
- }
-
- { /* The changing of the fonts */
- extern char mainfontname[], listfontname[];
- extern short mainfontsize, listfontsize;
-
- if(!mainfont || !listfont ||
- (mainfontsize != mainfont->tf_YSize) || (listfontsize != listfont->tf_YSize) ||
- stricmp(mainfontname,mainfont->tf_Message.mn_Node.ln_Name) ||
- stricmp(mainfontname,mainfont->tf_Message.mn_Node.ln_Name))
- {
- int reset = 0;
-
- closefonts();
- while(!(mainfont = openfont(&mainattr,mainfontname,mainfontsize)))
- strcpy(mainfontname,"topaz.font"), mainfontsize = 8, reset = 1;
- while(!(listfont = openfont(&listattr,listfontname,listfontsize)))
- strcpy(listfontname,"topaz.font"), listfontsize = 8, reset = 1;
- windowremake();
- if(reset)
- GlobPostMod(prefsglob,mainprefschanged);
- }
- }
-
- { /* Set the audio to nasty or nice */
- extern char nasty_audio;
- extern void NoteSysAudioPri(char pri);
-
- NoteSysAudioPri(nasty_audio ? 127 : 0);
- }
- }
-
-
- static void
- loadprefs(void)
- {
- extern char prefs[], prefsend[], prefsglob[];
- BPTR han;
-
- if(han = Open("ENV:MultiPlayerPrefs",MODE_OLDFILE))
- {
- Read(han,prefs,(long)(prefsend-prefs));
- Close(han);
- if(playmode >= ' ')
- switch(toupper(playmode))
- {
- case 'S': playmode = PM_SEQUENCE; break;
- case 'R': playmode = PM_RANDOM; break;
- case 'O': playmode = PM_ONCE; break;
- case 'V': playmode = PM_OVEROVER; break;
- }
- if(showmode >= ' ')
- switch(toupper(showmode))
- {
- case 'N': showmode = SM_NOTHING; break;
- case 'C': showmode = SM_CLOCK; break;
- case '0': showmode = SM_SEQUENCE0; break;
- case '1': showmode = SM_SEQUENCE1; break;
- }
- }
- GlobPostMod(prefsglob,0);
- }
-
- static void
- checkwbapp(void)
- {
- struct AppMessage *msg;
-
- if(!wbappport)
- return;
- while(msg = GetMsg(wbappport))
- {
- int start = 0;
-
- if(msg->am_NumArgs)
- {
- if(msg->am_ID)
- progclear();
- if(!showerr(progaddargs(msg->am_NumArgs,msg->am_ArgList)) && (msg->am_ID))
- start = 1;
- }
- else
- showerr(windowopen());
- ReplyMsg(msg);
- if(start)
- showerr(progstart());
- }
- }
-
- static void
- checkbroker(void)
- {
- CxMsg *msg;
-
- if(!brokerport)
- return;
- while(msg = GetMsg(brokerport))
- {
- switch(CxMsgType(msg))
- {
- case CXM_COMMAND:
- switch(CxMsgID(msg))
- {
- case CXCMD_DISABLE:
- ActivateCxObj(broker,0);
- break;
- case CXCMD_ENABLE:
- ActivateCxObj(broker,1);
- break;
- case CXCMD_KILL:
- sysflags |= SF_KILL;
- break;
- case CXCMD_DISAPPEAR:
- windowclose();
- break;
- case CXCMD_UNIQUE:
- ActivateCxObj(broker,1);
- case CXCMD_APPEAR:
- goto appear;
- }
- break;
- case CXM_IEVENT:
- appear:
- showerr(windowopen());
- break;
- }
- ReplyMsg(msg);
- }
- }
-
- static long
- standardsnapshot(int dummy,struct MPWin *win)
- {
- if(win->win)
- {
- win->snappos[0] = win->win->LeftEdge;
- win->snappos[1] = win->win->TopEdge;
- }
- return(0);
- }
-
- void
- closempwin(struct MPWin *win)
- {
- remind_rem(&win->snapnode);
- remind_rem(&win->checknode);
- remind_rem(&win->closenode);
- if(win->win)
- {
- if(win->snapnode.callfunc)
- (*win->snapnode.callfunc)(0,win);
- remsigs(win->sigmask);
- GClosePanel(win->win);
- win->sigmask = win->win = 0L;
- }
- }
-
- static long
- standardclose(int remake,struct MPWin *win)
- {
- closempwin(win);
- if(remake)
- showerr(openmpwin(win));
- return(0);
- }
-
- char *
- openmpwin(struct MPWin *win)
- {
- win->snapnode.localdata = win->checknode.localdata = win->closenode.localdata = win;
- if(win->snappos && !win->snapnode.callfunc)
- win->snapnode.callfunc = standardsnapshot;
- if(win->snapnode.callfunc)
- remind_add(&snaplist,&win->snapnode);
- if(win->checknode.callfunc)
- remind_add(&checklist,&win->checknode);
- if(!win->closenode.callfunc)
- win->closenode.callfunc = standardclose;
- remind_rem(&win->closenode); /* In case it was on the dolist */
- remind_add(&closelist,&win->closenode);
-
- if(win->win = GOpenPanel(win->spec,0,&mainattr))
- {
- addsigs(win->sigmask = 1<<win->win->UserPort->mp_SigBit);
- if(win->initfunc)
- (*(win->initfunc))();
- return(0L);
- }
- else
- {
- closempwin(win);
- return("Unable to open window");
- }
- }
-
- void setfinmpwin(struct MPWin *win)
- {
- remind_rem(&win->closenode);
- remind_add(&dolist,&win->closenode);
- }
-
- /* Program cleanup routine, called only by Main(). */
- static void
- shutdown(void)
- {
- extern struct Interrupt vblankint;
- extern void unloadftm(void);
- long rc;
-
- endmod();
-
- while(((rc = remind_callrem(&dolist,0L)) >= 0)
- || ((rc = remind_callrem(&endlist,0L)) >= 0));
-
- unloadftm(); /* FIXME - kludge - yuck */
-
- progclear();
- unlockcurdir();
-
- if(broker)
- {
- ActivateCxObj(broker,0);
- if(cxfilter)
- DeleteCxObj(cxfilter);
- if(cxtranslate)
- DeleteCxObj(cxtranslate);
- if(cxsender)
- DeleteCxObj(cxsender);
- DeleteCxObj(broker);
- }
- if(brokerport)
- DeleteMsgPort(brokerport);
-
- if(appi)
- RemoveAppIcon(appi);
- if(appia)
- RemoveAppIcon(appia);
- checkwbapp();
- if(wbappport)
- DeleteMsgPort(wbappport);
-
- if(dob)
- FreeDiskObject(dob);
-
- RemIntServer(INTB_VERTB,&vblankint);
-
- closefonts();
-
- if(DiskfontBase)
- CloseLibrary(DiskfontBase);
- if(CxBase)
- CloseLibrary(CxBase);
- if(XpkBase)
- CloseLibrary(XpkBase);
- if(ArpBase)
- CloseLibrary(ArpBase);
- if(AslBase)
- CloseLibrary(AslBase);
- if(IconBase)
- CloseLibrary(IconBase);
- if(WorkbenchBase)
- CloseLibrary(WorkbenchBase);
- if(GadToolsBase)
- CloseLibrary(GadToolsBase);
- CloseLibrary(IntuitionBase);
- CloseLibrary(GfxBase);
- }
-
- /* Initialize-everything routine, called only by Main() */
- static void
- startup(int arglen,char *argstr)
- {
- static struct NewBroker nb =
- {
- NB_VERSION,
- "MultiPlayer",
- "MultiPlayer",
- "MultiPlayer " VERSIONTEXT " - ⌐ 1992 Bryan Ford",
- NBU_UNIQUE|NBU_NOTIFY,COF_SHOW_HIDE,0
- };
-
- extern struct Interrupt vblankint;
- extern long scopeinterval;
- extern void initrexx(void);
- extern void randomseedclock(void);
- extern char keepprog;
- extern int argsparsed;
-
- struct WBStartup *wbs = argstr;
-
- remind_initlist(&dolist);
- remind_initlist(&checklist);
- remind_initlist(&updatelist);
- remind_initlist(&timerlist);
- remind_initlist(&snaplist);
- remind_initlist(&closelist);
- remind_initlist(&endlist);
-
- procpt = FindTask(0L);
- GfxBase = OpenLibrary("graphics.library",0);
- IntuitionBase = OpenLibrary("intuition.library",0);
- GadToolsBase = OpenLibrary("gadtools.library",0);
- WorkbenchBase = OpenLibrary("workbench.library",0);
- IconBase = OpenLibrary("icon.library",0);
- AslBase = OpenLibrary("asl.library",37);
- ArpBase = OpenLibrary("arp.library",39);
- if(!(XpkBase = OpenLibrary("xpkmaster.library",0)))
- XpkBase = OpenLibrary("compression.library",0);
- CxBase = OpenLibrary("commodities.library",0);
- DiskfontBase = OpenLibrary("diskfont.library",0);
- BattMemBase = OpenResource("ciab.resource");
-
- AddIntServer(INTB_VERTB,&vblankint);
-
- randomseedclock();
-
- if(WorkbenchBase)
- wbappport = CreateMsgPort(),
- addsigs(1<<wbappport->mp_SigBit);
-
- scopeinterval = (long)(FFperF*CLOCK)/(long)SysBase->VBlankFrequency;
-
- if(IconBase)
- {
- char *p;
-
- if(!arglen)
- {
- BPTR olddir = 0;
-
- if(wbs->sm_ArgList[0].wa_Lock)
- olddir = CurrentDir(wbs->sm_ArgList[0].wa_Lock);
- if(wbs->sm_ArgList[0].wa_Name)
- dob = GetDiskObject(wbs->sm_ArgList[0].wa_Name);
- if(olddir)
- CurrentDir(olddir);
- }
- else
- dob = GetDiskObject("Player");
- if(dob)
- {
- if((p = FindToolType(dob->do_ToolTypes,"DIR")) ||
- (p = FindToolType(dob->do_ToolTypes,"DIRECTORY")))
- argarray.dir = p;
- if((p = FindToolType(dob->do_ToolTypes,"PROG")) ||
- (p = FindToolType(dob->do_ToolTypes,"PROGRAM")))
- argarray.prog = p;
- if(p = FindToolType(dob->do_ToolTypes,"SCREEN"))
- argarray.screen = p;
- if(p = FindToolType(dob->do_ToolTypes,"REQUEST"))
- argarray.noreq = MatchToolValue(p,"NO");
- if(p = FindToolType(dob->do_ToolTypes,"WINDOW"))
- argarray.nowin = MatchToolValue(p,"NO");
- if(p = FindToolType(dob->do_ToolTypes,"REXX"))
- argarray.norexx = MatchToolValue(p,"NO");
- }
- }
-
- if(CxBase)
- {
- if(brokerport = nb.nb_Port = CreateMsgPort())
- {
- addsigs(1<<brokerport->mp_SigBit);
- if(broker = CxBroker(&nb,0))
- {
- if((cxsender = CxSender(brokerport,0)) &&
- (cxtranslate = CxTranslate(IECLASS_NULL)) &&
- (cxfilter = CxFilter(0)))
- {
- AttachCxObj(cxfilter,cxsender);
- AttachCxObj(cxfilter,cxtranslate);
- /* Don't attach the filter to the broker: prefs does that */
- }
- }
- else /* Don't allow duplicates */
- {
- shutdown();
- BRExit(10,ERROR_OBJECT_EXISTS);
- }
- }
- }
-
- loadprefs();
-
- /* Now that we have our hot-key (if any), activate it */
- if(broker)
- ActivateCxObj(broker,1);
-
- if(!argarray.nowin)
- windowopen();
-
- if(!argarray.norexx)
- initrexx();
-
- if(arglen) /* CLI */
- {
- if(argsparsed) /* 2.0 arguments */
- {
- char **mods;
-
- if(argarray.dir)
- showerr(setdirname(argarray.dir));
- if(mods = argarray.mods)
- {
- while(*mods)
- {
- if(showerr(progadd(0L,*mods)))
- break;
- mods++;
- }
- argarray.noreq = 1;
- }
- }
- else /* 1.3 arguments */
- {
- arglen--;
- while(argstr[0] == ' ')
- argstr++, arglen--;
- while((arglen > 0) && (argstr[arglen-1] == ' '))
- arglen--;
- if(arglen > 0)
- {
- argstr[arglen--] = 0;
- showerr((argstr[arglen] == ':') || (argstr[arglen] == '/') ?
- setdirname(argstr) :
- (argarray.noreq = 1, progadd(0L,argstr)));
- }
- }
- }
- else /* Workbench */
- {
- showerr(wbs->sm_NumArgs > 1 ?
- (argarray.noreq = 1, progaddargs(wbs->sm_NumArgs-1,wbs->sm_ArgList+1)) :
- argarray.dir ? setdirname(argarray.dir) : setdir(wbs->sm_ArgList[0].wa_Lock));
- }
-
- if(argarray.noreq)
- {
- if(modlist.mlh_Head->mln_Succ)
- showerr(progstart());
- }
- else if(argarray.prog)
- {
- showerr(progload(procpt->pr_CurrentDir,argarray.prog,0));
- }
- else if(keepprog)
- {
- showerr(progload(0,"ENV:MultiPlayerProgram",0));
- }
- else
- showerr(reqmod(1));
- }
-
- /* Main entrypoint and program loop - called from Bovs if detach enabled,
- called from PreStart() if detach disabled. */
- void
- Main(int arglen,char *argstr)
- {
- extern long songtime, songendtime;
- extern short fadevol, volume;
- long gotsigs;
-
- startup(arglen,argstr);
-
- do
- {
- gotsigs = Wait(sigmask);
-
- checkwbapp();
- checkbroker();
- remind_call(&checklist,gotsigs);
- remind_callrem(&dolist,0L);
- if(sysflags & SF_TIMERUP)
- {
- extern void windowupdatetimer(void);
-
- windowupdatetimer();
- }
- if(sysflags & SF_SECOND)
- {
- sysflags &= ~SF_SECOND;
- remind_call(&timerlist,0);
- }
- if(sysflags & SF_WINDOWUP)
- {
- sysflags &= ~SF_WINDOWUP;
- remind_call(&updatelist,0);
- }
- if(sysflags & SF_REPEAT)
- {
- if(fadevol <= 0)
- {
- extern char contprogonerr;
-
- if((playmode == PM_ONCE)
- || ((playmode == PM_SEQUENCEONCE) && (curmod)
- && !(curmod->node.mln_Succ->mln_Succ)))
- endmod();
- else if(playmode != PM_OVEROVER)
- {
- /* If an error occurs and "continue on error" is
- selected, retry ONLY ONCE - otherwise it's very
- easy to get in infinite loops (by clearing the
- program, for example). */
- if(showerr(prognext()) && contprogonerr)
- prognext();
- }
- fadevol = -1;
- GlobPostMod(&volume,programsettingschanged);
- sysflags &= ~(SF_REPEAT|SF_FADEDONE);
- }
- }
- if(sysflags & SF_FADEDONE)
- {
- if(sysflags & SF_FADEPAUSE)
- stopmod();
- fadevol = -1;
- GlobPostMod(&volume,programsettingschanged);
- sysflags &= ~(SF_FADEDONE|SF_FADEPAUSE);
- }
- }
- while(!(sysflags & SF_KILL));
- shutdown();
- }
-
- /* PreStart() is called by Bovs before detaching, and if the user specifies
- NODETACH, it simply calls Main() immediately without ever detaching. */
- void
- PreStart (int arglen, char *argstr)
- {
- if(argarray.nodetach)
- {
- Main(arglen,argstr);
- BExit();
- }
- }
-
-