[xiph-commits] r18782 - trunk/postfish
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Tue Jan 22 02:29:03 PST 2013
Author: xiphmont
Date: 2013-01-22 02:29:03 -0800 (Tue, 22 Jan 2013)
New Revision: 18782
Modified:
trunk/postfish/Makefile
trunk/postfish/config.c
trunk/postfish/main.c
trunk/postfish/outpanel.c
trunk/postfish/output.c
trunk/postfish/output.h
trunk/postfish/version.h
Log:
Add libao support to Postfish (requires libao 1.2, which is not yet released)
Does automatic device discovery for OSS, ALSA and Pulse
Modified: trunk/postfish/Makefile
===================================================================
--- trunk/postfish/Makefile 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/Makefile 2013-01-22 10:29:03 UTC (rev 18782)
@@ -37,7 +37,7 @@
limit.o limitpanel.o mute.o mixpanel.o mix.o freeverb.o reverbpanel.o \
outpanel.o config.o window.o follower.o linkage.o
-GCF = -DETCDIR=\\\"$(ETCDIR)\\\" `pkg-config --cflags gtk+-2.0`
+GCF = -DETCDIR=\\\"$(ETCDIR)\\\" `pkg-config --cflags gtk+-2.0 ao \> 1.2`
all:
$(MAKE) target CFLAGS="-O2 -ffast-math -fomit-frame-pointer $(GCF) $(ADD_DEF)"
@@ -46,7 +46,7 @@
$(MAKE) target CFLAGS="-g -Wall -W -Wno-unused-parameter -D__NO_MATH_INLINES $(GCF) $(ADD_DEF)"
profile:
- $(MAKE) target CFLAGS="-pg -g -O2 -ffast-math $(GCF) $(ADD_DEF)" LIBS="-lgprof-helper "
+ $(MAKE) target CFLAGS="-pg -g -O2 -ffast-math $(GCF) $(ADD_DEF)"
clean:
rm -f $(OBJ) *.d *.d.* gmon.out postfish
@@ -76,7 +76,7 @@
target: $(OBJ) postfish-wisdomrc
./touch-version
- $(LD) $(OBJ) $(CFLAGS) -o postfish $(LIBS) `pkg-config --libs gtk+-2.0` -lpthread -lfftw3f -lm
+ $(LD) $(OBJ) $(CFLAGS) -o postfish $(LIBS) `pkg-config --libs gtk+-2.0 ao \> 1.2` -lpthread -lfftw3f -lm
install: target
$(INSTALL) -d -m 0755 $(BINDIR)
Modified: trunk/postfish/config.c
===================================================================
--- trunk/postfish/config.c 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/config.c 2013-01-22 10:29:03 UTC (rev 18782)
@@ -248,7 +248,7 @@
configentry *c=config_list+i;
if(c->string)
fprintf(f,"(%s bank%d A%d B%d C%d l%d \"%s\" )\n",
- c->key,c->bank,c->A,c->B,c->C,strlen(c->string),c->string);
+ c->key,c->bank,c->A,c->B,c->C,(int)strlen(c->string),c->string);
if(c->vec){
fprintf(f,"[%s bank%d A%d B%d C%d v%d ",
c->key,c->bank,c->A,c->B,c->C,c->vals);
Modified: trunk/postfish/main.c
===================================================================
--- trunk/postfish/main.c 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/main.c 2013-01-22 10:29:03 UTC (rev 18782)
@@ -26,13 +26,13 @@
reusable code. It's monolithic, inflexible, and designed that way
on purpose. */
-/* sound playback code is OSS-specific for now */
#include "postfish.h"
#include <signal.h>
#include <getopt.h>
#include <fenv.h> // Thank you C99!
#include <fftw3.h>
#include <gtk/gtk.h>
+#include <ao/ao.h>
#include "input.h"
#include "output.h"
#include "declip.h"
@@ -76,6 +76,7 @@
main_looping=0;
gtk_main_quit();
}
+ ao_shutdown();
exit(0);
}
@@ -331,6 +332,7 @@
}
/* probe outputs */
+ ao_initialize();
if(setvbuf(stdout, NULL, _IONBF , 0))
fprintf(stderr,"Unable to remove block buffering on stdout; continuing\n");
@@ -338,10 +340,16 @@
if(!batch) output_probe_monitor();
/* open all the input files */
- if(input_load())exit(1);
+ if(input_load()){
+ ao_shutdown();
+ exit(1);
+ }
/* load config file */
- if(config_load(configfile))exit(1);
+ if(config_load(configfile)){
+ ao_shutdown();
+ exit(1);
+ }
/* set up filter chains */
if(declip_load())exit(1);
@@ -359,7 +367,7 @@
if(pipe(eventpipe)){
fprintf(stderr,"Unable to open event pipe:\n"
" %s\n",strerror(errno));
-
+ ao_shutdown();
exit(1);
}
@@ -378,6 +386,7 @@
}else
mainpanel_go(argc,argv,input_ch);
+ ao_shutdown();
return(0);
}
Modified: trunk/postfish/outpanel.c
===================================================================
--- trunk/postfish/outpanel.c 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/outpanel.c 2013-01-22 10:29:03 UTC (rev 18782)
@@ -297,7 +297,7 @@
&state.monitor);
GtkWidget *stdout_panel=outpanel_subpanel(mp,panel,&outset.stdout,
" standard output ",
- output_stdout_device,
+ output_stdout_ao,
output_stdout_available,
&state.stdout);
Modified: trunk/postfish/output.c
===================================================================
--- trunk/postfish/output.c 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/output.c 2013-01-22 10:29:03 UTC (rev 18782)
@@ -2,7 +2,7 @@
*
* postfish
*
- * Copyright (C) 2002-2005 Monty
+ * Copyright (C) 2002-2012 Monty
*
* Postfish is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,9 +21,12 @@
*
*/
-/* sound playback code is OSS-specific for now */
-#include <linux/soundcard.h>
+/* sound playback now uses AO, but device detection only looks for OSS/ALSA/PULSE + the AO default*/
#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <ao/ao.h>
#include "postfish.h"
#include "feedback.h"
#include "input.h"
@@ -47,6 +50,16 @@
sig_atomic_t playback_seeking=0;
sig_atomic_t master_att;
+static inline int host_is_big_endian() {
+ union {
+ int32_t pattern;
+ unsigned char bytewise[4];
+ } m;
+ m.pattern = 0xfeedface; /* deadbeef */
+ if (m.bytewise[0] == 0xfe) return 1;
+ return 0;
+}
+
void output_reset(void){
/* empty feedback queues */
while(pull_output_feedback(NULL,NULL));
@@ -267,26 +280,73 @@
return 0;
}
-static int ilog(long x){
- int ret=-1;
+output_monitor_entry *monitor_list;
+int monitor_entries;
- while(x>0){
- x>>=1;
- ret++;
+/* look for sound devices that actually exist */
+
+static void add_monitor(char *file, char *name,int driver){
+ monitor_entries++;
+ if(monitor_list){
+ monitor_list=realloc(monitor_list,
+ monitor_entries*sizeof(*monitor_list));
+ }else
+ monitor_list=malloc(monitor_entries*sizeof(*monitor_list));
+
+ monitor_list[monitor_entries-1].file=file?strdup(file):NULL;
+ monitor_list[monitor_entries-1].name=strdup(name);
+ monitor_list[monitor_entries-1].driver=driver;
+}
+
+char *search_for_major_minor(char *dir,int major,int minor){
+ /* open the directory, stat entries one by one */
+ DIR *d=opendir(dir);
+ struct dirent *de;
+
+ if(d==NULL) return NULL;
+
+ while((de=readdir(d))){
+ struct stat s;
+ char buf[PATH_MAX];
+ snprintf(buf,PATH_MAX,"%s/%s",dir,de->d_name);
+ if(!stat(buf,&s)){
+ if (major==((int)(s.st_rdev>>8)&0xff) &&
+ minor==((int)(s.st_rdev&0xff))){
+ closedir(d);
+ return strdup(buf);
+ }
+ }
}
- return ret;
+
+ closedir(d);
+ return NULL;
}
static int is_oss(int f){
+ int id = ao_driver_id("oss");
struct stat s;
- if(isachr(f))
+ if(id>=0 && isachr(f))
if(!fstat(f,&s)){
int major=(int)(s.st_rdev>>8)&0xff;
int minor=(int)(s.st_rdev&0xff);
- // is this a Linux OSS audio device (Major 14) ?
- if(major==14 && ((minor&0xf)==3 || (minor&0xf)==4))return 1;
+ /* is this a Linux OSS audio device (Major 14)? */
+ if(major==14){
+ char *output_stdout_devicename = search_for_major_minor("/dev",major,minor);
+ if(!output_stdout_devicename)
+ output_stdout_devicename = search_for_major_minor("/dev/sound",major,minor);
+ if(!output_stdout_devicename){
+ fprintf(stderr,"OSS: Unable to find sound device matching stdout.\n");
+ exit(1);
+ }
+
+ add_monitor(output_stdout_devicename,output_stdout_devicename,id);
+ free(output_stdout_devicename);
+ fclose(stdout);
+ stdout=NULL;
+ return 1;
+ }
}
return 0;
@@ -294,13 +354,37 @@
static int is_alsa(int f){
struct stat s;
+ int id = ao_driver_id("alsa");
- if(isachr(f))
+ if(id>=0 && isachr(f))
if(!fstat(f,&s)){
- int type=(int)(s.st_rdev>>8);
+ int major=(int)(s.st_rdev>>8)&0xff;
+ int minor=(int)(s.st_rdev&0xff);
+ char buffer[80];
- // is this a Linux ALSA audio device (Major 116) ?
- if(type==116)return 1;
+ /* is this a Linux ALSA audio device (Major 116)? */
+ if(major==116){
+ int ret,c,d;
+
+ char *output_stdout_devicename = search_for_major_minor("/dev/snd",major,minor);
+ if(!output_stdout_devicename){
+ fprintf(stderr,"ALSA: Unable to find sound device matching stdout.\n");
+ exit(1);
+ }
+
+ /* parse the ALSA id from the device name */
+ ret=sscanf(output_stdout_devicename,"/dev/snd/pcmC%dD%dp",&c,&d);
+ if(ret!=2){
+ fprintf(stderr,"ALSA: Unable to find sound device matching stdout.\n");
+ exit(1);
+ }
+ free(output_stdout_devicename);
+ sprintf(buffer,"hw:%d,%d",c,d);
+ add_monitor(buffer,buffer,id);
+ fclose(stdout);
+ stdout=NULL;
+ return 1;
+ }
}
return 0;
@@ -313,7 +397,7 @@
}
int output_stdout_available=0;
-int output_stdout_device=0; /* 0== file, 1==OSS, 2==ALSA */
+int output_stdout_ao=0;
int output_monitor_available=0;
int output_probe_stdout(int outfileno){
@@ -326,90 +410,116 @@
}else if (isareg(outfileno)){
/* stdout is a regular file */
output_stdout_available=1;
- output_stdout_device=0;
+ output_stdout_ao=0;
}else if((ret=isaudio(outfileno))){
- /* stdout is an audio device */
+ /* stdout is an audio device; we don't actually use stdout, we'll reopen as an ao_device */
output_stdout_available=1;
- output_stdout_device=ret;
+ output_stdout_ao=1;
- if(ret==2){
- fprintf(stderr,
- "\nStdout is pointing to an ALSA sound device;\n"
- "Postfish does not yet support ALSA playback.\n\n");
- exit(1);
- }
}else{
/* God only knows what stdout is. It might be /dev/null or some other.... treat it similar to file */
output_stdout_available=1;
- output_stdout_device=0;
+ output_stdout_ao=0;
}
return 0;
}
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-output_monitor_entry *monitor_list;
-int monitor_entries;
+static void output_probe_monitor_OSS(){
+ /* open /dev and search of major 14 */
+ int id = ao_driver_id("oss");
-static char *audio_dev_type[]={"file","OSS"};
+ if(id>=0){
+ DIR *d=opendir("/dev");
+ struct dirent *de;
-/* look for sound devices that actually exist */
+ while((de=readdir(d))){
+ struct stat s;
+ char buf[PATH_MAX];
+ snprintf(buf,PATH_MAX,"/dev/%s",de->d_name);
+ if(!stat(buf,&s)){
-static void add_monitor(char *file, char *name,int type){
- monitor_entries++;
- if(monitor_list){
- monitor_list=realloc(monitor_list,
- monitor_entries*sizeof(*monitor_list));
- }else
- monitor_list=malloc(monitor_entries*sizeof(*monitor_list));
-
- monitor_list[monitor_entries-1].file=strdup(file);
- monitor_list[monitor_entries-1].name=strdup(name);
- monitor_list[monitor_entries-1].type=type;
-
- fprintf(stderr,"Found an output device (type %s): %s\n",
- audio_dev_type[type],file);
+ int major=(int)(s.st_rdev>>8)&0xff;
+ int minor=(int)(s.st_rdev&0xff);
+
+ /* is this a Linux OSS dsp audio device? (Major 14, minor 3,19...[only list /dev/dspX]) */
+ if(major==14 && (minor&0xf)==3){
+ int f=open(buf,O_RDWR|O_NONBLOCK);
+ if(f!=-1){
+ char name[80];
+ snprintf(name,80,"OSS %s",de->d_name);
+ add_monitor(buf,name,id);
+ close(f);
+ }
+ }
+ }
+ }
+
+ closedir(d);
+ }
}
-static void output_probe_monitor_OSS(){
- /* open /dev and search of major 14 */
- DIR *d=opendir("/dev");
- struct dirent *de;
-
- if(d==NULL){
- fprintf(stderr,"Odd; could not open /dev to look for audio devices.\n");
- return;
- }
-
- while((de=readdir(d))){
- struct stat s;
- char buf[PATH_MAX];
- snprintf(buf,PATH_MAX,"/dev/%s",de->d_name);
- if(!stat(buf,&s)){
-
- int major=(int)(s.st_rdev>>8)&0xff;
- int minor=(int)(s.st_rdev&0xff);
-
- // is this a Linux OSS dsp audio device (Major 14, minor 3,19,35...) ?
- if(major==14 && (minor&0xf)==3){
- int f=open(buf,O_RDWR|O_NONBLOCK);
- if(f!=-1){
- add_monitor(buf,de->d_name,1);
- close(f);
- }
+static void output_probe_monitor_ALSA(){
+ /* does this AO even have alsa output? */
+ int id = ao_driver_id("alsa");
+ if(id>=0){
+
+ /* test adding a default plug device; the format doesn't matter */
+ ao_sample_format format={16,48000,2,AO_FMT_NATIVE,NULL};
+ ao_option opt1={"dev","default",0};
+ ao_option opt={"client_name","postfish",&opt1};
+ ao_device *test=ao_open_live(id, &format, &opt);
+
+ if(test){
+ add_monitor("default","ALSA default",id);
+ ao_close(test);
+
+ /* discover hardware devices from /proc/asound/pcm */
+ {
+ FILE *pcm=fopen("/proc/asound/pcm","r");
+ if(pcm){
+ char buf[1024];
+ while(fgets(buf,1024,pcm)){
+ /* is this a playback device? */
+ if(strstr(buf,": playback ")){
+ int c,d;
+ char desc[80];
+ /* parse the card and device numbers, and the name */
+ if(sscanf(buf,"%d-%d: %*[^:]: %79[^:]",&c,&d,desc)==3){
+ /* add a monitor device */
+ snprintf(buf,1024,"ALSA %s",desc);
+ snprintf(desc,80,"hw:%d,%d",c,d);
+ add_monitor(desc,buf,id);
+ }
+ }
+ }
+ fclose(pcm);
+ }
}
}
}
-
- closedir(d);
}
+static void output_probe_monitor_pulse(){
+ /* does this AO even have pulse output? */
+ int id = ao_driver_id("pulse");
+ if(id>=0){
+ /* test open; format doesn't matter */
+ ao_sample_format format={16,48000,2,AO_FMT_NATIVE,NULL};
+ ao_option opt={"client_name","postfish",NULL};
+ ao_device *test=ao_open_live(id, &format, &opt);
+
+ if(test){
+ add_monitor(NULL,"PulseAudio",id);
+ ao_close(test);
+ }
+ }
+}
+
static int moncomp(const void *a, const void *b){
output_monitor_entry *ma=(output_monitor_entry *)a;
output_monitor_entry *mb=(output_monitor_entry *)b;
@@ -417,190 +527,154 @@
}
int output_probe_monitor(void ){
- if(output_stdout_device!=0){
+ if(output_stdout_ao!=0){
output_monitor_available=0;
return 0;
}
-
- output_probe_monitor_OSS();
-
- if(monitor_entries>0){
- output_monitor_available=1;
- /* sort the entries alphabetically by name */
- qsort(monitor_list, monitor_entries, sizeof(*monitor_list), moncomp);
+ output_probe_monitor_pulse();
+ {
+ int n = monitor_entries;
+ output_probe_monitor_ALSA();
+ if(monitor_entries>n){
+ if(monitor_entries+1>n)
+ qsort(monitor_list+n+1, monitor_entries-n-1, sizeof(*monitor_list), moncomp);
+ }else{
+ /* only search for OSS if we don't find ALSA */
+ output_probe_monitor_OSS();
+ if(monitor_entries<n){
+ qsort(monitor_list+n, monitor_entries-n, sizeof(*monitor_list), moncomp);
+ }
+ }
}
+ if(monitor_entries>0)
+ output_monitor_available=1;
+
return 0;
}
-#ifndef AFMT_S24_LE
-# define AFMT_S24_LE 0x00000800
-# define AFMT_S24_BE 0x00001000
-# define AFMT_U24_LE 0x00002000
-# define AFMT_U24_BE 0x00004000
-#endif
-
-static int OSS_playback_startup(FILE *f, int rate, int *ch, int *endian, int *bits,int *signp){
- int fd=fileno(f);
+static ao_device *playback_startup(int driver,char *device, int rate, int *ch, int *endian, int *bits,int *signp){
+ ao_device *ret = NULL;
int downgrade=0;
- int failflag=1;
+ int downgrade_dev=0;
int local_ch=*ch;
int local_bits=*bits;
+ char localdevice[80];
- *endian=(AFMT_S16_NE==AFMT_S16_BE?1:0);
-
+ *endian=host_is_big_endian();
+ if(device)
+ strncpy(localdevice,device,80);
+
/* try to configure requested playback. If it fails, keep dropping back
until one works */
while(local_ch || local_bits>16){
- int format;
-
+ ao_sample_format format;
+ ao_option opt1={"dev",localdevice,0};
+ ao_option opt={"client_name","postfish",&opt1};
+ if(!device)opt.next=0;
+
+ format.rate=rate;
+ format.channels=local_ch;
+ format.byte_format=AO_FMT_NATIVE;
+ format.matrix=0;
+
switch(local_bits){
case 8:
- format=AFMT_U8;
+ format.bits=8;
*signp=0;
break;
case 16:
- format=AFMT_S16_NE;
+ format.bits=16;
*signp=1;
break;
case 24:
- format=AFMT_S24_LE;
- if(*endian)format=AFMT_S24_BE;
+ format.bits=24;
*signp=1;
break;
}
-
- /* try to lower the DSP delay; this ioctl may fail gracefully */
- {
-
- long bytesperframe=(local_bits+7)/8*local_ch*input_size;
- int fraglog=ilog(bytesperframe);
- int fragment=0x00040000|fraglog,fragcheck;
-
- fragcheck=fragment;
- int ret=ioctl(fd,SNDCTL_DSP_SETFRAGMENT,&fragment);
- if(ret || fragcheck!=fragment){
- fprintf(stderr,"Could not set DSP fragment size; continuing.\n");
+
+ ret = ao_open_live(driver,&format,&opt);
+ if(ret) break;
+
+ /* first, if this is ALSA, use a plughw instead of a hw device */
+ if(driver==ao_driver_id("alsa") && strstr(localdevice,"hw:")==localdevice){
+ snprintf(localdevice,80,"plug%s",device);
+ downgrade_dev=1;
+ }else{
+ /* first try decreasing bit depth */
+ downgrade=1;
+ if(local_bits==24){
+ local_bits=16;
+ }else{
+ /* next, drop channels */
+ local_bits=*bits;
+ local_ch--;
}
}
-
- /* format, channels, rate */
- {
- int temp=format;
- int ret=ioctl(fd,SNDCTL_DSP_SETFMT,&temp);
- if(ret || format!=temp) goto failset;
- }
-
- {
- int temp=local_ch;
- int ret=ioctl(fd,SNDCTL_DSP_CHANNELS,&temp);
- if(ret || temp!=local_ch) goto failset;
- }
-
- {
- int temp=rate;
- int ret=ioctl(fd,SNDCTL_DSP_SPEED,&temp);
- if(ret || temp!=rate) goto failset;
- }
-
- failflag=0;
- break;
-
- failset:
- downgrade=1;
-
- /* first try decreasing bit depth */
- if(local_bits==24){
- local_bits=16;
- }else{
-
- /* next, drop channels */
- local_bits=*bits;
- local_ch--;
- }
-
- ioctl(fd,SNDCTL_DSP_RESET);
}
- if(failflag || downgrade)
- fprintf(stderr,"Unable to set playback for %d bits, %d channels, %dHz\n",
- *bits,*ch,rate);
- if(downgrade && !failflag)
+ if(!ret || downgrade_dev || downgrade)
+ fprintf(stderr,"Unable to open %s for %d bits, %d channels, %dHz\n",
+ device,*bits,*ch,rate);
+ if(downgrade && ret)
fprintf(stderr,"\tUsing %d bits, %d channels, %dHz instead\n",
local_bits,local_ch,rate);
- if(failflag)return -1;
-
+ else if(downgrade_dev && ret)
+ fprintf(stderr,"\tUsing plug%s instead\n",
+ device);
+
*bits=local_bits;
*ch=local_ch;
-
- return 0;
+
+ return ret;
}
-static int output_startup(FILE *f, int devtype, int format, int rate, int *ch, int *endian, int *bits,int *signp){
- switch(devtype){
- case 0: // pipe, regular file or file device
- switch(format){
- case 0:
+static int file_startup(FILE *f, int format, int rate, int *ch, int *endian, int *bits,int *signp){
+ switch(format){
+ case 0:
/* WAVE format */
- ftruncate(fileno(f),0);
- WriteWav(f,*ch,rate,*bits,-1);
- *endian=0;
- *signp=1;
+ ftruncate(fileno(f),0);
+ WriteWav(f,*ch,rate,*bits,-1);
+ *endian=0;
+ *signp=1;
+ if(*bits==8)*signp=0;
+ break;
+ case 1:
+ /* AIFF-C format */
+ ftruncate(fileno(f),0);
+ WriteAifc(f,*ch,rate,*bits,-1);
+ *endian=1;
+ *signp=1;
+ break;
+ case 2:
+ /* raw little endian */
+ *endian=0;
+ *signp=1;
+ if(*bits==8)*signp=0;
+ break;
+ case 3:
+ /* raw big endian */
+ *endian=1;
+ *signp=1;
if(*bits==8)*signp=0;
break;
- case 1:
- /* AIFF-C format */
- ftruncate(fileno(f),0);
- WriteAifc(f,*ch,rate,*bits,-1);
- *endian=1;
- *signp=1;
- break;
- case 2:
- /* raw little endian */
- *endian=0;
- *signp=1;
- if(*bits==8)*signp=0;
- break;
- case 3:
- /* raw big endian */
- *endian=1;
- *signp=1;
- if(*bits==8)*signp=0;
- break;
- default:
- fprintf(stderr,"Unsupported output file format selected!\n");
- return -1;
- }
- return 0;
-
- case 1: // OSS playback
- return OSS_playback_startup(f, rate, ch, endian, bits, signp);
-
- default: // undefined for now
- fprintf(stderr,"Unsupported playback device selected\n");
+ default:
+ fprintf(stderr,"Unsupported output file format selected!\n");
return -1;
}
+ return 0;
}
-static void output_halt(FILE *f,int devtype,int format, int rate, int ch, int endian, int bits,int signp,
- off_t bytecount){
- switch(devtype){
+static void file_halt(FILE *f,int format, int rate, int ch, int endian, int bits,int signp,
+ off_t bytecount){
+ switch(format){
case 0:
- switch(format){
- case 0:
- WriteWav(f,ch,rate,bits,bytecount); // will complete header only if stream is seekable
- break;
- case 1:
- WriteAifc(f,ch,rate,bits,bytecount); // will complete header only if stream is seekable
- break;
- }
+ WriteWav(f,ch,rate,bits,bytecount); // will complete header only if stream is seekable
break;
- case 1: // OSS
- {
- int fd=fileno(f);
- ioctl(fd,SNDCTL_DSP_RESET);
- }
+ case 1:
+ WriteAifc(f,ch,rate,bits,bytecount); // will complete header only if stream is seekable
+ break;
}
}
@@ -627,7 +701,7 @@
for(j=0;j<ch;j++){
unsigned char *o=audiobuf+bytes*j;
if(!mute_channel_muted(link->active,j) && source[j]){
-
+
float *d=link->data[j];
for(i=0;i<link->samples;i++){
@@ -636,7 +710,7 @@
if(val>8388607)val=8388607;
if(val<-8388608)val=-8388608;
val ^= signxor;
-
+
switch(endbytecase){
case 2:
/* LE 24 */
@@ -668,7 +742,7 @@
}else{
for(i=0;i<link->samples;i++){
int32_t val = signxor;
-
+
switch(endbytecase){
case 2:case 5:
/* 24 */
@@ -683,7 +757,7 @@
*o++=val>>16;
break;
}
-
+
o+=bytestep;
}
}
@@ -698,7 +772,7 @@
void *playback_thread(void *dummy){
int i,j,k;
unsigned char *audiobuf;
- int bigendianp=(AFMT_S16_NE==AFMT_S16_BE?1:0);
+ int bigendianp=host_is_big_endian();
time_linkage *link;
int result;
off_t output_bytecount=0;
@@ -712,7 +786,7 @@
long offset=0;
/* monitor setup */
- FILE *monitor_fd=NULL;
+ ao_device *monitor_device=NULL;
int monitor_bits;
int monitor_ch;
int monitor_endian=bigendianp;
@@ -720,6 +794,7 @@
int monitor_started=0;
int monitor_devicenum=outset.monitor.device;
+ ao_device *stdout_device=NULL;
int stdout_bits;
int stdout_ch;
int stdout_endian;
@@ -732,7 +807,7 @@
for(j=OUTPUT_CHANNELS-1;j>=0;j--){
for(i=0;i<input_ch;i++){
mix_settings *m=mix_set+i;
-
+
if(m->placer_destA[j] ||
m->placer_destB[j])break;
@@ -775,7 +850,7 @@
break;
}
}
-
+
if(output_stdout_available){
int ch=outset.stdout.ch;
int bits=outset.stdout.bytes;
@@ -795,7 +870,7 @@
/* bits */
switch(bits){
case 0:
- if(output_stdout_device)
+ if(output_stdout_ao)
stdout_bits=16;
else
stdout_bits=24;
@@ -814,7 +889,7 @@
}
audiobuf=malloc(input_size*OUTPUT_CHANNELS*4); // largest possible need
-
+
while(1){
/* the larger lock against seeking is primarily cosmetic, but
@@ -826,12 +901,12 @@
pipeline_reset();
playback_seeking=0;
}
-
+
if(playback_exit){
pthread_mutex_unlock(&input_mutex);
break;
}
-
+
offset+=input_size;
/* get data */
@@ -876,14 +951,14 @@
if(!result)break;
/************/
-
+
/* master att */
if(link->samples>0){
int att=master_att;
if(att==att_last){
float scale=fromdB(att/10.);
-
+
for(i=0;i<link->samples;i++)
for(j=0;j<link->channels;j++)
link->data[j][i]*=scale;
@@ -891,7 +966,7 @@
/* slew-limit the scaling */
float scale=fromdB(att_last*.1);
float mult=fromdB((att-att_last)*.1 / input_size);
-
+
for(i=0;i<link->samples;i++){
for(j=0;j<link->channels;j++)
link->data[j][i]*=scale;
@@ -908,43 +983,26 @@
if(link->samples>0){
/* final limiting and conversion */
-
+
/* monitor output */
if(output_monitor_available){
if(outset.panel_active[0]){
-
+
/* lazy playback init */
if(!monitor_started){
- /* nonblocking open... just in case this is an exclusive
- use device currently used by something else */
- int mfd=open(monitor_list[monitor_devicenum].file,O_RDWR|O_NONBLOCK);
- if(mfd==-1){
- fprintf(stderr,"unable to open audio monitor device %s for playback.\n",
- monitor_list[monitor_devicenum].file);
+ monitor_device =
+ playback_startup(monitor_list[monitor_devicenum].driver,
+ monitor_list[monitor_devicenum].file,
+ input_rate,
+ &monitor_ch,&monitor_endian,&monitor_bits,&monitor_signp);
+ if(!monitor_device){
+ outpanel_monitor_off();
+ fprintf(stderr,"unable to open audio monitor device %s (%s) for playback.\n",
+ monitor_list[monitor_devicenum].file,monitor_list[monitor_devicenum].name);
outpanel_monitor_off();
}else{
- fcntl(mfd,F_SETFL,0); /* unset non-blocking */
- monitor_fd=fdopen(dup(mfd),"wb");
- close(mfd);
-
- if(monitor_fd==NULL){
- fprintf(stderr,"unable to fdopen audio monitor device %s for playback.\n",
- monitor_list[monitor_devicenum].file);
- outpanel_monitor_off();
- }else{
- if(setvbuf(monitor_fd, NULL, _IONBF , 0)){
- fprintf(stderr,"Unable to remove block buffering on audio monitor; continuing\n");
- }
-
- if(output_startup(monitor_fd,monitor_list[monitor_devicenum].type,0,input_rate,
- &monitor_ch,&monitor_endian,&monitor_bits,&monitor_signp)){
- outpanel_monitor_off();
- fclose(monitor_fd);
- monitor_fd=NULL;
- }else
- monitor_started=1;
- }
+ monitor_started=1;
}
}
@@ -952,48 +1010,59 @@
int outbytes=outpack(link,audiobuf,monitor_ch,
monitor_bits,monitor_endian,monitor_signp,
outset.monitor.source);
-
- fwrite(audiobuf,1,outbytes,monitor_fd);
+ ao_play(monitor_device,(char *)audiobuf,outbytes);
}
}else{
if(monitor_started){
/* halt playback */
- output_halt(monitor_fd,monitor_list[monitor_devicenum].type,0,input_rate,monitor_ch,
- monitor_endian,monitor_bits,monitor_signp,-1);
- fclose(monitor_fd);
- monitor_fd=NULL;
+ ao_close(monitor_device);
+ monitor_device=NULL;
monitor_started=0;
}
}
}
-
+
/* standard output */
if(output_stdout_available){
if(outset.panel_active[1]){
/* lazy playback/header init */
if(!stdout_started){
- if(output_startup(stdout,output_stdout_device,stdout_format,input_rate,
+ if(output_stdout_ao){ // AO device
+ stdout_device =
+ playback_startup(monitor_list[0].driver,
+ monitor_list[0].file,
+ input_rate,
+ &stdout_ch,&stdout_endian,&stdout_bits,&stdout_signp);
+ if(!stdout_device){
+ outpanel_stdout_off();
+ fprintf(stderr,"unable to open stdout device for playback.\n");
+ }else
+ stdout_started=1;
+ }else{
+ if(file_startup(stdout,stdout_format,input_rate,
&stdout_ch,&stdout_endian,&stdout_bits,&stdout_signp))
- outpanel_stdout_off();
- else
- stdout_started=1;
- }
+ outpanel_stdout_off();
+ else
+ stdout_started=1;
+ }
+ }
if(stdout_started){
int outbytes=outpack(link,audiobuf,stdout_ch,
stdout_bits,stdout_endian,stdout_signp,
outset.stdout.source);
-
- output_bytecount+=fwrite(audiobuf,1,outbytes,stdout);
+ if(output_stdout_ao) // AO device
+ ao_play(stdout_device,(char *)audiobuf,outbytes);
+ else
+ output_bytecount+=fwrite(audiobuf,1,outbytes,stdout);
}
}else{
if(stdout_started){
/* if stdout is a device, halt playback. Otherwise, write nothing */
- if(output_stdout_device){
- /* halt playback */
- output_halt(stdout,output_stdout_device,0,input_rate,stdout_ch,stdout_endian,
- stdout_bits,stdout_signp,-1);
+ if(output_stdout_ao){
+ ao_close(stdout_device);
+ stdout_device=NULL;
stdout_started=0;
}
}
@@ -1025,17 +1094,19 @@
}
/* shut down monitor */
- if(monitor_fd){
+ if(monitor_device){
if(monitor_started)
- output_halt(monitor_fd,monitor_list[monitor_devicenum].type,0,input_rate,monitor_ch,
- monitor_endian,monitor_bits,monitor_signp,-1);
- fclose(monitor_fd);
+ ao_close(monitor_device);
}
/* shut down stdout playback or write final header */
- if(stdout_started)
- output_halt(stdout,output_stdout_device,stdout_format,input_rate,stdout_ch,stdout_endian,
+ if(stdout_started){
+ if(output_stdout_ao)
+ ao_close(stdout_device);
+ else
+ file_halt(stdout,stdout_format,input_rate,stdout_ch,stdout_endian,
stdout_bits,stdout_signp,output_bytecount);
+ }
pipeline_reset();
playback_active=0;
Modified: trunk/postfish/output.h
===================================================================
--- trunk/postfish/output.h 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/output.h 2013-01-22 10:29:03 UTC (rev 18782)
@@ -38,13 +38,13 @@
} output_settings;
typedef struct {
- int type;
+ int driver;
char *name;
char *file;
} output_monitor_entry;
extern int output_stdout_available;
-extern int output_stdout_device;
+extern int output_stdout_ao;
extern int output_monitor_available;
extern output_monitor_entry *monitor_list;
extern int monitor_entries;
Modified: trunk/postfish/version.h
===================================================================
--- trunk/postfish/version.h 2013-01-22 10:26:45 UTC (rev 18781)
+++ trunk/postfish/version.h 2013-01-22 10:29:03 UTC (rev 18782)
@@ -1,2 +1,2 @@
#define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Wed Aug 1 11:37:36 EDT 2012] */
+/* DO NOT EDIT: Automated versioning hack [Tue Jan 22 05:15:23 EST 2013] */
More information about the commits
mailing list