>From 2f087041d6edbd5c445f3bcfd626733be03fe16e Mon Sep 17 00:00:00 2001 From: Alexander Varnin Date: Mon, 14 Mar 2011 20:42:33 +0300 Subject: [PATCH] Pulseaudio support based on Samo Pogacnik patch. --- configure.ac | 2 +- src/dsp.c | 217 +++++++++++++++++++++++++++++++++++++++++++---------- src/dsp.h | 13 ++- src/globals.h | 5 +- src/gtkoptions.c | 87 ++++++++++++++++++---- src/metro.c | 218 +++++++++++++++++++++++++++++++++++------------------ src/metro.h | 12 ++-- src/options.h | 5 +- src/threadtalk.h | 5 +- 9 files changed, 417 insertions(+), 147 deletions(-) diff --git a/configure.ac b/configure.ac index db9b643..152b4b9 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MALLOC AC_CHECK_FUNCS([floor strdup setlocale strtol]) -PKG_CHECK_MODULES(DEPS, gtk+-2.0 gthread-2.0) +PKG_CHECK_MODULES(DEPS, gtk+-2.0 gthread-2.0 libpulse-simple) # samplerate #AC_ARG_WITH([alsa], diff --git a/src/dsp.c b/src/dsp.c index dde4a87..4bfe36d 100644 --- a/src/dsp.c +++ b/src/dsp.c @@ -54,6 +54,10 @@ #include #endif +#include +#include +#include + /* own headers */ #include "g711.h" #include "globals.h" @@ -110,7 +114,7 @@ static format_t formats[] = { */ dsp_t* dsp_new(comm_t* comm) { dsp_t* result; - + result = (dsp_t*) g_malloc0(sizeof(dsp_t)); result->dspfd = -1; comm_server_register(comm); @@ -136,7 +140,7 @@ void dsp_delete(dsp_t* dsp) { static void encode_sample(short sample, int format, unsigned char* dest) { static int error = 0; - + switch (format) { case AFMT_MU_LAW: *dest = linear2ulaw(sample); @@ -202,7 +206,7 @@ static int limit_int(int x, int limit) { * from_channels: number of channels in * dsp: the dsp_t structure holding rate, channels, samplesize * and format of the initialized dsp - * + * * output: * to: the pointer to the allocated data, ready for playback * return value: number of bytes generated, -1 on error @@ -238,12 +242,12 @@ static int generate_data(short* from, double dummy; double frac = modf(leftbound, &dummy); double weight; - + if (rightbound - leftbound < 1) weight = rightbound - leftbound; else weight = 1.0; - + for (j = 0; j < from_channels; j++) { mixdown += weight * ( (1.0 - frac) * from[from_channels * index + j] + @@ -256,7 +260,7 @@ static int generate_data(short* from, } for (j = 0; j < dsp->channels; j++) { /* for each channel */ double sample; - + if (dsp->channels != from_channels) { sample = mixdown; } else { @@ -269,12 +273,12 @@ static int generate_data(short* from, double dummy; double frac = modf(leftbound, &dummy); double weight; - + if (rightbound - leftbound < 1) weight = rightbound - leftbound; else weight = 1.0; - + sample += weight * ( (1.0 - frac) * from[from_channels * index + j] + frac * from[from_channels * limit_int(index + 1, from_size) + j]); @@ -326,7 +330,7 @@ int generate_sine(int samplefreq, double sinfreq, double sigdur, double fadedur, (-cos((double)(size - i) / (samplefreq * sigdur) * 2 * M_PI) + 1) * 0.5; s[i] = sample * scale; } - + *samples = s; return size; } @@ -361,15 +365,15 @@ int sndfile_get_samples(const char* filename, } if (!sfinfo.seekable) return -1; - + frames = sfinfo.frames; *rate = sfinfo.samplerate; *channels = sfinfo.channels ; *samples = (short*) g_malloc(frames * sizeof(short) * sfinfo.channels); - + sf_readf_short(sf, *samples, frames); - + sf_close(sf); return frames; } @@ -409,7 +413,7 @@ static int init_sample(dsp_t* dsp) { return 0; } - + /* * allocates and initializes dsp->tickdata{0,1,2} * and initializes dsp->td{0,1,2}_size @@ -422,7 +426,7 @@ static int prepare_buffers(dsp_t* dsp) { int i; int attack = 0; - + /* generate single ticks */ if ((dsp->td0_size = generate_data(dsp->frames, dsp->number_of_frames, dsp->rate_in, dsp->channels_in, dsp, &dsp->tickdata0)) == -1) @@ -432,7 +436,7 @@ static int prepare_buffers(dsp_t* dsp) { /* generate first tick */ if ((dsp->td1_size = generate_data(dsp->frames, dsp->number_of_frames, - dsp->rate_in * 2, dsp->channels_in, dsp, &dsp->tickdata1)) == -1) + dsp->rate_in / 2, dsp->channels_in, dsp, &dsp->tickdata1)) == -1) { return -1; } @@ -447,19 +451,19 @@ static int prepare_buffers(dsp_t* dsp) { if (attack < dsp->number_of_frames / 3) { unsigned char* newdata; int offset; - + offset = attack / 2 * dsp->channels * dsp->samplesize / 8; if ((newdata = realloc(dsp->tickdata1, dsp->td1_size + offset))) { int modul = dsp->channels * dsp->samplesize / 8; int i; - + dsp->tickdata1 = newdata; - + for (i = dsp->td1_size - 1; i >= 0; i--) dsp->tickdata1[i + offset] = dsp->tickdata1[i]; for (i = 0; i < offset; i++) dsp->tickdata1[i] = dsp->silence[i % modul]; - + dsp->td1_size += offset; if (debug) @@ -483,6 +487,62 @@ static int prepare_buffers(dsp_t* dsp) { } /* + * Opens pulseaudio connection + * + * returns 0 on success, -1 otherwise + */ +static int pulse_open(dsp_t *dsp) +{ + static int debug_todo = 1; + /* The Sample format to use */ + static const pa_sample_spec pulse_format = { + .format = PA_SAMPLE_S16LE, /* DEFAULT_FORMAT */ + .rate = DEFAULT_RATE, + .channels = DEFAULT_CHANNELS + }; + int error; + unsigned int format_index; + + dsp->pas = NULL; + /* Create a new playback stream */ + if (!(dsp->pas = pa_simple_new(NULL, "GTick metronome", PA_STREAM_PLAYBACK, NULL, "gtick", &pulse_format, NULL, NULL, &error))) { + fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); + return -1; + } + + dsp->format = DEFAULT_FORMAT; + for (format_index = 0; + formats[format_index].format != 0 && + formats[format_index].format != dsp->format; + format_index++); + + if (debug && debug_todo) { + g_print("pulse_open: Used sample format: %s (%s)\n", + formats[format_index].name, formats[format_index].description); + } + + dsp->rate = DEFAULT_RATE; /* requested default */ + if (debug && debug_todo) { + g_print("pulse_open: Sampling rate = %d\n", dsp->rate); + } + + dsp->channels = DEFAULT_CHANNELS; + if (debug && debug_todo) { + g_print("pulse_open: Number of channels = %d\n", dsp->channels); + } + + dsp->samplesize = formats[format_index].samplesize; + dsp->fragmentsize = dsp->rate / 10 /*0.1s fragment time*/ * dsp->channels * dsp->samplesize / 8; + + if (debug && debug_todo) + g_print ("pulse_open: fragment size = %d\n", dsp->fragmentsize); + + dsp->fragment = g_malloc(dsp->fragmentsize); + + return 0; +} + +/* * Opens sound device specified in dsp * * returns 0 on success, -1 otherwise @@ -492,14 +552,16 @@ int dsp_open(dsp_t* dsp) { unsigned int format_index; int requested_format = DEFAULT_FORMAT; audio_buf_info info; - + dsp->fragmentsize = 0x7fff0008; /* at least request fragment size 2^8=256 */ /* = minimum recommended size */ if (debug && debug_todo) g_print ("dsp_open: Initialising %s ...\n", dsp->devicename); /* Initialise sound device */ - if ((dsp->dspfd = open(dsp->devicename, O_WRONLY)) == -1) + if(!strcmp(dsp->soundsystem, "")) + return pulse_open(dsp); + else if ((dsp->dspfd = open(dsp->devicename, O_WRONLY)) == -1) { perror(dsp->devicename); return -1; @@ -514,7 +576,7 @@ int dsp_open(dsp_t* dsp) { if (debug && debug_todo) { unsigned int i; int mask; - + if (ioctl(dsp->dspfd, SNDCTL_DSP_GETFMTS, &mask) == -1) { perror("SNDCTL_DSP_GETFMTS"); } @@ -532,19 +594,19 @@ int dsp_open(dsp_t* dsp) { perror ("SNDCTL_DSP_SETFMT"); return -1; } - + for (format_index = 0; formats[format_index].format != 0 && formats[format_index].format != dsp->format; format_index++); - + if (debug && debug_todo) { g_print("dsp_open: Used sample format: %s (%s)\n", formats[format_index].name, formats[format_index].description); } dsp->samplesize = formats[format_index].samplesize; - + /* Set dsp to default: mono */ dsp->channels = DEFAULT_CHANNELS; if (ioctl (dsp->dspfd, SNDCTL_DSP_CHANNELS, &dsp->channels) == -1) { @@ -554,7 +616,7 @@ int dsp_open(dsp_t* dsp) { if (debug && debug_todo) { g_print("dsp_open: Number of channels = %d\n", dsp->channels); } - + /* Set the DSP rate (in Hz) */ dsp->rate = DEFAULT_RATE; /* requested default */ if (ioctl (dsp->dspfd, SNDCTL_DSP_SPEED, &dsp->rate) == -1) { @@ -585,7 +647,7 @@ int dsp_open(dsp_t* dsp) { if (debug && debug_todo) g_print("dsp_open: Total number of fragments in DSP buffer = %d.\n", dsp->fragstotal); - + debug_todo = 0; return 0; } @@ -595,7 +657,7 @@ int dsp_open(dsp_t* dsp) { */ void dsp_close(dsp_t* dsp) { static int debug_todo = 1; - + if (debug && debug_todo) g_print ("dsp_close: Closing sound device ...\n"); if (dsp->dspfd != -1) { @@ -610,6 +672,9 @@ void dsp_close(dsp_t* dsp) { } } + if (dsp->pas) + pa_simple_free(dsp->pas); + debug_todo = 0; } @@ -621,16 +686,16 @@ void dsp_close(dsp_t* dsp) { int dsp_init(dsp_t* dsp) { short silencelevel = 0; - + if (dsp_open(dsp) == -1) return -1; - + dsp->frames = NULL; dsp->silence = NULL; dsp->tickdata0 = NULL; dsp->tickdata1 = NULL; dsp->tickdata2 = NULL; - + /* silence */ generate_data(&silencelevel, 1, dsp->rate, 1, dsp, &dsp->silence); @@ -658,7 +723,7 @@ void dsp_deinit(dsp_t* dsp) { dsp->running = 0; dsp_close(dsp); - + if (dsp->tickdata0) { g_free(dsp->tickdata0); dsp->tickdata0 = NULL; @@ -686,7 +751,7 @@ void dsp_deinit(dsp_t* dsp) */ static void wrap_position(dsp_t* dsp, int ticklen) { unsigned int* reply; - + if (dsp->tickpos >= ticklen) { dsp->tickpos = 0; dsp->cyclepos++; @@ -701,6 +766,67 @@ static void wrap_position(dsp_t* dsp, int ticklen) { } /* + * Feed pulseaudio stream with next samples + */ +gboolean pulse_feed(dsp_t* dsp) +{ + int ticklen = rint(dsp->rate / dsp->frequency) * + dsp->channels * dsp->samplesize / 8; + unsigned char *the_data; /* pointer to actual buffer */ + int data_size; /* size of actual buffer */ + + int fragments; /* number of fragments yet to write */ + int error; + fragments = 1; + + wrap_position(dsp, ticklen); + + /* write as many fragments as possible */ + while (fragments > 0) { + int i; + + /* generate fragment */ + for (i = 0; i < dsp->fragmentsize; i++) { + int index; + + if (dsp->meter == 1) { /* single ticks */ + the_data = dsp->tickdata0; + data_size = dsp->td0_size; + } else if (dsp->accents[dsp->cyclepos]) { /* accentuate 1st tick */ + the_data = dsp->tickdata1; + data_size = dsp->td1_size; + } else { /* sound of 2nd tick */ + the_data = dsp->tickdata2; + data_size = dsp->td2_size; + } + + if ((index = dsp->tickpos) < data_size) { /* tick! */ + dsp->fragment[i] = the_data[index]; + } else { /* silence (between ticks) */ + dsp->fragment[i] = + dsp->silence[i % (dsp->samplesize / 8 * dsp->channels)]; + } + + dsp->tickpos++; + wrap_position(dsp, ticklen); + } + + if (pa_simple_write(dsp->pas, dsp->fragment, (size_t) dsp->fragmentsize, &error) < 0) { + g_print("pulse_feed: pa_simple_write ERROR: %s\n", pa_strerror(error)); + } + fragments--; + } + +#if 0 + if (pa_simple_drain(dsp->pas, &error) < 0) { + g_print("pulse_feed: pa_simple_drain ERROR: %s\n", pa_strerror(error)); + } +#endif + + return 1; +} + +/* * Feed dsp device with next samples * * used as output start and callback @@ -715,7 +841,7 @@ gboolean dsp_feed(dsp_t* dsp) int fragments; /* number of fragments yet to write */ int limit; /* number of fragments we want to have filled */ - + /* get number of fragments to write to dsp */ if (ioctl(dsp->dspfd, SNDCTL_DSP_GETOSPACE, &info) == -1) { perror("SNDCTL_DSP_GETOSPACE"); @@ -733,11 +859,11 @@ gboolean dsp_feed(dsp_t* dsp) /* write as many fragments as possible */ while (fragments > 0) { int i; - + /* generate fragment */ for (i = 0; i < dsp->fragmentsize; i++) { int index; - + if (dsp->meter == 1) { /* single ticks */ the_data = dsp->tickdata0; data_size = dsp->td0_size; @@ -793,7 +919,7 @@ void dsp_set_volume(dsp_t* dsp, double volume) free(dsp->tickdata0); free(dsp->tickdata1); free(dsp->tickdata2); - + prepare_buffers(dsp); } } @@ -812,12 +938,12 @@ void dsp_main_loop(dsp_t* dsp) { void* message; int get_volume = 0; /* flag */ void* reply = NULL; - + while ((message_type = comm_server_try_get_query(dsp->inter_thread_comm, &message)) != MESSAGE_TYPE_NO_MESSAGE) { - + switch (message_type) { case MESSAGE_TYPE_STOP_SERVER: repeat_flag = 0; @@ -830,6 +956,10 @@ void dsp_main_loop(dsp_t* dsp) { if (dsp->soundname) free(dsp->soundname); dsp->soundname = (char*) message; break; + case MESSAGE_TYPE_SET_SOUNDSYSTEM: + if (dsp->soundsystem) free(dsp->soundsystem); + dsp->soundsystem = (char*) message; + break; case MESSAGE_TYPE_SET_METER: dsp->meter = *((int*) message); free(message); @@ -872,7 +1002,7 @@ void dsp_main_loop(dsp_t* dsp) { if (get_volume) { double volume = dsp_get_volume(dsp); - + reply = (double*) g_malloc0 (sizeof(double)); *((double*)reply) = volume; if (*((double*)reply) != -1) { @@ -884,8 +1014,13 @@ void dsp_main_loop(dsp_t* dsp) { } if (dsp->running) { /* metronome running */ - dsp_feed(dsp); + if (dsp->dspfd != -1) { /* metronome running */ + dsp_feed(dsp); + } else { + pulse_feed(dsp); + } } + nanosleep(&requested, &remaining); } } diff --git a/src/dsp.h b/src/dsp.h index 7567896..e619382 100644 --- a/src/dsp.h +++ b/src/dsp.h @@ -1,8 +1,8 @@ -/* +/* * DSP interface * * This file is part of GTick - * + * * * Copyright (c) 1999, Alex Roberts * Copyright (c) 2003, 2004, 2005, 2006 Roland Stigge @@ -28,12 +28,17 @@ /* GTK headers */ #include +#include + /* own headers */ #include "threadtalk.h" typedef struct dsp_t { char* devicename; char* soundname; + char* soundsystem; + + pa_simple *pas; /* pa simple playback stream */ int dspfd; /* file descriptor */ int fragmentsize; /* fragment size */ @@ -47,7 +52,7 @@ typedef struct dsp_t { int channels_in; /* number of channels of input data in Hz */ unsigned char* fragment; - + unsigned char* tickdata0; /* raw dsp sample bytes for single tick */ int td0_size; /* length in bytes */ unsigned char* tickdata1; /* raw dsp sample bytes for first tick */ @@ -69,7 +74,7 @@ typedef struct dsp_t { int running; /* on/off flag */ double volume; /* 0.0 ... 1.0 */ - + int sync_flag; comm_t* inter_thread_comm; diff --git a/src/globals.h b/src/globals.h index 1c56b80..836ad0e 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,8 +1,8 @@ -/* +/* * Global definitions * * This file is part of GTick - * + * * * Copyright (c) 1999, Alex Roberts * Copyright (c) 2003, 2004, 2005, 2006 Roland Stigge @@ -43,6 +43,7 @@ #define VOLUME_MIN 0 #define VOLUME_MAX 100 #define MAX_METER 100 +#define DEFAULT_SOUND_SYSTEM "" #define DEFAULT_SOUND_DEVICE_FILENAME "/dev/dsp" #define DEFAULT_SAMPLE_FILENAME "" #define DEFAULT_SPEED 75 diff --git a/src/gtkoptions.c b/src/gtkoptions.c index ad0d4c4..f46104f 100644 --- a/src/gtkoptions.c +++ b/src/gtkoptions.c @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU General Public License * along with GTick; if not, see . - * + * */ #include @@ -84,6 +84,34 @@ sound_button_toggled(GtkToggleButton *togglebutton, options_t* options) } static void +soundsystem_button_toggled(GtkToggleButton *togglebutton, options_t* options) +{ + GSList* group; + GtkWidget* radio_button; + const char* soundsystem; + + /* + * Sample filename setup + */ + group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(togglebutton)); + while (group && + !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data))) + { + group = group->next; + } + radio_button = GTK_WIDGET(group->data); + soundsystem = g_object_get_data(G_OBJECT(radio_button), "choice"); + if (strcmp(soundsystem, "")!=0 && strcmp(soundsystem, "")!=0) + { + fprintf(stderr, "Warning: Unhandled samplename case: \"%s\".\n", + (char*) g_object_get_data(G_OBJECT(radio_button), "choice")); + soundsystem = ""; + } + + option_set(options->option_list, "SoundSystem", soundsystem); +} + +static void sound_device_entry_changed(GtkEntry *entry, options_t* options) { const char* sounddevice; @@ -185,7 +213,7 @@ static void choose_cb(GtkWidget *button) { GtkWidget* file_selection = gtk_file_selection_new(_("Please choose a sound file.")); gtk_window_set_modal(GTK_WINDOW(file_selection), TRUE); - + g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_selection)->ok_button), "sample_name_entry", g_object_get_data(G_OBJECT(button), "sample_name_entry")); @@ -196,19 +224,19 @@ static void choose_cb(GtkWidget *button) { "clicked", G_CALLBACK(choose_cb_store), NULL); - + /* destroy file selection dialog if ok or cancel button has been clicked */ g_signal_connect_swapped( GTK_OBJECT(GTK_FILE_SELECTION(file_selection)->ok_button), "clicked", - G_CALLBACK(gtk_widget_destroy), - (gpointer) file_selection); + G_CALLBACK(gtk_widget_destroy), + (gpointer) file_selection); g_signal_connect_swapped( GTK_OBJECT(GTK_FILE_SELECTION(file_selection)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), - (gpointer) file_selection); - + (gpointer) file_selection); + gtk_widget_show(file_selection); } #endif /* WITH_SNDFILE */ @@ -261,6 +289,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { GtkWidget* alignment; GtkSizeGroup* sizegroup; const char* samplename; + const char* soundsystem; if (!(samplename = option_get(options->option_list, "SampleFilename", 0, NULL))) @@ -272,14 +301,14 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(window)->vbox), 12); - + vbox = gtk_vbox_new(FALSE, 18); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 12); gtk_widget_show(vbox); sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - + /* * Sound effect setting */ @@ -366,7 +395,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { G_CALLBACK(sound_button_toggled), options); g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(sample_name_entry_changed), options); - + /* save entry at button to retrieve value in file selection dialog */ g_object_set_data(G_OBJECT(button), "sample_name_entry", entry); @@ -374,11 +403,11 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { G_CALLBACK(choose_cb), options); #endif /* WITH_SNDFILE */ - + /* * Sound device setting */ - frame = gtk_frame_new(_("Sound Device")); + frame = gtk_frame_new(_("Sound System")); label = gtk_frame_get_label_widget(GTK_FRAME(frame)); gtk_label_attr_bold(GTK_LABEL(label)); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE); @@ -394,6 +423,34 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { gtk_container_add(GTK_CONTAINER(alignment), devicevbox); gtk_widget_show(devicevbox); + if(! (soundsystem = option_get(options->option_list, + "SoundSystem", 0, NULL)) ) + soundsystem = ""; + + radiobutton = gtk_radio_button_new_with_label(NULL, _("Pulseaudio")); + g_object_set_data(G_OBJECT(radiobutton), "choice", ""); + if (!strcmp(soundsystem, "")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobutton), TRUE); + gtk_box_pack_start(GTK_BOX(devicevbox), radiobutton, FALSE, TRUE, 0); + gtk_widget_show(radiobutton); + + /* Instant apply */ + g_signal_connect(G_OBJECT(radiobutton), "toggled", + G_CALLBACK(soundsystem_button_toggled), options); + + radiobutton = + gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radiobutton), + _("OSS")); + g_object_set_data(G_OBJECT(radiobutton), "choice", ""); + if (!strcmp(soundsystem, "")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobutton), TRUE); + gtk_box_pack_start(GTK_BOX(devicevbox), radiobutton, FALSE, TRUE, 0); + gtk_widget_show(radiobutton); + + /* Instant apply */ + g_signal_connect(G_OBJECT(radiobutton), "toggled", + G_CALLBACK(soundsystem_button_toggled), options); + hbox = gtk_hbox_new(FALSE, 12); gtk_box_pack_start(GTK_BOX(devicevbox), hbox, FALSE, TRUE, 0); gtk_widget_show(hbox); @@ -452,7 +509,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { /* Instant apply */ g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(cmd_start_entry_changed), options); - + label = gtk_label_new(_("Execute on stop:")); gtk_size_group_add_widget(sizegroup, label); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, @@ -508,7 +565,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { gtk_widget_show(spinbutton); g_signal_connect(G_OBJECT(spinbutton), "value-changed", G_CALLBACK(min_bpm_value_changed), options); - + label = gtk_label_new(_("Maximum BPM:")); gtk_size_group_add_widget(sizegroup, label); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, @@ -525,7 +582,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) { gtk_widget_show(spinbutton); g_signal_connect(G_OBJECT(spinbutton), "value-changed", G_CALLBACK(max_bpm_value_changed), options); - + g_signal_connect(G_OBJECT(window), "response", G_CALLBACK(response_cb), options); return window; diff --git a/src/metro.c b/src/metro.c index 8429026..2611792 100644 --- a/src/metro.c +++ b/src/metro.c @@ -1,8 +1,8 @@ -/* +/* * Metronome session * * This file is part of GTick - * + * * * Copyright (c) 1999, Alex Roberts * Copyright (c) 2005 Marco Tulio Gontijo e Silva @@ -22,7 +22,7 @@ * along with GTick; if not, see . * */ - + #include /* GNU headers */ @@ -168,7 +168,7 @@ static guint get_name_index_from_speed(int speed) { while (result < sizeof(speed_names) / sizeof(speed_name_t) && (speed_names[result].min_bpm > speed || speed_names[result].max_bpm <= speed)) { - + result ++; } @@ -204,10 +204,10 @@ static void tap_cb(metro_t* metro) assert(metro != NULL); gettimeofday(&thistime, NULL); - + timeval_subtract(&diffval, &thistime, &metro->lasttap); timediff = diffval.tv_sec + (double)diffval.tv_usec / 1000000.0; - + if (timediff < 10.0) { gtk_adjustment_set_value(GTK_ADJUSTMENT(metro->speed_adjustment), round(60.0 / timediff)); @@ -263,14 +263,14 @@ static void set_speed_cb(metro_t *metro) double* frequency = (double*) g_malloc(sizeof(double)); gint old_index; gint new_index; - + *frequency = GTK_ADJUSTMENT(metro->speed_adjustment)->value / 60.0; if (debug) g_print ("set_speed_cb(): rate=%f bpm\n", *frequency * 60.0); old_index = (gint) gtk_combo_box_get_active(GTK_COMBO_BOX(metro->speed_name)); new_index = get_name_index_from_speed((int)round(*frequency * 60.0)); - + if (new_index != old_index) gtk_combo_box_set_active(GTK_COMBO_BOX(metro->speed_name), new_index); @@ -310,7 +310,7 @@ static void accents_changed_cb(metro_t* metro) { message[i] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( metro->accentbuttons[i])); } - + comm_client_query(metro->inter_thread_comm, MESSAGE_TYPE_SET_ACCENTS, message); } @@ -319,9 +319,9 @@ static void accents_changed_cb(metro_t* metro) { * Change state */ static void set_state(metro_t* metro, int state) { - + if (state != metro->state) { - + if (metro->state == STATE_RUNNING && state == STATE_IDLE) { comm_client_query(metro->inter_thread_comm, MESSAGE_TYPE_STOP_METRONOME, NULL); @@ -334,7 +334,7 @@ static void set_state(metro_t* metro, int state) { } else { fprintf(stderr, "Warning: Unhandled state change.\n"); } - + gtk_statusbar_pop(GTK_STATUSBAR(metro->statusbar), metro->status_context); gtk_statusbar_push(GTK_STATUSBAR(metro->statusbar), @@ -345,7 +345,7 @@ static void set_state(metro_t* metro, int state) { /* Set Start/Stop label */ g_object_set(metro->start_action, "label", _(state_data[state].toggle_label), NULL); - + metro->state = state; } } @@ -368,7 +368,7 @@ static gint handle_comm(metro_t* metro) { break; case MESSAGE_TYPE_RESPONSE_START_ERROR: gtk_widget_show(metro->start_error); - + set_state(metro, STATE_IDLE); break; default: @@ -407,7 +407,7 @@ static void toggle_accenttable_cb(GtkToggleAction *action _U_, metro_t *metro) { */ static void metro_toggle_cb(GtkToggleAction *action _U_, metro_t *metro) { int new_state; - + if (metro->state == STATE_IDLE) { new_state = STATE_RUNNING; } else { @@ -568,6 +568,67 @@ static int set_sound_device_name(metro_t* metro, return 0; } + +/* + * option system callback for initializing sound system with default value + * returns 0 on success, -1 otherwise + */ + +static int new_sound_system(metro_t* metro) { + metro->options->sound_device_name = strdup(DEFAULT_SOUND_SYSTEM); + comm_client_query(metro->inter_thread_comm, + MESSAGE_TYPE_SET_SOUNDSYSTEM, + strdup(DEFAULT_SOUND_SYSTEM)); + if (metro->options->soundsystem) + return 0; + else + return -1; +} + +/* + * option system callback for destroying sound system + */ +static void delete_sound_system(metro_t* metro) { + if (metro->options->soundsystem) + free(metro->options->soundsystem); +} + +/* + * option system callback for choosing the sound system + * + * returns 0 on success, -1 otherwise + */ +static int set_sound_system(metro_t* metro, + const char* option_name _U_, + const char* sound_system) +{ + if (metro->options->soundsystem) + free(metro->options->soundsystem); + else + fprintf(stderr, + "free() error: metro->options->sound_device_name not allocated.\n"); + metro->options->soundsystem = strdup(sound_system); + comm_client_query(metro->inter_thread_comm, + MESSAGE_TYPE_SET_SOUNDSYSTEM, strdup(sound_system)); + if (metro->state == STATE_RUNNING) { + comm_client_query(metro->inter_thread_comm, + MESSAGE_TYPE_STOP_METRONOME, NULL); + comm_client_query(metro->inter_thread_comm, + MESSAGE_TYPE_START_METRONOME, NULL); + } + + return 0; +} + +/* + * option system callback for spotting the sound device name + */ +static const char* get_sound_system(metro_t* metro, + int n _U_, char** option_name _U_) +{ + return metro->options->soundsystem; +} + /* * option system callback for spotting the sound device name */ @@ -590,7 +651,7 @@ static int set_min_bpm(metro_t* metro, if (!metro || !metro->speed_adjustment || !min_bpm) return -1; - + new_min_bpm = abs(strtol(min_bpm, NULL, 0)); if (new_min_bpm >= MIN_BPM && new_min_bpm <= MAX_BPM) { if (new_min_bpm > GTK_ADJUSTMENT(metro->speed_adjustment)->upper) @@ -650,7 +711,7 @@ static int set_max_bpm(metro_t* metro, if (!metro || !metro->speed_adjustment || !max_bpm) return -1; - + new_max_bpm = abs(strtol(max_bpm, NULL, 0)); if (new_max_bpm >= MIN_BPM && new_max_bpm <= MAX_BPM) { if (new_max_bpm < GTK_ADJUSTMENT(metro->speed_adjustment)->lower) @@ -658,7 +719,7 @@ static int set_max_bpm(metro_t* metro, GTK_ADJUSTMENT(metro->speed_adjustment)->upper = (gdouble) new_max_bpm; gtk_adjustment_changed(GTK_ADJUSTMENT(metro->speed_adjustment)); } - + return 0; } @@ -706,7 +767,7 @@ int set_speed(metro_t* metro, const char* option_name _U_, const char* speed) { if (!metro || !metro->speed_adjustment || !speed) return -1; - + gtk_adjustment_set_value(GTK_ADJUSTMENT(metro->speed_adjustment), (gdouble) strtol(speed, NULL, 0)); @@ -757,7 +818,7 @@ int set_volume(metro_t* metro, { if (!metro || !metro->volume_adjustment || !volume) return -1; - + gtk_adjustment_set_value(GTK_ADJUSTMENT(metro->volume_adjustment), g_ascii_strtod(volume, NULL)); @@ -807,7 +868,7 @@ static void set_meter_int(metro_t* metro, int meter) { int* message; int i; - + switch (meter) { case 1: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(metro->meter_button_1), @@ -845,7 +906,7 @@ static void set_meter_int(metro_t* metro, int meter) } } gtk_window_resize(GTK_WINDOW(metro->window), 1, 1); - + if (debug) g_print("new meter: %d\n", meter); @@ -873,14 +934,14 @@ static void set_meter_cb(GtkWidget* widget, metro_t *metro) { int set_meter(metro_t* metro, const char* option_name _U_, const char* meter) { int n; - + if (!metro || !meter) return -1; n = (int) strtol(meter, NULL, 0); set_meter_int(metro, n); - + return 0; } @@ -895,12 +956,12 @@ const char* get_meter(metro_t* metro, int n _U_, char** option_name _U_) if (result) free(result); - + if (metro == NULL) return NULL; result = g_strdup_printf("%d", gui_get_meter(metro)); - + return result; } @@ -914,7 +975,7 @@ static int new_meter(metro_t* metro) { s = g_strdup_printf("%d", DEFAULT_METER); set_meter(metro, NULL, s); free(s); - + meter = (int*) g_malloc (sizeof(int)); *meter = DEFAULT_METER; comm_client_query(metro->inter_thread_comm, MESSAGE_TYPE_SET_METER, meter); @@ -1130,7 +1191,7 @@ const char* get_accents(metro_t* metro, int n _U_, char** option_name _U_) { static char result[MAX_METER + 1]; - + if (metro) { int i; @@ -1140,9 +1201,9 @@ const char* get_accents(metro_t* metro, metro->accentbuttons[i])) ? '1' : '0'; } - + result[MAX_METER] = '\0'; - + i = MAX_METER - 1; while (i > 0 && result[i] == '0') { result[i] = '\0'; @@ -1157,7 +1218,7 @@ const char* get_accents(metro_t* metro, /* * returns the (main) menu bar for the specified window - * + * * further initialization done in metro: * - menu-prepared accel_group added to window * - visualtick_menu_item @@ -1413,10 +1474,10 @@ metro_t* metro_new(void) { if (debug) printf("Creating metro object at %p.\n", metro); - + metro->options = options_new(); metro->state = STATE_IDLE; /* set default */ - + metro->inter_thread_comm = comm_new(); metro->audio_thread = g_thread_create_full((GThreadFunc) audio_loop, @@ -1427,7 +1488,7 @@ metro_t* metro_new(void) { G_THREAD_PRIORITY_NORMAL, /* G_THREAD_PRIORITY_URGENT would be highest priority */ NULL /* no GError reporting */); - + option_register(&metro->options->option_list, "SampleFilename", (option_new_t) new_sample, @@ -1437,6 +1498,15 @@ metro_t* metro_new(void) { (option_get_t) get_sample, (void*) metro); option_register(&metro->options->option_list, + "SoundSystem", + (option_new_t) new_sound_system, + (option_delete_t) delete_sound_system, + (option_set_t) set_sound_system, + (option_get_n_t) option_return_one, + (option_get_t) get_sound_system, + (void*) metro); + + option_register(&metro->options->option_list, "SoundDevice", (option_new_t) new_sound_device_name, (option_delete_t) delete_sound_device_name, @@ -1461,7 +1531,7 @@ metro_t* metro_new(void) { (option_get_n_t) option_return_one, (option_get_t) get_command_on_stop, (void*) metro->options); - + metro->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(metro->window), "destroy", @@ -1494,7 +1564,7 @@ metro_t* metro_new(void) { metro->status_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(metro->statusbar), "status"); gtk_statusbar_push(GTK_STATUSBAR(metro->statusbar), - metro->status_context, + metro->status_context, _(state_data[metro->state].state)); gtk_box_pack_end(GTK_BOX(windowvbox), metro->statusbar, FALSE, TRUE, 0); gtk_widget_show(metro->statusbar); @@ -1526,7 +1596,7 @@ metro_t* metro_new(void) { gtk_table_set_row_spacings(GTK_TABLE(table), 6); gtk_table_set_col_spacings(GTK_TABLE(table), 12); gtk_widget_show(table); - + metro->speed_name = gtk_combo_box_new_text(); for (i = 0; i < sizeof(speed_names) / sizeof(speed_name_t); i++) { gchar tmpbuf[1000]; @@ -1544,7 +1614,7 @@ metro_t* metro_new(void) { "changed", G_CALLBACK(set_speed_name_cb), metro); - + /* TRANSLATORS: This button needs to be clicked ("tapped") at least twice for specifying a tempo */ button = gtk_button_new_with_label(_("Tap")); @@ -1611,7 +1681,7 @@ metro_t* metro_new(void) { (option_get_n_t) option_return_one, (option_get_t) get_speed, (void*) metro); - + option_register(&metro->options->option_list, "Volume", (option_new_t) new_volume, @@ -1620,14 +1690,14 @@ metro_t* metro_new(void) { (option_get_n_t) option_return_one, (option_get_t) get_volume, (void*) metro); - + label = gtk_label_new (_("Volume:")); gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_widget_show (label); - + metro->volume_adjustment = gtk_adjustment_new(DEFAULT_VOLUME, VOLUME_MIN, VOLUME_MAX, 5.0, 25.0, 0.0); g_signal_connect_swapped(G_OBJECT(metro->volume_adjustment), @@ -1635,7 +1705,7 @@ metro_t* metro_new(void) { G_CALLBACK(set_volume_cb), metro); set_volume_cb(metro); - + scale = gtk_hscale_new (GTK_ADJUSTMENT(metro->volume_adjustment)); gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_CONTINUOUS); gtk_scale_set_digits (GTK_SCALE (scale), 0); @@ -1644,7 +1714,7 @@ metro_t* metro_new(void) { 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show (scale); - + spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(metro->volume_adjustment), 1.0, /* Step */ 1 /* number of decimals */); @@ -1652,9 +1722,9 @@ metro_t* metro_new(void) { 2, 3, 2, 3, GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show(spinbutton); - + /* Timing UI Code */ - + beatframe = gtk_frame_new (_("Meter")); gtk_frame_set_shadow_type(GTK_FRAME(beatframe), GTK_SHADOW_NONE); label = gtk_frame_get_label_widget(GTK_FRAME(beatframe)); @@ -1687,7 +1757,7 @@ metro_t* metro_new(void) { "toggled", G_CALLBACK(set_meter_cb), metro); - + metro->meter_button_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(metro->meter_button_1), /* TRANSLATORS: duple meter */ @@ -1698,7 +1768,7 @@ metro_t* metro_new(void) { "toggled", G_CALLBACK(set_meter_cb), metro); - + metro->meter_button_3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(metro->meter_button_2), /* TRANSLATORS: triple meter */ @@ -1732,7 +1802,7 @@ metro_t* metro_new(void) { "toggled", G_CALLBACK(set_meter_cb), metro); - + adjustment = gtk_adjustment_new(5, 5, MAX_METER, 1, 4, 0); metro->meter_spin_button = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1, 0); @@ -1769,7 +1839,7 @@ metro_t* metro_new(void) { for (i = 0; i < (MAX_METER - 1) / 10 + 1; i++) { for (j = 0; j < 10; j++) { char* temp; - + temp = g_strdup_printf("%d", i * 10 + j + 1); button = gtk_check_button_new_with_label(temp); free(temp); @@ -1779,7 +1849,7 @@ metro_t* metro_new(void) { g_signal_connect_swapped(button, "toggled", G_CALLBACK(accents_changed_cb), metro); - + metro->accentbuttons[i * 10 + j] = button; } } @@ -1809,7 +1879,7 @@ metro_t* metro_new(void) { (option_get_n_t) option_return_one, (option_get_t) get_accents, (void*) metro); - + /* Profiles */ metro->profileframe = profiles_new(metro); gtk_box_pack_start(GTK_BOX(vbox), metro->profileframe, FALSE, TRUE, 0); @@ -1823,7 +1893,7 @@ metro_t* metro_new(void) { togglebutton = gtk_button_new(); g_signal_connect(G_OBJECT(togglebutton), "clicked", G_CALLBACK(metro_toggle_cb), metro); - + gtk_box_pack_start(GTK_BOX(hbox), togglebutton, TRUE, FALSE, 0); GTK_WIDGET_SET_FLAGS (togglebutton, GTK_CAN_DEFAULT); gtk_widget_grab_default (togglebutton); @@ -1851,43 +1921,43 @@ metro_t* metro_new(void) { gtk_accel_group_connect(metro->accel_group, '+', GDK_CONTROL_MASK, 0, g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_plus), metro, NULL)); gtk_accel_group_connect(metro->accel_group, '-', GDK_CONTROL_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minus),metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minus),metro, NULL)); + gtk_accel_group_connect(metro->accel_group, 'x', GDK_MOD1_MASK, 0, g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_plusTwo), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'z', GDK_MOD1_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTwo),metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTwo),metro, NULL)); + gtk_accel_group_connect(metro->accel_group, 'd', GDK_CONTROL_MASK, 0, g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_double), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'h', GDK_CONTROL_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL)); + gtk_accel_group_connect(metro->accel_group, 'w', GDK_MOD1_MASK, 0, g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_double), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'q', GDK_MOD1_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL)); + gtk_accel_group_connect(metro->accel_group, 's', GDK_MOD1_MASK, 0, g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_plusTen), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'a', GDK_MOD1_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTen), metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTen), metro, NULL)); + gtk_accel_group_connect(metro->accel_group, 'x', GDK_SHIFT_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTwo), metro, NULL)); + g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTwo), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'z', GDK_SHIFT_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTwo),metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTwo),metro, NULL)); + gtk_accel_group_connect(metro->accel_group, 's', GDK_SHIFT_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTen), metro, NULL)); + g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTen), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'a', GDK_SHIFT_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTen),metro, NULL)); + g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTen),metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'w', GDK_SHIFT_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_double), metro, NULL)); + g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_double), metro, NULL)); gtk_accel_group_connect(metro->accel_group, 'q', GDK_SHIFT_MASK, 0, - g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_half),metro, NULL)); - + g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_half),metro, NULL)); + option_register(&metro->options->option_list, "VisualTick", (option_new_t) new_visualtick, @@ -1896,19 +1966,19 @@ metro_t* metro_new(void) { (option_get_n_t) option_return_one, (option_get_t) get_visualtick, (void*) metro); - + /* read rc file */ option_restore_all(metro->options->option_list); /* set up additional handlers */ gtk_timeout_add(TIMER_DELAY, (GtkFunction) timeout_callback, metro); gtk_timeout_add(VISUAL_DELAY * 1000, (GtkFunction) handle_comm, metro); - + signal(SIGINT, &terminate_signal_callback); signal(SIGTERM, &terminate_signal_callback); /* additional helper widgets: */ - + /* Start error message */ metro->start_error = gtk_message_dialog_new(GTK_WINDOW(metro->window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1922,7 +1992,7 @@ metro_t* metro_new(void) { "response", G_CALLBACK(gtk_widget_hide), G_OBJECT(metro->start_error)); - + gtk_widget_show (metro->window); return metro; diff --git a/src/metro.h b/src/metro.h index 1358f41..fd21309 100644 --- a/src/metro.h +++ b/src/metro.h @@ -1,8 +1,8 @@ -/* +/* * Metronome session interface * * This file is part of GTick - * + * * * Copyright (c) 1999, Alex Roberts * Copyright (c) 2005 Marco Tulio Gontijo e Silva @@ -22,7 +22,7 @@ * along with GTick; if not, see . * */ - + #ifndef METRO_H #define METRO_H @@ -43,7 +43,7 @@ typedef enum state_t { STATE_IDLE, /* Metronome off */ STATE_RUNNING, /* Metronome on */ - + STATE_NUMBER } state_t; @@ -80,7 +80,7 @@ typedef struct metro_t { GtkWidget* meter_button_4; GtkWidget* meter_button_more; GtkWidget* meter_spin_button; - + GtkWidget* togglebutton_label; GtkWidget* speed_name; /* ComboBox */ @@ -93,7 +93,7 @@ typedef struct metro_t { GtkWidget* accentframe; /* show / hide */ GtkWidget** accentbuttons; /* to switch on / off */ GtkToggleAction* accenttable_action; - + GtkWidget* profileframe; /* show / hide */ GtkToggleAction* profiles_action; GtkTreeView* profiles_tree; diff --git a/src/options.h b/src/options.h index e1285a2..d70e6d1 100644 --- a/src/options.h +++ b/src/options.h @@ -1,8 +1,8 @@ -/* +/* * Metronome options object interface * * This file is part of GTick - * + * * * Copyright (c) 1999, Alex Roberts * Copyright (c) 2003, 2004, 2005, 2006 Roland Stigge @@ -34,6 +34,7 @@ typedef struct options_t { option_list_t* option_list; /* list of available rc options */ char* sample_name; + char* soundsystem; char* sound_device_name; char* command_on_start; char* command_on_stop; diff --git a/src/threadtalk.h b/src/threadtalk.h index 7f30fa0..e99cef7 100644 --- a/src/threadtalk.h +++ b/src/threadtalk.h @@ -38,10 +38,11 @@ typedef struct comm_t { */ enum message_type_t { MESSAGE_TYPE_NO_MESSAGE, - + MESSAGE_TYPE_STOP_SERVER, MESSAGE_TYPE_SET_DEVICE, /* param: char*: device */ MESSAGE_TYPE_SET_SOUND, /* param: char* sound name or filename */ + MESSAGE_TYPE_SET_SOUNDSYSTEM, MESSAGE_TYPE_SET_METER, /* param: int*: meter */ MESSAGE_TYPE_SET_ACCENTS, /* param: char*: accent list: {'0','1'}* */ MESSAGE_TYPE_SET_FREQUENCY, /* param: double*: frequency */ @@ -51,7 +52,7 @@ enum message_type_t { MESSAGE_TYPE_STOP_SYNC, MESSAGE_TYPE_SET_VOLUME, /* param: double*: volume 0.0 ... 1.0 */ MESSAGE_TYPE_GET_VOLUME, /* response needed: double*: volume 0.0...1.0 */ - + MESSAGE_TYPE_RESPONSE_VOLUME, /* param: int*: volume 0 ... 100 */ MESSAGE_TYPE_RESPONSE_SYNC, /* param: unsigned int*: position in meter*/ MESSAGE_TYPE_RESPONSE_START_ERROR -- 1.7.1