[xiph-cvs] cvs commit: MTG soundboard.c

Monty xiphmont at xiph.org
Thu Jan 31 02:43:24 PST 2002



xiphmont    02/01/31 02:43:24

  Modified:    .        soundboard.c
  Log:
  only remaining work: playback thread, tag list menu

Revision  Changes    Path
1.2       +651 -310  MTG/soundboard.c

Index: soundboard.c
===================================================================
RCS file: /usr/local/cvsroot/MTG/soundboard.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- soundboard.c	2002/01/30 12:28:35	1.1
+++ soundboard.c	2002/01/31 10:43:23	1.2
@@ -1,25 +1,37 @@
+/* TODO:
+
+   make Esc behavior correct in editing menus by using temp cue/tag storage
+   tag list menu
+
+*/
+
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <pthread.h>
 #include <string.h>
 #include <math.h>
 #include <signal.h>
 #include <curses.h>
+#include <fcntl.h>
 
 
 #define int16 short
 static char *tempdir="/tmp/beaverphonic/";
-static char *installdir="/usr/local/beaverphonic/";
+static char *lockfile="/tmp/beaverphonic/lock";
+//static char *installdir="/usr/local/beaverphonic/";
+static char *installdir="/home/xiphmont/MotherfishCVS/MTG/";
 #define VERSION "20020128.0"
 
 enum menutype {MENU_MAIN,MENU_KEYPRESS,MENU_ADD,MENU_EDIT,MENU_OUTPUT,MENU_QUIT};
 
 pthread_mutex_t master_mutex=PTHREAD_MUTEX_INITIALIZER;
-static int main_master_volume=50;
+static long main_master_volume=50;
 char *program;
 static int playback_buffer_minfill=-1;
 static int running=1;
@@ -35,13 +47,21 @@
   return(realloc(in,bytes));
 }
 
-void addnlstr(char *s,int n,char c){
+void addnlstr(const char *s,int n,char c){
   int len=strlen(s),i;
   addnstr(s,n);
   n-=len;
   for(i=0;i<n;i++)addch(c);
 }
 
+void switch_to_stderr(){
+  def_prog_mode();           /* save current tty modes */
+  endwin();                  /* restore original tty modes */
+}
+
+void switch_to_ncurses(){
+  refresh();                 /* restore save modes, repaint screen */
+}
 
 /******** channel mappings.  All hardwired for now... ***********/
 // only OSS stereo builin for now
@@ -104,6 +124,15 @@
   label_list[number].refcount++;
 }
 
+const char *label_text(int number){
+  if(number<0 || 
+     number>=label_count || 
+     label_list[number].refcount==0 ||
+     label_list[number].text==NULL)
+    return"";
+  return label_list[number].text;
+}
+
 void release_label(int number){
   label *label;
   if(number>=label_count)return;
@@ -118,8 +147,8 @@
   if(number<=label_count){
     if(label_list[number].refcount){
       fprintf(f,"LBL:%d %d:%s",number,
-	      strlen(label_list[number].text),
-	      label_list[number].text);
+	      strlen(label_text(number)),
+	      label_text(number));
       
       count=fprintf(f,"\n");
       if(count<1)return(-1);
@@ -162,13 +191,14 @@
   int          refcount;
 
   label_number sample_path;
-  int    loop_p;
+  label_number sample_desc;
+  long   loop_p;
   long   loop_start;
   long   loop_lapping;
   long   fade_out;
 
   void  *basemap;
-  int16 *channel_vec[2];
+  int16 *data;
   int    channels;
   long   samplelength;
 
@@ -191,7 +221,6 @@
 struct sample_header{
   long sync;
   long channels;
-  long samples;
 };
 
 static tag        *tag_list;
@@ -217,103 +246,130 @@
     memset(tag_list+prev,0,sizeof(*tag_list)*(tag_count-prev));
   }
 }
