Switch pulseaudio driver to complex api for low latency, set as default
authorAlexander Koenig <alex@lisas.de>
Wed, 15 Jun 2016 21:39:21 +0000 (23:39 +0200)
committerAlexander Koenig <alex@lisas.de>
Wed, 15 Jun 2016 21:39:21 +0000 (23:39 +0200)
driver.

src/tX_audiodevice.cc
src/tX_audiodevice.h
src/tX_audiofile.cc
src/tX_dial.c
src/tX_dialog.cc
src/tX_flash.c
src/tX_global.c
src/tX_global.h
src/tX_ui_interface.cc

index b21580a7ac370e84eeace26ad034883da6898d88..6e8223bc2b4665591e03af8dd58d5b1995992cb8 100644 (file)
@@ -354,75 +354,244 @@ void tX_audiodevice_alsa :: play(int16_t *buffer)
 #ifdef USE_PULSE
 #include <pulse/error.h>
 
-int tX_audiodevice_pulse :: open()
-{
-       int error;
+void tX_audiodevice_pulse::wrap_stream_started_callback(pa_stream *stream, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->stream_started_callback(stream);
+}
 
-       /* pulse client based on pacat-simple.c API demo */
-       pa_sample_spec spec = {
-               .format = PA_SAMPLE_S16LE,
-               .rate = 44100,
-               .channels = 2
-       };
+void tX_audiodevice_pulse::wrap_stream_underflow_callback(pa_stream *stream, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->stream_underflow_callback(stream);
+}
 
-       
-       pa_buffer_attr attr = {
-               .maxlength = (uint32_t) -1,
-               .tlength = 2048,
-               .prebuf = 1,
-               .minreq = (uint32_t) -1,
-               .fragsize = (uint32_t) -1
-       };
+void tX_audiodevice_pulse::wrap_stream_overflow_callback(pa_stream *stream, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->stream_overflow_callback(stream);
+}
 
-       attr.minreq = attr.tlength / 4;
-       attr.maxlength = attr.tlength + attr.minreq;
+void tX_audiodevice_pulse::wrap_stream_drain_complete_callback(pa_stream *stream, int success, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->stream_drain_complete_callback(stream, success);
+}
+
+void tX_audiodevice_pulse::wrap_stream_trigger_success_callback(pa_stream *stream, int success, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->stream_trigger_success_callback(stream, success);
+}
+
+void tX_audiodevice_pulse::wrap_stream_write_callback(pa_stream *stream, size_t length, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->stream_write_callback(stream, length);
+}
+
+void tX_audiodevice_pulse::wrap_context_state_callback(pa_context *context, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->context_state_callback(context);
+}
+
+void tX_audiodevice_pulse::context_state_callback(pa_context *context) {
+       pa_context_state_t state;
+
+       state = pa_context_get_state(context);
+
+       tX_debug("pulseaudio context state: %i", state);
+       switch (state) {
+               case PA_CONTEXT_FAILED:
+               case PA_CONTEXT_TERMINATED:
+                       tX_error("pulseaudio disconnected");
+                       break;
+
+               case PA_CONTEXT_READY:
+                       pa_sample_spec spec = {
+                               .format = PA_SAMPLE_S16LE,
+                               .rate = 44100,
+                               .channels = 2
+                       };
+       
+                       pa_buffer_attr attr = {
+                               .maxlength = (uint32_t) -1,
+                               .tlength = globals.pulse_buffer_length * 4, // 2 bytes per sample, 2 channels
+                               .prebuf = (uint32_t) -1,
+                               .minreq = (uint32_t) -1,
+                               .fragsize = (uint32_t) -1
+                       };
+
+                       pa_stream_flags_t flags = PA_STREAM_ADJUST_LATENCY;
+
+                       if (stream = pa_stream_new(context, "terminatorX", &spec, NULL)) {
+                               tX_debug("pulseaudio stream created");
+                               //pa_stream_set_started_callback(stream, tX_audiodevice_pulse::wrap_stream_started_callback, this);
+                               //pa_stream_set_underflow_callback(stream, tX_audiodevice_pulse::wrap_stream_underflow_callback, this);
+                               pa_stream_set_overflow_callback(stream, tX_audiodevice_pulse::wrap_stream_overflow_callback, this);
+                               pa_stream_set_write_callback(stream, tX_audiodevice_pulse::wrap_stream_write_callback, this);
+
+                               if (pa_stream_connect_playback(stream, NULL, &attr, flags, NULL, NULL) >= 0) {
+                                       // start the playback.
+                                       pa_stream_trigger(stream, tX_audiodevice_pulse::wrap_stream_trigger_success_callback, this);
+                               } else {
+                                       tX_error("Failed to connect pulseaudio stream playback: %s", pa_strerror(pa_context_errno(context)));
+                               }
+                       }       else {
+                               tX_error("Failed to create pulseaudio stream: %s", pa_strerror(pa_context_errno(context)));
+                       }
 
-       samples_per_buffer = attr.tlength / 2;
-       
-       /* Create a new playback stream */
-       if (!(stream = pa_simple_new(NULL, "terminatorX", PA_STREAM_PLAYBACK, NULL, "playback", &spec, NULL, &attr, &error))) {
-               tX_error("PULSE: Failed to open stream: %s", pa_strerror(error));
-               return -1;
        }
-       
-       is_open = true;
+}
 
-        pa_usec_t latency;
+void tX_audiodevice_pulse::wrap_context_drain_complete_callback(pa_context *context, void *userdata) {
+       tX_audiodevice_pulse *device = (tX_audiodevice_pulse *) userdata;
+       device->context_drain_complete_callback(context);
+}
 
-        if ((latency = pa_simple_get_latency(stream, &error)) == (pa_usec_t) -1) {
-            tX_error("PULSE: Error getting latency  %s\n", pa_strerror(error));
-        }
+void tX_audiodevice_pulse::context_drain_complete_callback(pa_context *context) {
+       pa_context_disconnect(context);
+       is_open = false;
+       pa_mainloop_quit(mainloop, 0);
+}
 
-        tX_debug( "%0.0f usec    \r", (float)latency);
+void tX_audiodevice_pulse::stream_started_callback(pa_stream *stream) {
+       tX_debug("pulseaudio stream started");
+}
 
-       return 0;
+void tX_audiodevice_pulse::stream_underflow_callback(pa_stream *stream) {
+       tX_debug("pulseaudio stream underflow");
 }
 
-int tX_audiodevice_pulse :: close()
-{
-       if (is_open) {
-               pa_simple_free(stream);
+void tX_audiodevice_pulse::stream_overflow_callback(pa_stream *stream) {
+       tX_debug("pulseaudio stream overflow");
+}
+
+void tX_audiodevice_pulse::stream_trigger_success_callback(pa_stream *stream, int success) {
+       tX_debug("pulseaudio trigger success %i", success);
+}
+
+void tX_audiodevice_pulse::stream_drain_complete_callback(pa_stream *stream, int success) {
+       if (!success) {
+               tX_debug("pulseaudio drain failed %s", pa_strerror(pa_context_errno(context)));
+       } else {
+               pa_operation *operation;
+               pa_stream_disconnect(stream);
+               pa_stream_unref(stream);
                stream = NULL;
+
+               if (!(operation = pa_context_drain(context, tX_audiodevice_pulse::wrap_context_drain_complete_callback, this))) {
+                       pa_context_disconnect(context);
+                       is_open = false;
+                       pa_mainloop_quit(mainloop, -1);
+               } else {
+                       pa_operation_unref(operation);
+               }
        }
+}
 
-       is_open=false;
+void tX_audiodevice_pulse::stream_write_callback(pa_stream *stream, size_t length) {
+       size_t sample_length = length/2;
+
+       if (engine->is_stopped()) {
+               tX_debug("pulseaudio write callback trying to disconnect pulseaudio");
+               pa_operation *operation;
+               pa_stream_set_write_callback(stream, NULL, NULL);
+               if (!(operation = pa_stream_drain(stream, tX_audiodevice_pulse::wrap_stream_drain_complete_callback, this))) {
+                       tX_error("pulseaudio failed to initiate drain %s", pa_strerror(pa_context_errno(context)));
+               }
+               pa_operation_unref(operation);
+       } else {
+               //tX_debug("pulseaudio write %i samples", sample_length);
+               unsigned int outbuffer_pos=0;
+               unsigned int sample;
+       
+               // re-alloc outbuffer only when not yet allocated or allocated buffer smaller
+               // than the chunk requested by pulseaudio
+/*             if (!outbuffer || (outbuffer_length < sample_length)) {
+                       if (outbuffer) {
+                               pa_xfree(outbuffer);
+                       }
+                       outbuffer = (int16_t* ) pa_xmalloc(length);
+                       outbuffer_length = sample_length;
+               }
+*/
+
+               int16_t *outbuffer = NULL;
+               size_t outbuffer_bytes = length;
+               pa_stream_begin_write(stream, (void **) &outbuffer, &outbuffer_bytes);
+
+               //tX_debug("begin write %i %i", outbuffer_bytes, length)
+
+               if (samples_in_overrun_buffer) {
+                       for (sample=0; ((sample<samples_in_overrun_buffer) && (outbuffer_pos<sample_length));) {
+                               outbuffer[outbuffer_pos++]=overrun_buffer[sample++];
+                       }
+               }
        
+               while (outbuffer_pos<sample_length) {
+                       //tX_debug("render %i %i %i", outbuffer_pos, sample_length, vtt_class::samples_in_mix_buffer);
+                       int16_t *data=engine->render_cycle();
+               
+                       for (sample=0; ((sample<(unsigned int) vtt_class::samples_in_mix_buffer) && (outbuffer_pos<sample_length));) {
+                               outbuffer[outbuffer_pos++]=data[sample++];
+                       }
+               
+                       if (sample<(unsigned int) vtt_class::samples_in_mix_buffer) {
+                               samples_in_overrun_buffer=vtt_class::samples_in_mix_buffer-sample;
+                               /* There's more data in the mixbuffer... */
+                               memcpy(overrun_buffer, &data[sample], sizeof(int16_t) * samples_in_overrun_buffer);
+                       } else {
+                               samples_in_overrun_buffer=0;
+                       }
+               }
+       
+               //tX_debug("write %i bytes", length);
+               if (pa_stream_write(stream, (uint8_t *) outbuffer, length, NULL, 0, PA_SEEK_RELATIVE) < 0) {
+                       tX_error("pulseaudio error writing to stream: %s", pa_strerror(pa_context_errno(context)));
+               }
+               outbuffer = NULL;
+       }
+}
+
+void tX_audiodevice_pulse::start() {
+       overrun_buffer=new int16_t[vtt_class::samples_in_mix_buffer];
+       samples_in_overrun_buffer = 0;
+       int result;
+       
+       tX_debug("handover flow control to pulseaudio");
+
+       while (!engine->is_stopped()) {
+               pa_mainloop_run(mainloop, &result);
+               tX_debug("pulseaudio mainloop has terminated: %i", result);
+       }       
+       
+       delete [] overrun_buffer;
+}
+
+int tX_audiodevice_pulse::open() {
+       mainloop = pa_mainloop_new();
+       mainloop_api = pa_mainloop_get_api(mainloop);
+       context = pa_context_new(mainloop_api, "terminatorX");
+       pa_context_flags_t flags = PA_CONTEXT_NOFLAGS;
+       pa_context_connect(context, NULL, flags, NULL);
+       pa_context_set_state_callback(context, tX_audiodevice_pulse::wrap_context_state_callback, this);
+
+       sample_rate=44100;
+       tX_debug("pulseaudio opened.");
+
+       is_open = true;
        return 0;
 }
 
-tX_audiodevice_pulse :: tX_audiodevice_pulse() : tX_audiodevice(),
-stream(NULL) {}
+int tX_audiodevice_pulse :: close() {
+       return 0;
+}
 
-void tX_audiodevice_pulse :: play(int16_t *buffer)
-{
-       int error;
+tX_audiodevice_pulse :: tX_audiodevice_pulse() : tX_audiodevice(),
+mainloop(NULL), mainloop_api(NULL), context(NULL), stream(NULL)  {
+}
 
-        if (pa_simple_write(stream, buffer, (size_t) samples_per_buffer * 2, &error) < 0) {
-               tX_error("PULSE: playback failed: %s\n", pa_strerror(error));
-           return;
-        }
+void tX_audiodevice_pulse :: play(int16_t *buffer) {
+       tX_error("tX_audiodevice_pulse::play()");
 }
 
+tX_audiodevice_pulse :: ~tX_audiodevice_pulse() {
+}
 
 #endif //USE_PULSE
 
@@ -430,6 +599,7 @@ void tX_audiodevice_pulse :: play(int16_t *buffer)
 
 tX_jack_client tX_jack_client::instance;
 
+
 bool tX_jack_client::init()
 {
        if (!client_initialized) {
index dddd22949eaa13ed9d43d39f886b5d3648506fbc..e665b2bf47cb4faab1b279f73064c131e96cf7a6 100644 (file)
@@ -41,7 +41,7 @@
 #endif
 
 #ifdef USE_PULSE
-#include <pulse/simple.h>
+#include <pulse/pulseaudio.h>
 #endif
 
 class tX_engine;
@@ -115,14 +115,48 @@ class tX_audiodevice_alsa : public tX_audiodevice
 
 class tX_audiodevice_pulse : public tX_audiodevice
 {
-       pa_simple *stream;
-       
+       pa_mainloop *mainloop;
+       pa_mainloop_api *mainloop_api;
+       pa_context *context;
+       pa_stream *stream;
+       int16_t *overrun_buffer;
+       unsigned int samples_in_overrun_buffer;
+
        public:
        virtual int open();
        virtual int close();
+       virtual void start();
        virtual void play(int16_t*);
-       
+
        tX_audiodevice_pulse();
+       ~tX_audiodevice_pulse();
+       
+       private:
+       // context callbacks
+       static void wrap_context_state_callback(pa_context *context, void *userdata);
+       void context_state_callback(pa_context *context);
+
+       static void wrap_context_drain_complete_callback(pa_context *context, void *userdata);
+       void context_drain_complete_callback(pa_context *context);
+
+       // stream callbacks
+       static void wrap_stream_started_callback(pa_stream *stream, void *userdata);
+       void stream_started_callback(pa_stream *stream);
+
+       static void wrap_stream_underflow_callback(pa_stream *stream, void *userdata);
+       void stream_underflow_callback(pa_stream *stream);
+       
+       static void wrap_stream_overflow_callback(pa_stream *stream, void *userdata);
+       void stream_overflow_callback(pa_stream *stream);
+       
+       static void wrap_stream_drain_complete_callback(pa_stream *stream, int success, void *userdata);
+       void stream_drain_complete_callback(pa_stream *stream, int success);
+
+       static void wrap_stream_trigger_success_callback(pa_stream *stream, int success, void *userdata);
+       void stream_trigger_success_callback(pa_stream *stream, int success);
+
+       static void wrap_stream_write_callback(pa_stream *stream, size_t length, void *userdata);
+       void stream_write_callback(pa_stream *stream, size_t length);
 };
 
 #endif
index 61e7c978cfd19d03dd91df5ecdd55ee2e1f39145..3e2420b78e82b3fe2d240f2222ec38da91b32fcd 100644 (file)
@@ -312,7 +312,7 @@ tX_audio_error tx_audiofile :: load_wav() {
                bytes = fread(p, 1, min(1024, wav_in.len-allbytes), wav_in.handle);
 
 #ifdef ENABLE_DEBUG_OUTPUT
-               if (output) { tX_debug("tX_audiofile::load_wav() read %i Bytes [%04x %04x %04x %04x %04x %04x ..]", bytes, (unsigned int) p[0],  (unsigned int) p[1], (unsigned int) p[2], (unsigned int) p[3], (unsigned int) p[4], (unsigned int) p[5]); }
+               if (output) { tX_debug("tX_audiofile::load_wav() read %zu Bytes [%04x %04x %04x %04x %04x %04x ..]", bytes, (unsigned int) p[0],  (unsigned int) p[1], (unsigned int) p[2], (unsigned int) p[3], (unsigned int) p[4], (unsigned int) p[5]); }
 #endif
 
                if (bytes<=0) {
@@ -523,7 +523,7 @@ int tx_audiofile::mad_decode(unsigned char const *start, unsigned long length) {
        buffer.sample_rate=0;
        buffer.lost_sync_counter=0;
 
-       tX_debug("tx_audiofile::mad_decode() - start %016" PRIxPTR ", length %i", (uintptr_t) buffer.start, buffer.size);
+       tX_debug("tx_audiofile::mad_decode() - start %016" PRIxPTR ", length %zu", (uintptr_t) buffer.start, buffer.size);
        /* configure input, output, and error functions */
 
        mad_decoder_init(&decoder, &buffer, tX_mad_input, NULL, NULL, tX_mad_output, tX_mad_error, NULL);
index f9ec8550b7766669ac6693d9d9eb311618fb5737..0be706c6ef800296bf65a4df05946ce6fb6d414c 100644 (file)
@@ -252,21 +252,6 @@ static void gtk_tx_dial_size_allocate (GtkWidget *widget, GtkAllocation *allocat
        }
 }
 
-inline void gtk_tx_dial_do_draw (GtkTxDial *tx_dial, GtkWidget *widget, cairo_t *cr)
-{
-       if (gtk_widget_is_drawable (widget)) {
-//             gdk_draw_pixbuf(gtk_widget_is_drawable (widget), 
-//                             //gtk_widget_get_stlye(widget)->bg_gc[GTK_WIDGET_STATE(widget)],
-//                             NULL, //TODO: this needs to be ported to cairo!
-//                             knob_pixmaps[tx_dial->old_image],
-//                             0, 0, tx_dial->xofs, tx_dial->yofs,
-//                                             tX_knob_size, tX_knob_size, GDK_RGB_DITHER_NORMAL, 0, 0);
-
-               gdk_cairo_set_source_pixbuf (cr, knob_pixmaps[tx_dial->old_image], 0, 0);
-               cairo_paint (cr);
-       }                
-}
-
 gboolean gtk_tx_dial_draw (GtkWidget *widget, cairo_t *cr)
 {
        GtkTxDial *tx_dial;
@@ -276,7 +261,10 @@ gboolean gtk_tx_dial_draw (GtkWidget *widget, cairo_t *cr)
        
        tx_dial = GTK_TX_DIAL (widget);
        
-       gtk_tx_dial_do_draw(tx_dial, widget, cr);
+       if (gtk_widget_is_drawable (widget)) {
+               gdk_cairo_set_source_pixbuf (cr, knob_pixmaps[tx_dial->old_image], 0, 0);
+               cairo_paint (cr);
+       }                
                  
        return FALSE;
 }
index f0d902f39de26f9666d3f6ae594c1abe314ca084..2baf1bdc29014332eed43738aab28f07bf559d16 100644 (file)
@@ -68,7 +68,6 @@ void apply_options(GtkWidget *dialog) {
        } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "jack_driver")))) {
                globals.audiodevice_type=JACK;
        } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "pulse_driver")))) {
-               printf("pulse\n");
                globals.audiodevice_type=PULSE;
        }
        globals.use_realtime=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "use_realtime")));
