diff --git a/drmr.c b/drmr.c index 0598ec6..621e3bf 100644 --- a/drmr.c +++ b/drmr.c @@ -24,22 +24,34 @@ static void* load_thread(void* arg) { DrMr* drmr = (DrMr*)arg; - - pthread_mutex_lock(&drmr->load_mutex); + drmr_sample *loaded_samples,*old_samples; + int loaded_count, old_scount; for(;;) { + pthread_mutex_lock(&drmr->load_mutex); pthread_cond_wait(&drmr->load_cond, &drmr->load_mutex); + pthread_mutex_unlock(&drmr->load_mutex); int request = (int)floorf(*(drmr->kitReq)); - if (request >= drmr->kits->num_kits) { - int os = drmr->num_samples; + if (request == drmr->curKit) continue; + old_samples = drmr->samples; + old_scount = drmr->num_samples; + if (request < 0 || request >= drmr->kits->num_kits) { + pthread_mutex_lock(&drmr->load_mutex); drmr->num_samples = 0; - if (os > 0) free_samples(drmr->samples,os); drmr->samples = NULL; - } else - load_hydrogen_kit(drmr,drmr->kits->kits[request].path); + pthread_mutex_unlock(&drmr->load_mutex); + } else { + printf("loading kit: %i\n",request); + loaded_samples = load_hydrogen_kit(drmr->kits->kits[request].path,drmr->rate,&loaded_count); + // just lock for the critical moment when we swap in the new kit + pthread_mutex_lock(&drmr->load_mutex); + drmr->samples = loaded_samples; + drmr->num_samples = loaded_count; + pthread_mutex_unlock(&drmr->load_mutex); + } + if (old_scount > 0) free_samples(old_samples,old_scount); drmr->curKit = request; } - pthread_mutex_unlock(&drmr->load_mutex); return 0; } @@ -51,7 +63,9 @@ instantiate(const LV2_Descriptor* descriptor, int i; DrMr* drmr = malloc(sizeof(DrMr)); drmr->map = NULL; + drmr->samples = NULL; drmr->num_samples = 0; + drmr->curKit = -1; drmr->rate = rate; if (pthread_mutex_init(&drmr->load_mutex, 0)) { @@ -64,11 +78,6 @@ instantiate(const LV2_Descriptor* descriptor, free(drmr); return 0; } - if (pthread_create(&drmr->load_thread, 0, load_thread, drmr)) { - fprintf(stderr, "Could not initialize loading thread.\n"); - free(drmr); - return 0; - } // Map midi uri while(*features) { @@ -93,9 +102,12 @@ instantiate(const LV2_Descriptor* descriptor, free(drmr); return 0; } - drmr->samples = NULL; // prevent attempted freeing in load - load_hydrogen_kit(drmr,drmr->kits->kits->path); - drmr->curKit = 0; + + if (pthread_create(&drmr->load_thread, 0, load_thread, drmr)) { + fprintf(stderr, "Could not initialize loading thread.\n"); + free(drmr); + return 0; + } drmr->gains = malloc(32*sizeof(float*)); drmr->pans = malloc(32*sizeof(float*)); diff --git a/drmr_hydrogen.c b/drmr_hydrogen.c index a7d3e56..29bedb0 100644 --- a/drmr_hydrogen.c +++ b/drmr_hydrogen.c @@ -451,13 +451,16 @@ int load_sample(char* path, drmr_layer* layer, double target_rate) { return 0; } -int load_hydrogen_kit(DrMr* drmr, char* path) { +drmr_sample* load_hydrogen_kit(char *path, double rate, int *num_samples) { FILE* file; char buf[BUFSIZ]; XML_Parser parser; int done; struct hp_info info; struct kit_info kit_info; + drmr_sample *samples; + struct instrument_info * cur_i; + int i = 0, num_inst = 0; snprintf(buf,BUFSIZ,"%s/drumkit.xml",path); @@ -466,7 +469,7 @@ int load_hydrogen_kit(DrMr* drmr, char* path) { file = fopen(buf,"r"); if (!file) { perror("Unable to open file:"); - return 1; + return NULL; } parser = XML_ParserCreate(NULL); @@ -487,88 +490,71 @@ int load_hydrogen_kit(DrMr* drmr, char* path) { "%s at line %lu\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); - return 1; + return NULL; } } while (!done); XML_ParserFree(parser); - { - drmr_sample *samples, *old_samples; - struct instrument_info * cur_i; - int i = 0, num_inst = 0, old_scount; - printf("Read kit: %s\n",kit_info.name); - cur_i = kit_info.instruments; - while(cur_i) { // first count how many samples we have - num_inst ++; - cur_i = cur_i->next; - } - printf("Loading %i instruments\n",num_inst); - samples = malloc(num_inst*sizeof(drmr_sample)); - cur_i = kit_info.instruments; - while(cur_i) { - if (cur_i->filename) { // top level filename, just make one dummy layer - drmr_layer *layer = malloc(sizeof(drmr_layer)); - layer->min = 0; - layer->max = 1; - snprintf(buf,BUFSIZ,"%s/%s",path,cur_i->filename); - if (load_sample(buf,layer,drmr->rate)) { + printf("Read kit: %s\n",kit_info.name); + cur_i = kit_info.instruments; + while(cur_i) { // first count how many samples we have + num_inst ++; + cur_i = cur_i->next; + } + printf("Loading %i instruments\n",num_inst); + samples = malloc(num_inst*sizeof(drmr_sample)); + cur_i = kit_info.instruments; + while(cur_i) { + if (cur_i->filename) { // top level filename, just make one dummy layer + drmr_layer *layer = malloc(sizeof(drmr_layer)); + layer->min = 0; + layer->max = 1; + snprintf(buf,BUFSIZ,"%s/%s",path,cur_i->filename); + if (load_sample(buf,layer,rate)) { + fprintf(stderr,"Could not load sample: %s\n",buf); + // set limit to zero, will never try and play + layer->info = NULL; + layer->limit = 0; + layer->data = NULL; + } + samples[i].layer_count = 0; + samples[i].layers = NULL; + samples[i].offset = 0; + samples[i].info = layer->info; + samples[i].limit = layer->limit; + samples[i].data = layer->data; + free(layer); + } else { + int layer_count = 0; + int j; + struct instrument_layer *cur_l = cur_i->layers; + while(cur_l) { + layer_count++; + cur_l = cur_l->next; + } + samples[i].layer_count = layer_count; + samples[i].layers = malloc(sizeof(drmr_layer)*layer_count); + cur_l = cur_i->layers; + j = 0; + while(cur_l) { + snprintf(buf,BUFSIZ,"%s/%s",path,cur_l->filename); + if (load_sample(buf,samples[i].layers+j,rate)) { fprintf(stderr,"Could not load sample: %s\n",buf); // set limit to zero, will never try and play - layer->info = NULL; - layer->limit = 0; - layer->data = NULL; - } - samples[i].layer_count = 0; - samples[i].layers = NULL; - samples[i].offset = 0; - samples[i].info = layer->info; - samples[i].limit = layer->limit; - samples[i].data = layer->data; - free(layer); - } else { - int layer_count = 0; - int j; - struct instrument_layer *cur_l = cur_i->layers; - while(cur_l) { - layer_count++; - cur_l = cur_l->next; - } - samples[i].layer_count = layer_count; - samples[i].layers = malloc(sizeof(drmr_layer)*layer_count); - cur_l = cur_i->layers; - j = 0; - while(cur_l) { - snprintf(buf,BUFSIZ,"%s/%s",path,cur_l->filename); - if (load_sample(buf,samples[i].layers+j,drmr->rate)) { - fprintf(stderr,"Could not load sample: %s\n",buf); - // set limit to zero, will never try and play - samples[i].layers[j].info = NULL; - samples[i].layers[j].limit = 0; - samples[i].layers[j].data = NULL; - } - samples[i].layers[j].min = cur_l->min; - samples[i].layers[j].max = cur_l->max; - j++; - cur_l = cur_l->next; + samples[i].layers[j].info = NULL; + samples[i].layers[j].limit = 0; + samples[i].layers[j].data = NULL; } + samples[i].layers[j].min = cur_l->min; + samples[i].layers[j].max = cur_l->max; + j++; + cur_l = cur_l->next; } - samples[i].active = 0; - i++; - cur_i = cur_i->next; } - old_samples = drmr->samples; - old_scount = drmr->num_samples; - if (num_inst > drmr->num_samples) { - // we have more, so we can safely swap our sample list in before updating num_samples - drmr->samples = samples; - drmr->num_samples = num_inst; - } else { - // previous has more, update count first - drmr->num_samples = num_inst; - drmr->samples = samples; - } - if (old_samples) free_samples(old_samples,old_scount); + samples[i].active = 0; + i++; + cur_i = cur_i->next; } - return 0; - + *num_samples = num_inst; + return samples; } diff --git a/drmr_hydrogen.h b/drmr_hydrogen.h index 1b9fa29..e69f804 100644 --- a/drmr_hydrogen.h +++ b/drmr_hydrogen.h @@ -22,6 +22,6 @@ kits* scan_kits(); void free_kits(kits* kits); void free_samples(drmr_sample* samples, int num_samples); int load_sample(char* path,drmr_layer* layer,double target_rate); -int load_hydrogen_kit(DrMr* drmr, char* path); +drmr_sample *load_hydrogen_kit(char *path, double rate, int *num_samples); #endif // DRMR_HYDRO_H diff --git a/drmr_ui.c b/drmr_ui.c index 4951f0c..b12ab67 100644 --- a/drmr_ui.c +++ b/drmr_ui.c @@ -31,6 +31,7 @@ typedef struct { GtkWidget *drmr_widget; GtkTable *sample_table; GtkComboBox *kit_combo; + GtkSpinButton *base_spin; GtkLabel *base_label; GtkListStore *kit_store; GtkWidget** gain_sliders; @@ -42,6 +43,7 @@ typedef struct { GQuark gain_quark, pan_quark; int curKit; + int kitReq; kits* kits; } DrMrUi; @@ -188,7 +190,7 @@ static void build_drmr_ui(DrMrUi* ui) { (gtk_adjustment_new(36.0, // val 21.0,107.0, // min/max 1.0, // step - 5.0,5.0)); // page adj/size + 5.0,0.0)); // page adj/size base_spin = gtk_spin_button_new(base_adj, 1.0, 0); gtk_box_pack_start(GTK_BOX(opts_hbox),kit_label, @@ -207,6 +209,7 @@ static void build_drmr_ui(DrMrUi* ui) { ui->sample_table = NULL; ui->kit_combo = GTK_COMBO_BOX(kit_combo_box); ui->base_label = GTK_LABEL(base_label); + ui->base_spin = GTK_SPIN_BUTTON(base_spin); g_signal_connect(G_OBJECT(kit_combo_box),"changed",G_CALLBACK(kit_combobox_changed),ui); @@ -257,6 +260,60 @@ static void cleanup(LV2UI_Handle handle) { free(ui); } +struct slider_callback_data { + GtkRange* range; + float val; +}; +static gboolean slider_callback(gpointer data) { + struct slider_callback_data *cbd = (struct slider_callback_data*)data; + gtk_range_set_value(cbd->range,cbd->val); + free(cbd); + return FALSE; // don't keep calling +} + +static gboolean idle = FALSE; +static gboolean kit_callback(gpointer data) { + DrMrUi* ui = (DrMrUi*)data; + if (ui->kitReq != ui->curKit) { + int samples = (ui->kitReqkits->num_kits && ui->kitReq >= 0)? + ui->kits->kits[ui->kitReq].samples: + 0; + GtkWidget** gain_sliders; + GtkWidget** pan_sliders; + if (ui->sample_table) { + gain_sliders = ui->gain_sliders; + pan_sliders = ui->pan_sliders; + ui->gain_sliders = NULL; + ui->pan_sliders = NULL; + if (gain_sliders) free(gain_sliders); + if (pan_sliders) free(pan_sliders); + gtk_widget_destroy(GTK_WIDGET(ui->sample_table)); + ui->sample_table = NULL; + } + if (samples > 0) { + ui->sample_table = GTK_TABLE(gtk_table_new(1,1,true)); + gtk_table_set_col_spacings(ui->sample_table,5); + gtk_table_set_row_spacings(ui->sample_table,5); + + gain_sliders = malloc(samples*sizeof(GtkWidget*)); + pan_sliders = malloc(samples*sizeof(GtkWidget*)); + fill_sample_table(ui,samples,gain_sliders,pan_sliders); + gtk_box_pack_start(GTK_BOX(ui->drmr_widget),GTK_WIDGET(ui->sample_table), + true,true,5); + gtk_box_reorder_child(GTK_BOX(ui->drmr_widget),GTK_WIDGET(ui->sample_table),0); + gtk_widget_show_all(GTK_WIDGET(ui->sample_table)); + ui->samples = samples; + ui->gain_sliders = gain_sliders; + ui->pan_sliders = pan_sliders; + + ui->curKit = ui->kitReq; + gtk_combo_box_set_active(ui->kit_combo,ui->curKit); + } + } + idle = FALSE; + return FALSE; // don't keep calling +} + static void port_event(LV2UI_Handle handle, uint32_t port_index, @@ -271,31 +328,19 @@ port_event(LV2UI_Handle handle, fprintf(stderr,"Invalid format for kitnum: %i\n",format); else { int kit = (int)(*((float*)buffer)); - int samples = ui->kits->kits[kit].samples; - GtkWidget** gain_sliders; - GtkWidget** pan_sliders; - if (ui->sample_table) { - ui->gain_sliders = NULL; - ui->pan_sliders = NULL; - gtk_widget_destroy(GTK_WIDGET(ui->sample_table)); + ui->kitReq = kit; + if (!idle) { + idle = TRUE; + g_idle_add(kit_callback,ui); } - ui->sample_table = GTK_TABLE(gtk_table_new(1,1,true)); - gtk_table_set_col_spacings(ui->sample_table,5); - gtk_table_set_row_spacings(ui->sample_table,5); - ui->curKit = kit; - if (ui->gain_sliders) free(ui->gain_sliders); - if (ui->pan_sliders) free(ui->pan_sliders); - gain_sliders = malloc(samples*sizeof(GtkWidget*)); - pan_sliders = malloc(samples*sizeof(GtkWidget*)); - fill_sample_table(ui,samples,gain_sliders,pan_sliders); - gtk_box_pack_start(GTK_BOX(ui->drmr_widget),GTK_WIDGET(ui->sample_table), - true,true,5); - gtk_box_reorder_child(GTK_BOX(ui->drmr_widget),GTK_WIDGET(ui->sample_table),0); - gtk_widget_show_all(GTK_WIDGET(ui->sample_table)); - gtk_combo_box_set_active(ui->kit_combo,kit); - ui->samples = samples; - ui->gain_sliders = gain_sliders; - ui->pan_sliders = pan_sliders; + } + } + else if (index == DRMR_BASENOTE) { + int base = (int)(*((float*)buffer)); + if (base >= 21 && base <= 107) { + setBaseLabel((int)base); + gtk_spin_button_set_value(ui->base_spin,base); + gtk_label_set_markup(ui->base_label,baseLabelBuf); } } else if (index >= DRMR_GAIN_ONE && @@ -304,8 +349,12 @@ port_event(LV2UI_Handle handle, float gain = *(float*)buffer; int idx = index-DRMR_GAIN_ONE; if (idx < ui->samples) { - GtkRange* range = GTK_RANGE(ui->gain_sliders[idx]); - gtk_range_set_value(range,gain); + struct slider_callback_data* data = malloc(sizeof(struct slider_callback_data)); + data->range = GTK_RANGE(ui->gain_sliders[idx]); + data->val = gain; + g_idle_add(slider_callback,data); + //GtkRange* range = GTK_RANGE(ui->gain_sliders[idx]); + //gtk_range_set_value(range,gain); } } } @@ -315,8 +364,12 @@ port_event(LV2UI_Handle handle, float pan = *(float*)buffer; int idx = index-DRMR_PAN_ONE; if (idx < ui->samples) { - GtkRange* range = GTK_RANGE(ui->pan_sliders[idx]); - gtk_range_set_value(range,pan); + struct slider_callback_data* data = malloc(sizeof(struct slider_callback_data)); + data->range = GTK_RANGE(ui->pan_sliders[idx]); + data->val = pan; + g_idle_add(slider_callback,data); + //GtkRange* range = GTK_RANGE(ui->pan_sliders[idx]); + //gtk_range_set_value(range,pan); } } }