-
-/* UI convention: this has too many useful things to report if sample
-   opening goes awry, and I don't want to define a huge message
-   reporting system through ncurses in C, so we go back to tty-like
-   for reporting here, waiting for a keypress if nonzero return */
-int edit_tag(int number,tag t){
-  int offset,ret;
-  tag *tag;
-  _alloc_tag_if_needed(number);
-  
-  t.basemap=NULL;
-  t.channels=0;
-  t.samplelength=0;
 
-  tag_list[number]=t;
-  tag=tag_list+number;
+  /* UI convention: this has too many useful things to report if
+     sample opening goes awry, and I don't want to define a huge
+     message reporting system through ncurses in C, so we go back to
+     tty-like for reporting here, waiting for a keypress if nonzero
+     return */
+
+int load_sample(tag *t,const char *path){
+  char *template=alloca(strlen(tempdir)+20);
+  char *tmp,*buffer;
+  int ret=0;
 
-  /* allow the edit to be accepted if the file cannot be opened, but
-     alert the operator */
+  fprintf(stderr,"Loading %s...\n",path);
+  /* parse the file; use preexisting tools via external Perl glue */
+  /* select a temp file for the glue to convert file into */
+  /* valid use of mktemp; only one Beaverphonic is running a time,
+     and we need a *name*, not a *file*. */
+
+  sprintf(template,"%sconversion.XXXXXX",tempdir);
+  tmp=mktemp(template);
+  if(!tmp)return(-1);
+
+  buffer=alloca(strlen(installdir)+strlen(tmp)+strlen(path)+20);  
+  fprintf(stderr,"\tcopying/converting...\n");
+  sprintf(buffer,"%sconvert.pl \'%s\' \'%s\'",installdir,path,tmp);
+  ret=system(buffer);
+  if(ret)goto out;
+  
+  /* our temp file is a host-ordered 44.1kHz 16 bit PCM file, n
+     channels uninterleaved.  first word is channels */
+  fprintf(stderr,"\treading...\n");
   {
-    /* parse the file; use preexisting tools via external Perl glue */
-    /* select a temp file for the glue to convert file into */
-    /* valid use of mktemp; only one Beaverphonic is running a time,
-       and we need a *name*, not a *file*. */
-
-    char *template=alloca(strlen(tempdir)+20);
-    char *tmp;
-
-    sprintf(template,"%sconversionXXXXXX",tempdir);
-    tmp=mktemp(template);
-    if(!tmp)return(-1);
-
-    {
-      char *orig=label_list[t.sample_path].text;
-      char *buffer=alloca(strlen(installdir)+strlen(tmp)+strlen(orig)+20);
-      
-      sprintf(buffer,"%sconvert.pl %s %s",installdir,orig,tmp);
-      ret=system(buffer);
-      if(ret)return(ret);
+    FILE *cheat=fopen(tmp,"rb");
+    struct sample_header head;
+    int count,i;
+    int fd;
+    long length;
+    if(!cheat){
+      fprintf(stderr,"Failed to open converted file %s:\n\t(%s)\n",
+	      tmp,strerror(errno));
+      ret=-1;goto out;
     }
-	
-    /* our temp file is a host-ordered 44.1kHz 16 bit PCM file, n
-       channels uninterleaved.  first word is channels */
-    {
-      FILE *cheat=fopen(tmp,"rb");
-      struct sample_header head;
-      int count,i;
-      int fd;
-      if(!cheat){
-	fprintf(stderr,"Failed to open converted file %s:\n\t%d (%s)\n",
-		tmp,ferror(cheat),strerror(ferror(cheat)));
-	return(-1);
-      }
-      count=fread(&head,sizeof(head),1,cheat);
+
+    /* find length,etc */
+    if(fseek(cheat,-sizeof(head),SEEK_END)){
+      fprintf(stderr,"Unable to seek to end of file!\n\t%s\n",
+	      strerror(ferror(cheat)));
       fclose(cheat);
-      if(count<(int)sizeof(head)){
-	fprintf(stderr,"Conversion file %s openable, but truncated\n",tmp);
-	return(-1);
-      }
-      if(head.sync!=55){
-	fprintf(stderr,"Conversion file created by incorrect "
-		"version of convert.pl\n\t%s unreadable\n",tmp);
-	return(-1);
-      }
+      ret=-1;goto out;
+    }
+    length=ftell(cheat);
+    if(length<0){
+      fprintf(stderr,"Unable to determine length of file!\n\t%s\n",
+	      strerror(ferror(cheat)));
+      fclose(cheat);
+      ret=-1;goto out;
+    }
+    count=fread(&head,sizeof(head),1,cheat);
 
-      tag->channels=head.channels;
-      tag->samplelength=head.samples;
-      offset=sizeof(head);
-
-      /* mmap the sample file */
-      fd=open(tmp,O_RDONLY);
-      if(fd<0){
-	fprintf(stderr,"Unable to open %s fd for mmap:\n\t%d (%s)\n",
-		tmp,errno,strerror(errno));
-	return(-1);
-      }
-      tag->basemap=
-	mmap(NULL,
-	     tag->samplelength*sizeof(int16)*tag->channels+sizeof(head),
-	     PROT_READ,MAP_PRIVATE,fd,0);
-      close(fd);
-      if(!tag->basemap){
-	fprintf(stderr,"Unable to mmap fd %d (%s):\n\t%d (%s)\n",
-		fd,tmp,errno,strerror(errno));
-	return(-1);
-      }
-      
-      for(i=0;i<tag->channels && i<2 ;i++) /* only up to stereo channels */
-	tag->channel_vec[i]=(int16 *)(tag->basemap)+
-	  sizeof(head)+head.samples*i;
-      
-    } 
+    fclose(cheat);
+    if(count<1){
+      fprintf(stderr,"Conversion file %s openable, but truncated\n",tmp);
+      ret=-1;goto out;
+    }
+    if(head.sync!=55){
+      fprintf(stderr,"Conversion file created by incorrect "
+	      "version of convert.pl\n\t%s unreadable\n",tmp);
+      ret=-1;goto out;
+    }
+    
+    t->channels=head.channels;
+    t->samplelength=length/(t->channels*2);
+
+    /* mmap the sample file */
+    fprintf(stderr,"\tmmaping...\n");
+    fd=open(tmp,O_RDONLY);
+    if(fd<0){
+      fprintf(stderr,"Unable to open %s fd for mmap:\n\t%d (%s)\n",
+	      tmp,errno,strerror(errno));
+      ret=-1;goto out;
+    }
+    t->basemap=
+      mmap(NULL,
+	   t->samplelength*sizeof(int16)*t->channels+sizeof(head),
+	   PROT_READ,MAP_PRIVATE,fd,0);
+    close(fd);
+
+    if(!t->basemap){
+      fprintf(stderr,"Unable to mmap fd %d (%s):\n\t%d (%s)\n",
+	      fd,tmp,errno,strerror(errno));
+      ret=-1;goto out;
+    }
+    t->data=t->basemap+sizeof(head);
   }
+  fprintf(stderr,"\tDONE\n\n");
+  
+ out:
+  if(tmp)unlink(tmp);
+  return(ret);
+}
 
-  /* state is zeroed when we go to production mode.  Done  */
+int unload_sample(tag *t){
+  /* unmap */
+  if(t->basemap)
+    munmap(t->basemap,
+	   t->samplelength*sizeof(int16)*
+	   t->channels+sizeof(struct sample_header));
+
+  t->basemap=NULL;
+  t->data=NULL;
+  t->samplelength=0;
+  t->channels=0;
   return(0);
+}
+
+int edit_tag(int number,tag t){
+  int ret;
+  tag *tag;
+  _alloc_tag_if_needed(number);
+  
+  tag_list[number]=t;
 
+  /* state is zeroed when we go to production mode.  Done  */
+  return(0);
 }
 
 void aquire_tag(int number){
@@ -326,6 +382,12 @@
   if(number<0)return;
   if(number>=tag_count)return;
   tag_list[number].refcount--;
+  if(tag_list[number].refcount==0){
+    if(tag_list[number].basemap)
+      unload_sample(tag_list+number);
+    release_label(tag_list[number].sample_path);
+    release_label(tag_list[number].sample_desc);
+  }
   if(tag_list[number].refcount<0)
     tag_list[number].refcount=0;
 }
@@ -337,8 +399,9 @@
   if(number>=tag_count)return(0);
   t=tag_list+number;
   if(t->refcount){
-    fprintf(f,"TAG:%d %d %ld %ld %ld",
-	    number,t->sample_path,t->loop_p,t->loop_start,t->loop_lapping,
+    fprintf(f,"TAG:%d %d %d %ld %ld %ld %ld",
+	    number,t->sample_path,t->sample_desc,
+	    t->loop_p,t->loop_start,t->loop_lapping,
             t->fade_out);
     count=fprintf(f,"\n");
     if(count<1)return(-1);
@@ -359,14 +422,20 @@
   int len,count,number;
   memset(&t,0,sizeof(t));
   
-  count=fscanf(f,":%d %d %ld %ld %ld",
-	       &number,&t.sample_path,&t.loop_p,&t.loop_start,
+  count=fscanf(f,":%d %d %d %ld %ld %ld %ld",
+	       &number,&t.sample_path,&t.sample_desc,&t.loop_p,&t.loop_start,
                &t.loop_lapping,&t.fade_out);
-  if(count<5){
+  if(count<7){
     addnlstr("LOAD ERROR (TAG): too few fields.",80,' ');
     return(-1);
   }
   aquire_label(t.sample_path);
+  if(load_sample(&t,label_text(t.sample_path))){
+    release_label(t.sample_path);
+    return(-1);
+  }
+  aquire_label(t.sample_desc);
+
   edit_tag(number,t);
   return(0);
 }
@@ -503,6 +572,11 @@
     addnlstr("LOAD ERROR (CUE): too few fields.",80,' ');
     return(-1);
   }
+  if(c.tag>=tag_count ||
+     !tag_list[c.tag].basemap){
+    addnlstr("LOAD ERROR (CUE): references a bad TAG",80,' ');
+    return(-1);
+  }
 
   for(i=0;i<maxchannels;i++){
     int v;
@@ -539,10 +613,10 @@
   return(0);
 }
 
-int load_val(FILE *f, int *val){
+int load_val(FILE *f, long *val){
   int count;
   int t;  
-  count=fscanf(f,": %d",&t);
+  count=fscanf(f,": %ld",&t);
   if(count<1){
     addnlstr("LOAD ERROR (VAL): missing field.",80,' ');
     return(-1);
@@ -551,9 +625,9 @@
   return(0);
 }
 
-int save_val(FILE *f, char *p, int val){  
+int save_val(FILE *f, char *p, long val){  
   int count;
-  fprintf(f,"%s: %d",p,val);
+  fprintf(f,"%s: %ld",p,val);
   count=fprintf(f,"\n");
   if(count<1)return(-1);
   return(0);
@@ -612,15 +686,6 @@
 
 /***************** simple form entry fields *******************/
 
-void switch_to_stderr(){
-  def_prog_mode();           /* save current tty modes */
-  endwin();                  /* restore original tty modes */
-}
-
-void switch_to_ncurses(){
-  refresh();                 /* restore save modes, repaint screen */
-}
-
 enum field_type { FORM_YESNO, FORM_PERCENTAGE, FORM_NUMBER, FORM_GENERIC,
                   FORM_BUTTON } ;
 typedef struct {
@@ -703,7 +768,7 @@
       break;
     case FORM_NUMBER:
       {
-	int var=*(int *)(f->var);
+	long var=*(long *)(f->var);
         char buf[80];
         snprintf(buf,80,"%*d",f->width-2,var);
         addstr(buf);
@@ -871,7 +936,7 @@
         break;
       case FORM_NUMBER:
         {
-	  int *val=(int *)ff->var;
+	  long *val=(long *)ff->var;
           switch(c){
           case '0':case '1':case '2':case '3':case '4':
           case '5':case '6':case '7':case '8':case '9':
@@ -1059,26 +1124,26 @@
 
     for(i=-1;i<2;i++){
       char buf[80];
-      move(y+i*2+2,0);
+      move(y+i*3+3,0);
       if(i==0){
         addstr("NEXT => ");
         attron(A_REVERSE);
       }
       if(cn<0){
-	move(y+i*2+2,8);
+	move(y+i*3+3,8);
         addnlstr("",71,' ');
-	move(y+i*2+3,8);
+	move(y+i*3+4,8);
         addnlstr("**** BEGIN",71,' ');
       }else if(cn>=cue_count){
-	move(y+i*2+2,8);
+	move(y+i*3+3,8);
         addnlstr("****** END",71,' ');
         attroff(A_REVERSE);
-	move(y+i*2+3,8);
+	move(y+i*3+4,8);
         addnlstr("",71,' ');
         if(i==0){
-	  move(y+i*2+4,8);
+	  move(y+i*3+6,8);
           addnlstr("",71,' ');
-	  move(y+i*2+5,8);
+	  move(y+i*3+7,8);
           addnlstr("",71,' ');
         }
         break;
@@ -1086,12 +1151,12 @@
         cue *c;
         c=cue_list+cn;
 
-	snprintf(buf,13,"%10s) ",label_list[c->label].text);
-	mvaddstr(y+i*2+2,8,buf);
-	addnlstr(label_list[c->cue_text].text,59,' ');
+	move(y+i*3+3,8);
+	addnlstr(label_text(c->label),12,' ');
+	addnlstr(label_text(c->cue_text),59,' ');
 
-	mvaddstr(y+i*2+3,8,"            ");
-	addnlstr(label_list[c->cue_desc].text,59,' ');
+	mvaddstr(y+i*3+4,8,"            ");
+	addnlstr(label_text(c->cue_desc),59,' ');
       }
       attroff(A_BOLD);
       while(++cn<cue_count)
@@ -1131,7 +1196,7 @@
         else
           sprintf(buf,"[%3ds] ",(ms+500)/1000);
         addstr(buf);
-	addnlstr(label_list[path].text,55,' ');
+	addnlstr(label_text(path),55,' ');
       }
       move(y+i,14);
       addnlstr("",55,' ');
@@ -1178,7 +1243,7 @@
   FILE *f;
   if(!firstsave){
     char *buf=alloca(strlen(fn)*2+20);
-    sprintf(buf,"cp %s %s~",fn,fn);
+    sprintf(buf,"cp %s %s~ 2>/dev/null",fn,fn);
     /* create backup file */
     system(buf);
     firstsave=1;
@@ -1237,14 +1302,14 @@
 
 
   mvhline(9+MAX_CHANNELS,0,0,80);
-  mvhline(16+MAX_CHANNELS,0,0,80);
+  mvhline(18+MAX_CHANNELS,0,0,80);
 
   main_update_master(main_master_volume,5);
   main_update_playbuffer(4);
   main_update_outchannel_labels(7);
 
   main_update_cues(10+MAX_CHANNELS);
-  main_update_tags(17+MAX_CHANNELS);
+  main_update_tags(19+MAX_CHANNELS);
   curs_set(0);
 
   refresh();
@@ -1396,7 +1461,7 @@
   int tnum=new_tag_number();
   form f;
 
-  char label[12]="";
+  char label[13]="";
   char text[61]="";
   char desc[61]="";
 
@@ -1454,97 +1519,6 @@
   return(MENU_MAIN);
 }
 
-int add_sample_cue_menu(){
-  int tnum=new_tag_number();
-  int i;
-  char buf[50];
-  form f;
-  form_init(&f,9+MAX_CHANNELS*3);
-  clear();
-  box(stdscr,0,0);
-  mvaddstr(0,2," Add new sample cue ");
-
-  mvaddstr(2,2,"cue number");
-  mvaddstr(3,2,"cue decimal");
-  mvaddstr(4,2,"sample tag");
-  sprintf(buf,"%4d",tnum);
-  attron(A_BOLD);
-  mvaddstr(4,18,buf);
-  attroff(A_BOLD);
-
-  mvaddstr(5,2,"cue text");
-  mvaddstr(7,2,"sample file");
-  mvaddstr(9,2,"volume master       % fade       /      ms");
-  mvaddstr(10,2,"loop                     crosslap       ms");
-
-  mvaddstr(12,2,"channels out");
-
-  for(i=0;i<MAX_CHANNELS;i++){
-    sprintf(buf,"L     %%     R -> %d ",i);
-    mvaddstr(12+i,17,buf);
-    addnlstr(channel_list[i].label,40,' ');
-  }
-    
-
-  {
-    int number=0;
-    int decimal=0;
-    char text[60]="\0";
-    char path[60]="\0";
-    int master=100;
-    int masterin=15;
-    int masterout=15;
-    int outvol[2][MAX_CHANNELS]={{100,0},{0,100}};
-    int loop=0;
-    int cross=0;
-    int loopfield,crossfield;
-
-    field_add(&f,FORM_NUMBER,17,2,6,&number);
-    field_add(&f,FORM_NUMBER,17,3,6,&decimal);
-    field_add(&f,FORM_GENERIC,17,5,60,text);
-    field_add(&f,FORM_GENERIC,17,7,60,path);
-
-    field_add(&f,FORM_PERCENTAGE,17,9,5,&master);
-    field_add(&f,FORM_NUMBER,29,9,6,&masterin);
-    field_add(&f,FORM_NUMBER,36,9,6,&masterout);
-
-    loopfield=field_add(&f,FORM_YESNO,17,10,5,&loop);
-    crossfield=field_add(&f,FORM_NUMBER,36,10,6,&cross);
-    field_state(&f,crossfield,0);
-		
-    for(i=0;i<MAX_CHANNELS;i++){
-      field_add(&f,FORM_PERCENTAGE,18,12+i,5,&(outvol[0][i]));
-      field_add(&f,FORM_PERCENTAGE,24,12+i,5,&(outvol[1][i]));
-    }
-    
-    refresh();
-
-    while(1){
-      int ch=form_handle_char(&f,getch());
-
-      switch(ch){
-      case 27: /* esc */
-	goto out;
-      case KEY_ENTER: case '\n':case '\r':
-	{
-
-	}
-	return(MENU_MAIN);
-      }
-
-      if(f.cursor==loopfield){
-	if(loop)
-	  field_state(&f,crossfield,1);
-	else
-	  field_state(&f,crossfield,0);
-      }
-    }
-  }
-  
- out:
-  form_clear(&f);
-  return(MENU_MAIN);
-}
 
 void edit_keypress_menu(){
   clear();
@@ -1571,13 +1545,396 @@
   mvaddstr(8,12,"add new mixer change to cue");
   mvaddstr(9,12,"delete highlighted action");
   mvaddstr(10,12,"edit highlighted action");
-  mvaddstr(11,12,"list all sample and sample tags");
+  mvaddstr(11,12,"list all samples and sample tags");
 
   mvaddstr(13,12,"any key to return to cue edit menu");
   refresh();
   getch();
 }
 
+void edit_sample_menu(int n){
+  int i,j;
+  cue *c=cue_list+n;
+  tag *t=tag_list+cue_list[n].tag;
+  char tdesc[61]="";
+  char buf[82];
+  form f;
+
+  clear();
+  box(stdscr,0,0);
+  mvaddstr(0,2," Add/Edit sample cue ");
+  
+  mvaddstr(10,2,"loop                      crosslap       ms");
+  mvaddstr(11,2,"volume master        % fade       /      ms");
+  
+  form_init(&f,7+MAX_CHANNELS*t->channels);
+  strcpy(tdesc,label_text(t->sample_desc));
+
+  field_add(&f,FORM_GENERIC,18,7,59,tdesc);
+
+  field_add(&f,FORM_YESNO,18,10,5,&t->loop_p);
+  field_add(&f,FORM_NUMBER,37,10,6,&t->loop_lapping);
+
+  field_add(&f,FORM_PERCENTAGE,18,11,5,&c->mix.vol_master);
+  field_add(&f,FORM_NUMBER,30,11,6,&c->mix.vol_ms);
+  field_add(&f,FORM_NUMBER,37,11,6,&t->fade_out);
+  
+  mvaddstr(2,2,"cue label        ");
+  addnlstr(label_text(c->label),59,' ');
+  mvaddstr(3,2,"cue text         ");
+  addnlstr(label_text(c->cue_text),59,' ');
+  mvaddstr(4,2,"cue description  ");
+  addnlstr(label_text(c->cue_desc),59,' ');
+
+  mvaddstr(6,2,"sample path      ");
+  addnlstr(label_text(t->sample_path),59,' ');
+
+  mvaddstr(7,2,"sample desc");
+  mvaddstr(8,2,"sample tag       ");
+  sprintf(buf,"%d",c->tag);
+  addstr(buf);
+
+  mvhline(13,3,0,74);
+  mvhline(14+MAX_CHANNELS,3,0,74);
+  mvvline(14,2,0,MAX_CHANNELS);
+  mvvline(14,77,0,MAX_CHANNELS);
+  mvaddch(13,2,ACS_ULCORNER);
+  mvaddch(13,77,ACS_URCORNER);
+  mvaddch(14+MAX_CHANNELS,2,ACS_LLCORNER);
+  mvaddch(14+MAX_CHANNELS,77,ACS_LRCORNER);
+  
+  if(t->channels==2){
+    mvaddstr(13,6," L ");
+    mvaddstr(13,11," R ");
+  }else{
+    for(i=0;i<t->channels;i++){
+      mvaddch(13,6+i*5,' ');
+      addch(48+i);
+      addch(' ');
+    }
+  }
+
+  for(i=0;i<MAX_CHANNELS;i++){
+    for(j=0;j<t->channels && j<2;j++)
+      field_add(&f,FORM_PERCENTAGE,4+j*5,14+i,5,&c->mix.outvol[j][i]);
+    sprintf(buf,"%% ->%2d ",i);
+    mvaddstr(14+i,4+t->channels*5,buf);
+    addnlstr(channel_list[i].label,76-11-t->channels*5,' ');
+  }
+
+  field_add(&f,FORM_BUTTON,61,17+MAX_CHANNELS,16,"ACCEPT CHANGES");
+
+
+#if 0
+ Add/edit sample to cue -------------------------------------------------------
+
+  cue label       [          ]
+  cue text        [                                                          ]
+  cue description [                                                          ]
+
+  sample path     [                                                          ]
+  sample desc     [                                                          ]
+  sample tag      0 
+
+  loop            [No ]     crosslap [----]ms                           
+  volume master   [100]% fade [  15]/[  15]ms
+                            
+  --- L -- R -----------------------------------------------------------------
+ |  [100][  0]% -> 0 offstage left                                            |
+ |  [  0][100]% -> 1 offstage right                                           |
+ |  [  0][  0]% -> 2                                                          |
+ |  [  0][  0]% -> 3                                                          |
+ |  [  0][  0]% -> 4                                                          |
+ |  [  0][  0]% -> 5                                                          |
+ |  [  0][  0]% -> 6                                                          |
+ |  [  0][  0]% -> 7                                                          |
+  ----------------------------------------------------------------------------
+
+#endif
+
+  while(1){
+    int ch=form_handle_char(&f,getch());
+    
+    switch(ch){
+    case 27:
+      goto out;
+    case 'x':case 'X':case KEY_ENTER:
+      unsaved=1;
+      edit_label(t->sample_desc,tdesc);
+      goto out;
+    }
+  }
+ out:
+  form_clear(&f);
+}
+
+void edit_mix_menu(int n){
+  int i,j;
+  cue *c=cue_list+n;
+  tag *t=tag_list+cue_list[n].tag;
+  char tdesc[61]="";
+  char buf[82];
+  form f;
+
+  clear();
+  box(stdscr,0,0);
+  mvaddstr(0,2," Add/Edit mix cue ");
+  
+  mvaddstr(10,2,"volume master        % fade       ms");
+  
+  form_init(&f,3+MAX_CHANNELS*t->channels);
+  strcpy(tdesc,label_text(t->sample_desc));
+
+  field_add(&f,FORM_PERCENTAGE,18,10,5,&c->mix.vol_master);
+  field_add(&f,FORM_NUMBER,30,10,6,&c->mix.vol_ms);
+  
+  mvaddstr(2,2,"cue label        ");
+  addnlstr(label_text(c->label),59,' ');
+  mvaddstr(3,2,"cue text         ");
+  addnlstr(label_text(c->cue_text),59,' ');
+  mvaddstr(4,2,"cue description  ");
+  addnlstr(label_text(c->cue_desc),59,' ');
+
+  mvaddstr(6,2,"sample path      ");
+  addnlstr(label_text(t->sample_path),59,' ');
+
+  mvaddstr(7,2,"sample desc      ");
+  addnlstr(label_text(t->sample_desc),59,' ');
+  mvaddstr(8,2,"sample tag       ");
+  sprintf(buf,"%d",c->tag);
+  addstr(buf);
+
+  mvhline(12,3,0,74);
+  mvhline(13+MAX_CHANNELS,3,0,74);
+  mvvline(13,2,0,MAX_CHANNELS);
+  mvvline(13,77,0,MAX_CHANNELS);
+  mvaddch(12,2,ACS_ULCORNER);
+  mvaddch(12,77,ACS_URCORNER);
+  mvaddch(13+MAX_CHANNELS,2,ACS_LLCORNER);
+  mvaddch(13+MAX_CHANNELS,77,ACS_LRCORNER);
+  
+  if(t->channels==2){
+    mvaddstr(12,6," L ");
+    mvaddstr(12,11," R ");
+  }else{
+    for(i=0;i<t->channels;i++){
+      mvaddch(12,6+i*5,' ');
+      addch(48+i);
+      addch(' ');
+    }
+  }
+
+  for(i=0;i<MAX_CHANNELS;i++){
+    for(j=0;j<t->channels && j<2;j++)
+      field_add(&f,FORM_PERCENTAGE,4+j*5,13+i,5,&c->mix.outvol[j][i]);
+    sprintf(buf,"%% ->%2d ",i);
+    mvaddstr(13+i,4+t->channels*5,buf);
+    addnlstr(channel_list[i].label,76-11-t->channels*5,' ');
+  }
+
+  field_add(&f,FORM_BUTTON,61,16+MAX_CHANNELS,16,"ACCEPT CHANGES");
+
+
+#if 0
+ Add/edit mix change ---------------------------------------------------------
+
+  cue label       [          ]
+  cue text        [                                                          ]
+  cue description [                                                          ]
+
+  modify tag      [   0]
+ 
+  volume master   [100]% fade [  15]
+                            
+  --- L -- R -----------------------------------------------------------------
+ |  [100][  0]% -> 0 offstage left                                            |
+ |  [  0][100]% -> 1 offstage right                                           |
+ |  [  0][  0]% -> 2                                                          |
+ |  [  0][  0]% -> 3                                                          |
+ |  [  0][  0]% -> 4                                                          |
+ |  [  0][  0]% -> 5                                                          |
+ |  [  0][  0]% -> 6                                                          |
+ |  [  0][  0]% -> 7                                                          |
+  ----------------------------------------------------------------------------
+
+ (l: list tags)
+
+#endif
+
+  while(1){
+    int ch=form_handle_char(&f,getch());
+    
+    switch(ch){
+    case 27:
+      goto out;
+    case 'x':case 'X':case KEY_ENTER:
+      unsaved=1;
+      goto out;
+    }
+  }
+ out:
+  form_clear(&f);
+
+}
+
+int add_sample_menu(){
+  /* two-stage... get sample first so the mixer is accurate */
+  tag t;
+  tag_number tagno;
+
+  form f;
+  char path[64]="";
+
+  clear();
+  box(stdscr,0,0);
+  mvaddstr(0,2," Add new sample to cue ");
+  
+  form_init(&f,1);
+  mvaddstr(2,2,"sample path");
+  field_add(&f,FORM_GENERIC,14,2,62,path);
+  f.edit=1;
+  form_redraw(&f);
+
+  while(1){
+    int ch=getch();
+    int re=form_handle_char(&f,ch);
+
+    if(re>=0 || !f.edit){
+      if(ch==27){
+	form_clear(&f);
+	return(MENU_EDIT);
+      }
+      break;
+    }
+  }
+
+  /* try to load the sample! */
+  switch_to_stderr();
+  if(load_sample(&t,path)){
+    fprintf(stderr,"Press enter to continue\n");
+    getc(stdin);
+    switch_to_ncurses();
+    return(1);
+  }
+  switch_to_ncurses();
+
+  unsaved=1;
+
+  /* finish the tag */
+  {
+    t.sample_path=new_label_number();
+    aquire_label(t.sample_path);
+    edit_label(t.sample_path,path);
+
+    t.sample_desc=new_label_number();
+    aquire_label(t.sample_desc);
+    edit_label(t.sample_desc,"");
+    t.loop_p=0;
+    t.loop_start=0;
+    t.loop_lapping=1000;
+
+    t.fade_out=15;
+    
+    tagno=new_tag_number();
+    aquire_tag(tagno);
+    edit_tag(tagno,t);
+  }
+
+  /* got it, add a new cue */
+  {
+    cue c;
+    
+    aquire_label(c.label=cue_list[cue_list_number].label);
+    aquire_label(c.cue_text=cue_list[cue_list_number].cue_text);
+    aquire_label(c.cue_desc=cue_list[cue_list_number].cue_desc);
+    c.tag=tagno;
+    c.tag_create_p=1;
+    memset(&c.mix,0,sizeof(mix));
+    c.mix.vol_master=100;
+    c.mix.vol_ms=10;
+    c.mix.outvol[0][0]=100;
+    c.mix.outvol[1][1]=100;
+
+    add_cue(cue_list_number+1,c);
+  }
+
+  /* go to main edit menu */
+  edit_sample_menu(cue_list_number+1);
+
+  return(MENU_EDIT);
+}
+
+int add_mix_menu(){
+  tag_number tagno=0;
+
+  form f;
+
+  clear();
+  box(stdscr,0,0);
+  mvaddstr(0,2," Add mixer change to cue ");
+  
+  form_init(&f,1);
+  mvaddstr(2,2,"tag number ");
+  field_add(&f,FORM_NUMBER,13,2,12,&tagno);
+  f.edit=1;
+  form_redraw(&f);
+
+  mvaddstr(4,2,"'");
+  attron(A_BOLD);
+  addstr("l");
+  attroff(A_BOLD);
+  addstr("' for a list of sample tags                    ");
+
+  while(1){
+    int ch=getch();
+    int re=form_handle_char(&f,ch);
+
+    if(re>=0 || !f.edit){
+      if(ch==27){
+	form_clear(&f);
+	return(MENU_EDIT);
+      }
+      if(tagno>=tag_count || tag_list[tagno].refcount<=0){
+	mvaddstr(4,2,"Bad tag number; any key to continue.");
+	getch();
+	mvaddstr(4,2,"'");
+	attron(A_BOLD);
+	addstr("l");
+	attroff(A_BOLD);
+	addstr("' for a list of sample tags                    ");
+	f.edit=1;
+	form_redraw(&f);
+      }else
+	break;
+    }
+  }
+
+  /* add the new cue */
+  {
+    cue c;
+    unsaved=1;
+
+    aquire_tag(tagno);
+    aquire_label(c.label=cue_list[cue_list_number].label);
+    aquire_label(c.cue_text=cue_list[cue_list_number].cue_text);
+    aquire_label(c.cue_desc=cue_list[cue_list_number].cue_desc);
+    c.tag=tagno;
+    c.tag_create_p=0;
+    memset(&c.mix,0,sizeof(mix));
+    c.mix.vol_master=100;
+    c.mix.vol_ms=10;
+    c.mix.outvol[0][0]=100;
+    c.mix.outvol[1][1]=100;
+
+    add_cue(cue_list_number+1,c);
+  }
+
+  /* go to main edit menu */
+  edit_mix_menu(cue_list_number+1);
+
+  return(MENU_EDIT);
+}
+
 int edit_cue_menu(){
   form f;
   char label[12]="";
@@ -1590,13 +1947,13 @@
   int last=first;
   int actions,i;
 
-  while(cue_list[last].tag!=-1)last++;
+  while(last<cue_count && cue_list[last].tag!=-1)last++;
   actions=last-first;
 
   form_init(&f,4+actions);
-  strcpy(label,label_list[cue_list[base].label].text);
-  strcpy(text,label_list[cue_list[base].cue_text].text);
-  strcpy(desc,label_list[cue_list[base].cue_desc].text);
+  strcpy(label,label_text(cue_list[base].label));
+  strcpy(text,label_text(cue_list[base].cue_text));
+  strcpy(desc,label_text(cue_list[base].cue_desc));
 
   field_add(&f,FORM_GENERIC,18,2,12,label);
   field_add(&f,FORM_GENERIC,18,3,59,text);
@@ -1607,8 +1964,8 @@
     int tag=cue_list[first+i].tag;
     snprintf(buf,80,"%s sample %d (%s)",
              cue_list[first+i].tag_create_p?"ADD":"MIX",tag,
-	     label_list[tag_list[tag].sample_path].text);
-    field_add(&f,FORM_BUTTON,11,6+i,64,buf);
+	     label_text(tag_list[tag].sample_path));
+    field_add(&f,FORM_BUTTON,11,6+i,66,buf);
   }
   if(actions==0){
     mvaddstr(6,11,"--None--");
@@ -1616,8 +1973,6 @@
   }
   field_add(&f,FORM_BUTTON,66,7+i,11,"MAIN MENU");
 
-  refresh();
-
   while(1){
     int loop=1;
     clear();
@@ -1646,7 +2001,29 @@
         edit_label(cue_list[base].cue_text,text);
         edit_label(cue_list[base].cue_desc,desc);
         goto out;
-
+      case 'a':case 'A':
+	add_sample_menu();
+	form_clear(&f);
+	return(MENU_EDIT);
+      case 'm':case 'M':
+	add_mix_menu();
+	form_clear(&f);
+	return(MENU_EDIT);
+      case 'd': case 'D':
+	if(actions>0){
+	  if(f.cursor>=3 && f.cursor<3+actions){
+	    int n=first+f.cursor-3;
+	    unsaved=1;
+	    delete_cue_single(n);
+	    form_clear(&f);
+	    return(MENU_EDIT);
+	  }
+	}
+	break;
+      case 'l': case 'L':
+	//list_tag_menu();
+	loop=0;
+	break;
       case KEY_ENTER:
         if(f.cursor==3+actions){
           unsaved=1;
@@ -1656,10 +2033,11 @@
           goto out;
         }
         /* ... else we're an action edit */
-
-	{
-
-	}
+	if(cue_list[first+f.cursor-3].tag_create_p)
+	   edit_sample_menu(first+f.cursor-3);
+	else
+	   edit_mix_menu(first+f.cursor-3);
+	loop=0;
         break;
       }
     }
@@ -1702,101 +2080,59 @@
 }
   
 int main(int gratuitously,char *different[]){
+  int lf;
+
   if(gratuitously<2){
     fprintf(stderr,"Usage: beaverphonic <settingfile>\n");
     exit(1);
   }
+
+  mkdir(tempdir,0777);
+
+  /* lock against other instances */
+  lf=open(lockfile,O_CREAT|O_RDWR,0770);
+  if(lf<0){
+    fprintf(stderr,"unable to open lock file: %s.\n",strerror(errno));
+    exit(1);
+  }
   
-  initscr(); cbreak(); noecho();
-  nonl();
-  intrflush(stdscr, FALSE);
-  keypad(stdscr, TRUE);
-  use_default_colors();
-  signal(SIGINT,SIG_IGN);
+  if(flock(lf,LOCK_EX|LOCK_NB)){
+    fprintf(stderr,"Another Beaverphonic process is running.\n"
+	    "  (could not aquire lockfile)\n");
+    exit(1);
+  }
 
   /* load the sound config if the file exists, else create it */
   program=strdup(different[1]);
   {
     FILE *f=fopen(program,"rb");
     if(f){
-      load_program(f);
+      if(load_program(f)){
+	fprintf(stderr,"Press enter to continue\n");
+	getc(stdin);
+      }
       fclose(f);
     }
   }
+
+
+  initscr(); cbreak(); noecho();
+  nonl();
+  intrflush(stdscr, FALSE);
+  keypad(stdscr, TRUE);
+  use_default_colors();
+  signal(SIGINT,SIG_IGN);
+
   
   main_loop();
   endwin();                  /* restore original tty modes */  
+  close(lf);
+  unlink(lockfile);
 }  
 
 
 #if 0 
 
- Add new cue -----------------------------------------------------------------
-  cue label       [          ]
-  cue text        [                                                          ]
-  cue description [                                                          ]
-
- Edit cue --------------------------------------------------------------------
-  cue label       [          ]
-  cue text        [                                                          ]
-  cue description [                                                          ]
-
-  actions: [MIX sample 1 (                    )                              ]
-           [ADD sample 3 (                    )                              ]
-
-  ?
-  a  add sample
-  m  mix sample
-  l  list samples
-  e/enter  edit action 
-  Esc/Enter off main menu
-
- Add new sample to cue -------------------------------------------------------
-
-  cue label       [          ]
-  cue text        [                                                          ]
-  cue description [                                                          ]
-
-  sample path     [                                                          ]
-  sample tag      0 
-
-  loop            [No ]     crosslap [----]ms                           
-  volume master   [100]% fade [  15]/[  15]ms
-                            
-  --- L -- R -----------------------------------------------------------------
- |  [100][  0]% -> 0 offstage left                                            |
- |  [  0][100]% -> 1 offstage right                                           |
- |  [  0][  0]% -> 2                                                          |
- |  [  0][  0]% -> 3                                                          |
- |  [  0][  0]% -> 4                                                          |
- |  [  0][  0]% -> 5                                                          |
- |  [  0][  0]% -> 6                                                          |
- |  [  0][  0]% -> 7                                                          |
-  ----------------------------------------------------------------------------
-
- Add mix change to cue -------------------------------------------------------
-
-  cue label       [          ]
-  cue text        [                                                          ]
-  cue description [                                                          ]
-
-  modify tag      [   0]
- 
-  volume master   [100]% fade [  15]
-                            
-  --- L -- R -----------------------------------------------------------------
- |  [100][  0]% -> 0 offstage left                                            |
- |  [  0][100]% -> 1 offstage right                                           |
- |  [  0][  0]% -> 2                                                          |
- |  [  0][  0]% -> 3                                                          |
- |  [  0][  0]% -> 4                                                          |
- |  [  0][  0]% -> 5                                                          |
- |  [  0][  0]% -> 6                                                          |
- |  [  0][  0]% -> 7                                                          |
-  ----------------------------------------------------------------------------
-
- (l: list tags)
-
 OUTPUT CHANNELS
 
 0: [                         ] built in OSS left 
@@ -1805,3 +2141,8 @@
 
 
 #endif
+
+
+
+
+

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list