@@ -93,7 +92,8 @@ void apply_options(GtkWidget *dialog) {
        globals.alsa_period_time*=1000;
        globals.alsa_samplerate=atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "alsa_samplerate")))); 
        globals.alsa_free_hwstats=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_free_hwstats")));
-       
+       globals.pulse_buffer_length=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "pulse_buffer_size")));
+
        /* TODO: JACK
        */
        
@@ -379,6 +379,9 @@ void init_tx_options(GtkWidget *dialog) {
        
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_free_hwstats")), globals.alsa_free_hwstats);
        
+       gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "pulse_buffer_size")), globals.pulse_buffer_length);
+       gtk_widget_set_tooltip_text(lookup_widget(dialog, "pulse_buffer_size"), "Sets the requested buffer size for PulseAudio in samples (per channel). Lower values should result in lower latency, however PulseAudio may override this setting.");  
+
        gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "mouse_speed")), globals.mouse_speed);
        gtk_widget_set_tooltip_text(lookup_widget(dialog, "mouse_speed"), "The speed of your mouse in scratch mode. Use negative values to invert motion.");
        
index 5dfad601917fd69da95c87c5ea9aa71f05d1d3f2..0f8ac634e4d5b9511bf2fd8878408c451bafe1c1 100644 (file)
@@ -120,7 +120,7 @@ enum {
 
 /* c=a+(a-b)*x; */
 
-inline void mk_half(double s, GdkRGBA *a, GdkRGBA *b, GdkRGBA *c)
+void mk_half(double s, GdkRGBA *a, GdkRGBA *b, GdkRGBA *c)
 {
        c->red=a->red-(a->red-b->red)*s;
        c->green=a->green-(a->green-b->green)*s;
index 6aefa41d34c94ceffca0a6f81a911f5319a6116b..92f4a406b87fa58b0679573a8237e9d55f7cc197 100644 (file)
@@ -79,7 +79,9 @@ void set_global_defaults() {
        globals.alsa_buffer_time=80000;
        globals.alsa_period_time=20000;
        globals.alsa_samplerate=44100;
-       
+
+       globals.pulse_buffer_length=320;
+
        globals.sense_cycles=80;
        
        globals.mouse_speed=0.8;
@@ -111,14 +113,18 @@ void set_global_defaults() {
        strcpy(globals.tables_filename, "");
        strcpy(globals.record_filename, "tX_record.wav");
        strcpy(globals.file_editor, "");
-               
+
+#ifdef USE_PULSE
+       globals.audiodevice_type=ALSA;
+#else  
 #ifdef USE_ALSA
        globals.audiodevice_type=ALSA;
 #else
 #ifdef USE_OSS
        globals.audiodevice_type=OSS;
 #endif 
-#endif         
+#endif 
+#endif
        globals.use_stdout_cmdline=0;
        strcpy(globals.current_path, "");
        strcpy(globals.lrdf_path, "/usr/share/ladspa/rdf:/usr/local/share/ladspa/rdf");
@@ -204,6 +210,8 @@ int load_globals_xml() {
                        restore_int("alsa_samplerate", globals.alsa_samplerate);
                        restore_int("alsa_free_hwstats", globals.alsa_free_hwstats);
                        
+                       restore_int("pulse_buffer_length", globals.pulse_buffer_length);
+
                        restore_string("xinput_device", globals.xinput_device);
                        restore_int("xinput_enable", globals.xinput_enable);
                        restore_int("update_idle", globals.update_idle);
@@ -327,6 +335,8 @@ void store_globals() {
                store_int("alsa_samplerate", globals.alsa_samplerate);          
                store_int("alsa_free_hwstats", globals.alsa_free_hwstats);
                
+               store_int("pulse_buffer_length", globals.pulse_buffer_length);
+
                store_string("xinput_device", globals.xinput_device);
                store_int("xinput_enable", globals.xinput_enable);
                store_int("update_idle", globals.update_idle);
index b17d8cdd94de399f8d588ee68fe95a927bd20f2c..c608ce6344294db5e465c969709464584d3e81bd 100644 (file)
@@ -143,7 +143,10 @@ typedef struct {
        int alsa_buffer_time;
        int alsa_period_time;
        int alsa_samplerate;
-       
+
+       /* PULSE specific options */
+       int pulse_buffer_length;
+
        char lrdf_path[PATH_MAX];
        
        int compress_set_files;
index 2c20d49f0096b07086ad6f9854ecf10ea700a11d..087299245f1a1acaa03172bf634c7510f872ab31 100644 (file)
@@ -138,7 +138,6 @@ create_tx_options (GtkWindow* parent)
   GtkWidget *use_realtime_label;
   GtkWidget *use_realtime;
   GtkWidget *label1;
-  GtkWidget *grid5;
   GtkWidget *label21;
   GtkWidget *label22;
   GtkWidget *label23;
@@ -148,8 +147,6 @@ create_tx_options (GtkWindow* parent)
   GtkWidget *oss_buffers;
   GtkWidget *oss_buffersize;
   GtkWidget *oss_samplerate;
-  GtkWidget *label15;
-  GtkWidget *grid6;
   GtkWidget *label27;
   GtkWidget *label29;
   GtkWidget *label30;
@@ -160,7 +157,7 @@ create_tx_options (GtkWindow* parent)
   GtkWidget *alsa_buffer_time;
   GtkWidget *label39;
   GtkWidget *alsa_free_hwstats;
-  GtkWidget *label16;
+  GtkWidget *pulse_buffer_size;
   GtkWidget *grid1;
   GtkWidget *label6;
   GtkWidget *label7;
@@ -292,7 +289,7 @@ create_tx_options (GtkWindow* parent)
   gtk_radio_button_set_group (GTK_RADIO_BUTTON (jack_driver), oss_driver_group);
   oss_driver_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (jack_driver));
  
-  pulse_driver = gtk_radio_button_new_with_mnemonic (NULL, "PULSE");
+  pulse_driver = gtk_radio_button_new_with_mnemonic (NULL, "PulseAudio");
   gtk_widget_show (pulse_driver);
   gtk_box_pack_start (GTK_BOX (hbox2), pulse_driver, FALSE, FALSE, 0);
   gtk_widget_set_tooltip_text(pulse_driver, "Use the PULSE (PulseAudio) driver for audio output.");
@@ -307,149 +304,120 @@ create_tx_options (GtkWindow* parent)
   use_realtime = gtk_check_button_new_with_mnemonic ("Use realtime scheduling where available");
   gtk_widget_show (use_realtime);
   gtk_grid_attach (GTK_GRID (grid4), use_realtime, 1, 1, 1, 1);
-  
+
   label1 = gtk_label_new ("Audio");
   gtk_widget_show (label1);
   gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label1);
 
-  grid5 = gtk_grid_new ();
-  gtk_widget_show (grid5);
-  gtk_container_add (GTK_CONTAINER (notebook1), grid5);
-  gtk_container_set_border_width (GTK_CONTAINER (grid5), 4);
-  gtk_grid_set_row_spacing (GTK_GRID (grid5), 2);
-  gtk_grid_set_column_spacing (GTK_GRID (grid5), 2);
-
-  label21 = gtk_label_new ("Audio device:");
+  label21 = gtk_label_new ("OSS Audio device:");
   gtk_widget_show (label21);
-  gtk_grid_attach (GTK_GRID (grid5), label21, 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label21, 0, 2, 1, 1);
   gtk_widget_set_halign(label21, GTK_ALIGN_START);
 
-  label22 = gtk_label_new ("No. of buffers:");
+  label22 = gtk_label_new ("OSS No. of buffers:");
   gtk_widget_show (label22);
-  gtk_grid_attach (GTK_GRID (grid5), label22, 0, 1, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label22, 0, 3, 1, 1);
   gtk_widget_set_halign(label22, GTK_ALIGN_START);
 
-  label23 = gtk_label_new ("Buffersize (2^x):");
+  label23 = gtk_label_new ("OSS Buffersize (2^x):");
   gtk_widget_show (label23);
-  gtk_grid_attach (GTK_GRID (grid5), label23, 0, 2, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label23, 0, 4, 1, 1);
   gtk_widget_set_halign(label23, GTK_ALIGN_START);
 
-  label24 = gtk_label_new ("Samplerate (Hz):");
+  label24 = gtk_label_new ("OSS Samplerate (Hz):");
   gtk_widget_show (label24);
-  gtk_grid_attach (GTK_GRID (grid5), label24, 0, 3, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label24, 0, 5, 1, 1);
   gtk_widget_set_halign(label24, GTK_ALIGN_START);
 
   oss_audio_device = gtk_combo_box_text_new ();
-//  g_object_set_data (G_OBJECT (GTK_COMBO_BOX (oss_audio_device)->popwin),
-//                     "tXUiParentKey", oss_audio_device);
   gtk_widget_show (oss_audio_device);
-  gtk_grid_attach (GTK_GRID (grid5), oss_audio_device, 1, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), oss_audio_device, 1, 2, 1, 1);
 
-  //combo_entry2 = GTK_COMBO (oss_audio_device)->entry;
-  //gtk_widget_show (combo_entry2);
   gtk_widget_set_tooltip_text(oss_audio_device, "Select the audiodevice you want terminatorX to send its output to.");
 
   oss_buffers_adj = gtk_adjustment_new (2, 2, 5, 1, 10, 0);
   oss_buffers = gtk_spin_button_new (GTK_ADJUSTMENT (oss_buffers_adj), 1, 0);
   gtk_widget_set_hexpand(oss_buffers, TRUE);
   gtk_widget_show (oss_buffers);
-  gtk_grid_attach (GTK_GRID (grid5), oss_buffers, 1, 1, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), oss_buffers, 1, 3, 1, 1);
   gtk_widget_set_tooltip_text(oss_buffers, "Sets the number of kernel level audio buffers. Actually most systems should run just fine with two.");
 
   oss_buffersize = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (gtk_adjustment_new (9, 8, 16, 1, 1, 1)));
   gtk_widget_show (oss_buffersize);
-  gtk_grid_attach (GTK_GRID (grid5), oss_buffersize, 1, 2, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), oss_buffersize, 1, 4, 1, 1);
   gtk_scale_set_value_pos (GTK_SCALE (oss_buffersize), GTK_POS_LEFT);
   gtk_scale_set_digits (GTK_SCALE (oss_buffersize), 0);
 
   oss_samplerate = gtk_combo_box_text_new ();
-  //g_object_set_data (G_OBJECT (GTK_COMBO (oss_samplerate)->popwin),
-                     //"tXUiParentKey", oss_samplerate);
   gtk_widget_set_hexpand(oss_samplerate, TRUE);
   gtk_widget_show (oss_samplerate);
-  gtk_grid_attach (GTK_GRID (grid5), oss_samplerate, 1, 3, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), oss_samplerate, 1, 5, 1, 1);
 
