Hello! I've continued Samo Pogacnik work for pulseaudio support (patch from there: http://lists.gnu.org/archive/html/gtick-devel/2010-01/msg00000.html).
I've added radiobox to select between Pulseaudio and OSS and added corresponding setting to options file. Now gtick can work with pulseaudio or OSS on user selection. There could be some problems, when you restart metronome after changing sound system, but it is not critical, because restarting gtick makes everything alright. Patch attached. Alexander.
>From 2f087041d6edbd5c445f3bcfd626733be03fe16e Mon Sep 17 00:00:00 2001 From: Alexander Varnin <[email protected]> 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 <dmalloc.h> #endif +#include <pulse/simple.h> +#include <pulse/error.h> +#include <pulse/gccmacro.h> + /* 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 <from> * 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, "<pulseaudio>")) + 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 <[email protected]> @@ -28,12 +28,17 @@ /* GTK headers */ #include <gtk/gtk.h> +#include <pulse/simple.h> + /* 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 <[email protected]> @@ -43,6 +43,7 @@ #define VOLUME_MIN 0 #define VOLUME_MAX 100 #define MAX_METER 100 +#define DEFAULT_SOUND_SYSTEM "<pulseaudio>" #define DEFAULT_SOUND_DEVICE_FILENAME "/dev/dsp" #define DEFAULT_SAMPLE_FILENAME "<default>" #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 <http://www.gnu.org/licenses/>. - * + * */ #include <config.h> @@ -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, "<pulseaudio>")!=0 && strcmp(soundsystem, "<oss>")!=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 = "<pulseaudio>"; + + radiobutton = gtk_radio_button_new_with_label(NULL, _("Pulseaudio")); + g_object_set_data(G_OBJECT(radiobutton), "choice", "<pulseaudio>"); + if (!strcmp(soundsystem, "<pulseaudio>")) + 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", "<oss>"); + if (!strcmp(soundsystem, "<oss>")) + 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 <[email protected]> @@ -22,7 +22,7 @@ * along with GTick; if not, see <http://www.gnu.org/licenses/>. * */ - + #include <config.h> /* 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 <[email protected]> @@ -22,7 +22,7 @@ * along with GTick; if not, see <http://www.gnu.org/licenses/>. * */ - + #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 <[email protected]> @@ -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
_______________________________________________ Gtick-devel mailing list [email protected] http://lists.gnu.org/mailman/listinfo/gtick-devel