-//  combo_entry3 = GTK_COMBO (oss_samplerate)->entry;
-//  gtk_widget_show (combo_entry3);
   gtk_widget_set_tooltip_text(oss_samplerate, "Select the sampling to use for this audio device - the higher the better quality. Note that not all sampling rates are supported by all audio devices.");
 
-  label15 = gtk_label_new ("Audio: OSS");
-  gtk_widget_show (label15);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label15);
-
-  grid6 = gtk_grid_new ();
-  gtk_widget_show (grid6);
-  gtk_container_add (GTK_CONTAINER (notebook1), grid6);
-  gtk_container_set_border_width (GTK_CONTAINER (grid6), 4);
-  gtk_grid_set_row_spacing (GTK_GRID (grid6), 2);
-  gtk_grid_set_column_spacing (GTK_GRID (grid6), 2);
-
-  label27 = gtk_label_new ("Audio Device:");
+  label27 = gtk_label_new ("ALSA Audio Device:");
   gtk_widget_show (label27);
-  gtk_grid_attach (GTK_GRID (grid6), label27, 0, 0, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label27, 0, 6, 1, 1);
   gtk_widget_set_halign(label27, GTK_ALIGN_START);
 
-  label29 = gtk_label_new ("Period Time (ms):");
+  label29 = gtk_label_new ("ALSA Period Time (ms):");
   gtk_widget_show (label29);
-  gtk_grid_attach (GTK_GRID (grid6), label29, 0, 2, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label29, 0, 8, 1, 1);
   gtk_widget_set_halign(label29, GTK_ALIGN_START);
 
-  label30 = gtk_label_new ("Samplerate (Hz):");
+  label30 = gtk_label_new ("ALSA Samplerate (Hz):");
   gtk_widget_show (label30);
-  gtk_grid_attach (GTK_GRID (grid6), label30, 0, 3, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label30, 0, 9, 1, 1);
   gtk_widget_set_halign(label30, GTK_ALIGN_START);
 
   alsa_audio_device = gtk_combo_box_text_new ();
-//  g_object_set_data (G_OBJECT (GTK_COMBO (alsa_audio_device)->popwin),
-//                     "tXUiParentKey", alsa_audio_device);
   gtk_widget_set_hexpand(alsa_audio_device, TRUE);
   gtk_widget_show (alsa_audio_device);
-  gtk_grid_attach (GTK_GRID (grid6), alsa_audio_device, 1, 0, 1, 1);
-
-//  combo_entry4 = GTK_COMBO (alsa_audio_device)->entry;
-//  gtk_widget_show (combo_entry4);
+  gtk_grid_attach (GTK_GRID (grid4), alsa_audio_device, 1, 6, 1, 1);
 
   alsa_samplerate = gtk_combo_box_text_new ();
-//  g_object_set_data (G_OBJECT (GTK_COMBO (alsa_samplerate)->popwin),
-//                     "tXUiParentKey", alsa_samplerate);
   gtk_widget_set_hexpand(alsa_samplerate, TRUE);
   gtk_widget_show (alsa_samplerate);
-  gtk_grid_attach (GTK_GRID (grid6), alsa_samplerate, 1, 3, 1, 1);
-
-//  combo_entry5 = GTK_COMBO (alsa_samplerate)->entry;
-//  gtk_widget_show (combo_entry5);
+  gtk_grid_attach (GTK_GRID (grid4), alsa_samplerate, 1, 9, 1, 1);
 
   alsa_period_time = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (gtk_adjustment_new (29, 10, 500, 1, 10, 10)));
   gtk_widget_show (alsa_period_time);
-  gtk_grid_attach (GTK_GRID (grid6), alsa_period_time, 1, 2, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), alsa_period_time, 1, 8, 1, 1);
   gtk_scale_set_value_pos (GTK_SCALE (alsa_period_time), GTK_POS_LEFT);
   gtk_scale_set_digits (GTK_SCALE (alsa_period_time), 0);
 
-  label32 = gtk_label_new ("Buffer Time (ms):");
+  label32 = gtk_label_new ("ALSA Buffer Time (ms):");
   gtk_widget_show (label32);
-  gtk_grid_attach (GTK_GRID (grid6), label32, 0, 1, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label32, 0, 7, 1, 1);
   gtk_widget_set_halign(label32, GTK_ALIGN_START);
 
   alsa_buffer_time = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (gtk_adjustment_new (69, 10, 500, 1, 10, 10)));
   gtk_widget_show (alsa_buffer_time);
-  gtk_grid_attach (GTK_GRID (grid6), alsa_buffer_time, 1, 1, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), alsa_buffer_time, 1, 7, 1, 1);
   gtk_scale_set_value_pos (GTK_SCALE (alsa_buffer_time), GTK_POS_LEFT);
   gtk_scale_set_digits (GTK_SCALE (alsa_buffer_time), 0);
 
-  label39 = gtk_label_new ("Free HWstats:");
+  label39 = gtk_label_new ("ALSA Free HWstats:");
   gtk_widget_show (label39);
-  gtk_grid_attach (GTK_GRID (grid6), label39, 0, 4, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), label39, 0, 10, 1, 1);
   gtk_widget_set_halign(label39, GTK_ALIGN_START);
 
   alsa_free_hwstats = gtk_check_button_new_with_mnemonic ("Enabled");
   gtk_widget_show (alsa_free_hwstats);
-  gtk_grid_attach (GTK_GRID (grid6), alsa_free_hwstats, 1, 4, 1, 1);
+  gtk_grid_attach (GTK_GRID (grid4), alsa_free_hwstats, 1, 10, 1, 1);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (alsa_free_hwstats), TRUE);
 
-  label16 = gtk_label_new ("Audio: ALSA");
-  gtk_widget_show (label16);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 2), label16);
-
+  GtkWidget *pulselabel = gtk_label_new ("PulseAudio Buffer:");
+  gtk_widget_show(pulselabel);
+  gtk_grid_attach (GTK_GRID (grid4), pulselabel, 0, 11, 1, 1);
+  gtk_widget_set_halign(pulselabel, GTK_ALIGN_START);
+
+  pulse_buffer_size = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (gtk_adjustment_new (64, 16, 4096, 1, 10, 10)));
+  gtk_widget_show(pulse_buffer_size);
+  gtk_grid_attach (GTK_GRID (grid4), pulse_buffer_size, 1, 11, 1, 1);
+  gtk_scale_set_value_pos (GTK_SCALE (pulse_buffer_size), GTK_POS_LEFT);
+  gtk_scale_set_digits (GTK_SCALE (pulse_buffer_size), 0);
+            
   grid1 = gtk_grid_new ();
   gtk_widget_show (grid1);
   gtk_container_add (GTK_CONTAINER (notebook1), grid1);
@@ -492,7 +460,7 @@ create_tx_options (GtkWindow* parent)
 
   label4 = gtk_label_new ("Input");
   gtk_widget_show (label4);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 3), label4);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label4);
 
   grid2 = gtk_grid_new ();
   gtk_widget_show (grid2);
@@ -615,7 +583,7 @@ create_tx_options (GtkWindow* parent)
 
   label2 = gtk_label_new ("User Interface");
   gtk_widget_show (label2);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 4), label2);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 2), label2);
 
   grid8 = gtk_grid_new ();
   gtk_widget_show (grid8);
@@ -685,7 +653,7 @@ create_tx_options (GtkWindow* parent)
 
   label41 = gtk_label_new ("Audio Colors");
   gtk_widget_show (label41);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 5), label41);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 3), label41);
 
   grid9 = gtk_grid_new ();
   gtk_widget_show (grid9);
@@ -735,7 +703,7 @@ create_tx_options (GtkWindow* parent)
 
   label52 = gtk_label_new ("VU Colors");
   gtk_widget_show (label52);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 6), label52);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 4), label52);
 
   grid3 = gtk_grid_new ();
   gtk_widget_show (grid3);
@@ -822,7 +790,7 @@ create_tx_options (GtkWindow* parent)
 
   label3 = gtk_label_new ("Misc");
   gtk_widget_show (label3);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 7), label3);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 5), label3);
 
 
   pref_reset = gtk_button_new_with_mnemonic("_Revert");
@@ -905,7 +873,6 @@ create_tx_options (GtkWindow* parent)
   TX_UI_HOOKUP_OBJECT (tx_options, use_realtime_label, "use_realtime_label");
   TX_UI_HOOKUP_OBJECT (tx_options, use_realtime, "use_realtime");
   TX_UI_HOOKUP_OBJECT (tx_options, label1, "label1");
-  TX_UI_HOOKUP_OBJECT (tx_options, grid5, "grid5");
   TX_UI_HOOKUP_OBJECT (tx_options, label21, "label21");
   TX_UI_HOOKUP_OBJECT (tx_options, label22, "label22");
   TX_UI_HOOKUP_OBJECT (tx_options, label23, "label23");
@@ -914,8 +881,6 @@ create_tx_options (GtkWindow* parent)
   TX_UI_HOOKUP_OBJECT (tx_options, oss_buffers, "oss_buffers");
   TX_UI_HOOKUP_OBJECT (tx_options, oss_buffersize, "oss_buffersize");
   TX_UI_HOOKUP_OBJECT (tx_options, oss_samplerate, "oss_samplerate");
-  TX_UI_HOOKUP_OBJECT (tx_options, label15, "label15");
-  TX_UI_HOOKUP_OBJECT (tx_options, grid6, "grid6");
   TX_UI_HOOKUP_OBJECT (tx_options, label27, "label27");
   TX_UI_HOOKUP_OBJECT (tx_options, label29, "label29");
   TX_UI_HOOKUP_OBJECT (tx_options, label30, "label30");
@@ -926,7 +891,7 @@ create_tx_options (GtkWindow* parent)
   TX_UI_HOOKUP_OBJECT (tx_options, alsa_buffer_time, "alsa_buffer_time");
   TX_UI_HOOKUP_OBJECT (tx_options, label39, "label39");
   TX_UI_HOOKUP_OBJECT (tx_options, alsa_free_hwstats, "alsa_free_hwstats");
-  TX_UI_HOOKUP_OBJECT (tx_options, label16, "label16");
+  TX_UI_HOOKUP_OBJECT (tx_options, pulse_buffer_size, "pulse_buffer_size");
   TX_UI_HOOKUP_OBJECT (tx_options, grid1, "grid1");
   TX_UI_HOOKUP_OBJECT (tx_options, label6, "label6");
   TX_UI_HOOKUP_OBJECT (tx_options, label7, "label7");