Beispiel #1
0
void
ags_drum_sequencer_count_callback(AgsDelayAudioRun *delay_audio_run,
				  guint nth_run,
				  guint delay, guint attack,
				  AgsDrum *drum)
{
  AgsWindow *window;
  AgsAudio *audio;
  AgsCountBeatsAudio *play_count_beats_audio;
  AgsCountBeatsAudioRun *play_count_beats_audio_run;
  AgsToggleLed *toggle_led;
  GList *list;
  guint counter, active_led;
  gdouble active_led_old, active_led_new;
  GValue value = {0,};
  
  window = AGS_WINDOW(gtk_widget_get_ancestor((GtkWidget *) drum, AGS_TYPE_WINDOW));

  audio = AGS_MACHINE(drum)->audio;

  /* get some recalls */
  list = ags_recall_find_type(audio->play,
			      AGS_TYPE_COUNT_BEATS_AUDIO);
  
  if(list != NULL){
    play_count_beats_audio = AGS_COUNT_BEATS_AUDIO(list->data);
  }

  list = ags_recall_find_type_with_recycling_container(audio->play,
						       AGS_TYPE_COUNT_BEATS_AUDIO_RUN,
						       (GObject *) AGS_RECALL(delay_audio_run)->recall_id->recycling_container);
  
  if(list != NULL){
    play_count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(list->data);
  }

  /* set optical feedback */
  active_led_new = (guint) play_count_beats_audio_run->sequencer_counter % AGS_DRUM_PATTERN_CONTROLS;
  drum->active_led = (guint) active_led_new;

  if(play_count_beats_audio_run->sequencer_counter == 0){
    g_value_init(&value, G_TYPE_DOUBLE);
    ags_port_safe_read(play_count_beats_audio->sequencer_loop_end,
		       &value);

    active_led_old = (guint) (g_value_get_double(&value) - 1.0) % AGS_DRUM_PATTERN_CONTROLS;
  }else{
    active_led_old = (guint) (drum->active_led - 1.0) % AGS_DRUM_PATTERN_CONTROLS;
  }

  toggle_led = ags_toggle_led_new(gtk_container_get_children(GTK_CONTAINER(drum->led)),
				  (guint) active_led_new,
				  (guint) active_led_old);

  ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(window->ags_main)->main_loop)->task_thread),
			      AGS_TASK(toggle_led));
}
Beispiel #2
0
void
ags_drum_done_callback(AgsAudio *audio,
		       AgsRecallID *recall_id,
		       AgsDrum *drum)
{
  GList *devout_play;
  gboolean all_done;

  devout_play = AGS_DEVOUT_PLAY_DOMAIN(audio->devout_play_domain)->devout_play;

  /* check unset */
  all_done = TRUE;

  while(devout_play != NULL){
    if(AGS_DEVOUT_PLAY(devout_play->data)->recall_id[1] != NULL){
      all_done = FALSE;
      break;
    }

    devout_play = devout_play->next;
  }

  if(all_done){
    GList *list;
    guint active_led;

    /* get active led */
    if(drum->active_led == 0){
      AgsCountBeatsAudio *play_count_beats_audio;
      GValue value = {0,};

      /* get some recalls */
      list = ags_recall_find_type(audio->play,
				  AGS_TYPE_COUNT_BEATS_AUDIO);
  
      if(list != NULL){
	play_count_beats_audio = AGS_COUNT_BEATS_AUDIO(list->data);
      }
  
      g_value_init(&value, G_TYPE_DOUBLE);
      ags_port_safe_read(play_count_beats_audio->sequencer_loop_end,
			 &value);
      
      active_led = g_value_get_double(&value) - 1.0;
    }else{
      active_led = drum->active_led - 1;
    }

    /* unset led */
    list = gtk_container_get_children(GTK_CONTAINER(drum->led));
    ags_led_unset_active(AGS_LED(g_list_nth(list,
					    active_led)->data));

    g_list_free(list);
  }
}
void
ags_osc_renew_controller_test_set_data()
{
  AgsChannel *channel;
  
  AgsOscConnection *osc_connection;

  AgsOscRenewController *osc_renew_controller;

  GList *osc_response;

  unsigned char *message;
  unsigned char *magnitude_message;

  gdouble *magnitude_buffer;
  
  guint magnitude_message_size;
  guint cache_buffer_size;
  guint length;
  guint padding;
  guint i, j;
  gboolean success;
  
  GValue value = {0,};
  
  static const unsigned char *mute_message = "/renew\x00\x00,sf\x00/AgsSoundProvider/AgsAudio[\"test-panel\"]/AgsInput[0-1]/AgsMuteChannel[0]/AgsPort[\"./muted[0]\"]:value\x00\x00\x00\x00\x00\x00";
  static const unsigned char *magnitude_path = "/AgsSoundProvider/AgsAudio[\"test-spectrometer\"]/AgsInput[0-1]/AgsAnalyseChannel[0]/AgsPort[\"./magnitude-buffer[0]\"]:value";

  static const guint mute_message_size = 120;
  
  osc_connection = ags_osc_connection_new(NULL);
  
  osc_renew_controller = ags_osc_renew_controller_new();

  /* panel */
  message = (unsigned char *) malloc(mute_message_size * sizeof(unsigned char));
  memcpy(message, mute_message, mute_message_size * sizeof(unsigned char));

  ags_osc_buffer_util_put_float(message + mute_message_size - 4,
				1.0);
  
  g_value_init(&value,
	       G_TYPE_FLOAT);

  g_object_get(panel,
	       "input", &channel,
	       NULL);
  success = TRUE;

  for(i = 0; i < 2 && success; i++){
    GList *start_play, *play;
    GList *start_port, *port;

    g_object_get(channel,
		 "play", &start_play,
		 NULL);

    play = ags_recall_template_find_type(start_play,
					 AGS_TYPE_MUTE_CHANNEL);

    g_object_get(play->data,
		 "port", &start_port,
		 NULL);

    port = ags_port_find_specifier(start_port,
				   "./muted[0]");

    ags_port_safe_read(port->data,
		       &value);

    if(g_value_get_float(&value) == 1.0){
      success = FALSE;

      break;
    }
    
    g_object_get(channel,
		 "next", &channel,
		 NULL);
  }
  
  CU_ASSERT(success);
  
  osc_response = ags_osc_renew_controller_set_data(osc_renew_controller,
						   osc_connection,
						   message, mute_message_size);

  CU_ASSERT(osc_response != NULL);
  
  g_object_get(panel,
	       "input", &channel,
	       NULL);
  success = TRUE;

  for(i = 0; i < 2 && success; i++){
    GList *start_play, *play;
    GList *start_port, *port;

    g_object_get(channel,
		 "play", &start_play,
		 NULL);

    play = ags_recall_template_find_type(start_play,
					 AGS_TYPE_MUTE_CHANNEL);

    g_object_get(play->data,
		 "port", &start_port,
		 NULL);

    port = ags_port_find_specifier(start_port,
				   "./muted[0]");

    ags_port_safe_read(port->data,
		       &value);

    if(g_value_get_float(&value) != 1.0){
      success = FALSE;

      break;
    }
    
    g_object_get(channel,
		 "next", &channel,
		 NULL);
  }
  
  CU_ASSERT(success);

  /* spectrometer */
  magnitude_message = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));

  cache_buffer_size = ags_soundcard_helper_config_get_buffer_size(ags_config_get_instance()) / 2;

  memcpy(magnitude_message, "/renew\x00\x00,s[", 11 * sizeof(unsigned char));
  magnitude_message_size = 11;

  for(i = 0; i < cache_buffer_size; i++){
    magnitude_message[11 + i] = 'd';
  }

  magnitude_message[11 + i] = ']';
  magnitude_message_size += (cache_buffer_size + 1);

  padding = (4 * (guint) ceil((cache_buffer_size + 5) / 4.0)) - (cache_buffer_size + 4);

  for(i = 0; i < padding; i++){
    magnitude_message[magnitude_message_size + i] = '\x00';
  }

  magnitude_message_size += padding;

  length = strlen(magnitude_path);
  memcpy(magnitude_message + magnitude_message_size, magnitude_path, (length) * sizeof(unsigned char));

  padding = (4 * (guint) ceil((length + 1) / 4.0)) - length;

  magnitude_message_size += length;
  
  for(i = 0; i < padding; i++){
    magnitude_message[magnitude_message_size + i] = '\x00';
  }
  
  magnitude_message_size += padding;
  
  for(i = 0; i < cache_buffer_size; i++){
    ags_osc_buffer_util_put_double(magnitude_message + magnitude_message_size + (i * 8),
				   4.0);
  }

  magnitude_message_size += (cache_buffer_size * 8);

  g_value_unset(&value);
  g_value_init(&value,
	       G_TYPE_POINTER);

  magnitude_buffer = (gdouble *) malloc(cache_buffer_size * sizeof(gdouble));
  g_value_set_pointer(&value,
		      magnitude_buffer);
  
  g_object_get(spectrometer,
	       "input", &channel,
	       NULL);
  success = TRUE;

  for(i = 0; i < 2 && success; i++){
    GList *start_play, *play;
    GList *start_port, *port;
    
    g_object_get(channel,
		 "play", &start_play,
		 NULL);

    play = ags_recall_template_find_type(start_play,
					 AGS_TYPE_ANALYSE_CHANNEL);

    g_object_get(play->data,
		 "port", &start_port,
		 NULL);

    port = ags_port_find_specifier(start_port,
				   "./magnitude-buffer[0]");
    
    ags_port_safe_read(port->data,
		       &value);

    for(j = 0; j < cache_buffer_size; j++){
      if(magnitude_buffer[j] != 0.0){
	success = FALSE;

	break;
      }
    }
    
    g_object_get(channel,
		 "next", &channel,
		 NULL);
  }
  
  CU_ASSERT(success);
  
  osc_response = ags_osc_renew_controller_set_data(osc_renew_controller,
						   osc_connection,
						   magnitude_message, magnitude_message_size);
  
  g_object_get(spectrometer,
	       "input", &channel,
	       NULL);
  success = TRUE;

  for(i = 0; i < 2 && success; i++){
    GList *start_play, *play;
    GList *start_port, *port;

    g_object_get(channel,
		 "play", &start_play,
		 NULL);

    play = ags_recall_template_find_type(start_play,
					 AGS_TYPE_ANALYSE_CHANNEL);

    g_object_get(play->data,
		 "port", &start_port,
		 NULL);

    port = ags_port_find_specifier(start_port,
				   "./magnitude-buffer[0]");

    ags_port_safe_read(port->data,
		       &value);

    for(j = 0; j < cache_buffer_size; j++){
      if(magnitude_buffer[j] != 4.0){
	success = FALSE;
	
	break;
      }
    }
    
    g_object_get(channel,
		 "next", &channel,
		 NULL);
  }
  
  CU_ASSERT(success);
}
void
ags_recall_dssi_run_run_pre(AgsRecall *recall)
{
  AgsRecallDssi *recall_dssi;
  AgsRecallChannelRun *recall_channel_run;
  AgsRecallRecycling *recall_recycling;
  AgsRecallDssiRun *recall_dssi_run;
  AgsAudioSignal *audio_signal;
  AgsPort *current_port;
  AgsRecallID *recall_id;
  AgsRecyclingContext *parent_recycling_context, *recycling_context;
  
  AgsCountBeatsAudioRun *count_beats_audio_run;
  AgsRouteDssiAudioRun *route_dssi_audio_run;
    
  GList *list_start, *list;
  GList *port;
  
  GList *note_start, *note;

  snd_seq_event_t **event_buffer;
  unsigned long *event_count;
    
  gchar *specifier, *current_specifier;
  
  LADSPA_Data port_data;

  guint bank, program;
  guint output_lines, input_lines;
  guint notation_counter;
  guint x0, x1;
  guint port_count;
  
  guint copy_mode_in, copy_mode_out;
  guint buffer_size;
  guint i, i_stop;

  void (*parent_class_run_pre)(AgsRecall *recall);

  void (*select_program)(LADSPA_Handle Instance,
			 unsigned long Bank,
			 unsigned long Program);
  void (*run_synth)(LADSPA_Handle Instance,
		    unsigned long SampleCount,
		    snd_seq_event_t *Events,
		    unsigned long EventCount);
  void (*run)(LADSPA_Handle Instance,
	      unsigned long SampleCount);
  void (*deactivate)(LADSPA_Handle Instance);
  void (*cleanup)(LADSPA_Handle Instance);
  
  pthread_mutex_t *recall_dssi_mutex;
  pthread_mutex_t *port_mutex;

  /* get parent class */
  pthread_mutex_lock(ags_recall_get_class_mutex());

  parent_class_run_pre = AGS_RECALL_CLASS(ags_recall_dssi_run_parent_class)->run_pre;
  
  pthread_mutex_unlock(ags_recall_get_class_mutex());

  /* call parent */
  parent_class_run_pre(recall);

  g_object_get(recall,
	       "recall-id", &recall_id,
	       "source", &audio_signal,
	       NULL);

  g_object_get(recall_id,
	       "recycling-context", &recycling_context,
	       NULL);

  g_object_get(recycling_context,
	       "parent", &parent_recycling_context,
	       NULL);

  g_object_get(audio_signal,
	       "note", &note_start,
	       NULL);

  if(ags_recall_global_get_rt_safe() &&
     parent_recycling_context != NULL &&
     note_start == NULL){
    g_object_unref(recall_id);

    g_object_unref(audio_signal);
    
    g_object_unref(recycling_context);

    g_object_unref(parent_recycling_context);
    
    return;
  }

  g_list_free_full(note_start,
		   g_object_unref);
  
  g_object_get(recall,
	       "parent", &recall_recycling,
	       NULL);

  g_object_get(recall_recycling,
	       "parent", &recall_channel_run,
	       NULL);

  g_object_get(recall_channel_run,
	       "recall-channel", &recall_dssi,
	       NULL);

  recall_dssi_run = AGS_RECALL_DSSI_RUN(recall);

  g_object_get(recall_dssi_run,
	       "route-dssi-audio-run", &route_dssi_audio_run,
	       NULL);
  
  if(route_dssi_audio_run == NULL){
    g_object_unref(recall_id);

    g_object_unref(audio_signal);

    g_object_unref(recycling_context);

    g_object_unref(parent_recycling_context);

    g_object_unref(recall_recycling);
    
    g_object_unref(recall_channel_run);

    g_object_unref(recall_dssi);

    return;
  }

  /* get recall dssi mutex */
  pthread_mutex_lock(ags_recall_get_class_mutex());
  
  recall_dssi_mutex = AGS_RECALL(recall_dssi)->obj_mutex;
  
  pthread_mutex_unlock(ags_recall_get_class_mutex());

  g_object_get(route_dssi_audio_run,
	       "count-beats-audio-run", &count_beats_audio_run,
	       NULL);

  g_object_get(audio_signal,
	       "buffer-size", &buffer_size,
	       NULL);

  /* get some fields */
  pthread_mutex_lock(recall_dssi_mutex);

  output_lines = recall_dssi->output_lines;
  input_lines = recall_dssi->input_lines;

  pthread_mutex_unlock(recall_dssi_mutex);

  if(input_lines < output_lines){
    i_stop = output_lines;
  }else{
    i_stop = input_lines;
  }

  g_object_get(count_beats_audio_run,
	       "notation-counter", &notation_counter,
	       NULL);
  
  if(ags_recall_global_get_rt_safe()){  
    g_object_get(recall_dssi_run,
		 "note", &note_start,
		 NULL);
    
    note = note_start;
    
    while(note != NULL){
      g_object_get(note->data,
		   "x0", &x0,
		   "x1", &x1,
		   NULL);
	
      if((x1 + 1 <= notation_counter &&
	  !ags_note_test_flags(note->data, AGS_NOTE_FEED)) ||
	 x0 > notation_counter){
	recall_dssi_run->note = g_list_remove(recall_dssi_run->note,
					      note->data);
	g_object_unref(note->data);
      }
    
      note = note->next;
    }
    
    if(note_start == NULL){
      memset(recall_dssi_run->event_buffer[0], 0, sizeof(snd_seq_event_t));
    }

    g_list_free_full(note_start,
		     g_object_unref);
  }else{  
    g_object_get(recall_dssi_run,
		 "note", &note_start,
		 NULL);
    
    g_object_get(note_start->data,
		 "x0", &x0,
		 "x1", &x1,
		 NULL);
    
    if(audio_signal->stream_current == NULL ||
       (x1 + 1 <= notation_counter &&
	!ags_note_test_flags(note_start->data, AGS_NOTE_FEED)) ||
       x0 > notation_counter){
      //    g_message("done");

      pthread_mutex_lock(recall_dssi_mutex);

      deactivate = recall_dssi->plugin_descriptor->LADSPA_Plugin->deactivate;
      cleanup = recall_dssi->plugin_descriptor->LADSPA_Plugin->cleanup;
      
      pthread_mutex_unlock(recall_dssi_mutex);
      
      for(i = 0; i < i_stop; i++){
	/* deactivate */
	//TODO:JK: fix-me
	if(deactivate != NULL){
	  deactivate(recall_dssi_run->ladspa_handle[i]);
	}
      
	cleanup(recall_dssi_run->ladspa_handle[i]);
      }
      
      ags_recall_done(recall);

      g_list_free_full(note_start,
		       g_object_unref);

      goto ags_recall_dssi_run_run_pre_END;
    }
  }
  
  /* get copy mode and clear buffer */
  copy_mode_in = ags_audio_buffer_util_get_copy_mode(AGS_AUDIO_BUFFER_UTIL_FLOAT,
						     ags_audio_buffer_util_format_from_soundcard(audio_signal->format));

  copy_mode_out = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(audio_signal->format),
						      AGS_AUDIO_BUFFER_UTIL_FLOAT);
  
  if(recall_dssi_run->output != NULL){
    ags_audio_buffer_util_clear_float(recall_dssi_run->output, output_lines,
				      buffer_size);
  }

  if(recall_dssi_run->input != NULL){
    ags_audio_buffer_util_clear_float(recall_dssi_run->input, input_lines,
				      buffer_size);
  }

  /* copy data  */
  if(recall_dssi_run->input != NULL){
    ags_audio_buffer_util_copy_buffer_to_buffer(recall_dssi_run->input, input_lines, 0,
						audio_signal->stream_current->data, 1, 0,
						buffer_size, copy_mode_in);
  }

  /* select program */
  pthread_mutex_lock(recall_dssi_mutex);

  port_count = recall_dssi->plugin_descriptor->LADSPA_Plugin->PortCount;

  select_program = recall_dssi->plugin_descriptor->select_program;
  
  pthread_mutex_unlock(recall_dssi_mutex);

  /* cache port data */
  g_object_get(recall_dssi,
	       "port", &list_start,
	       NULL);
  
  for(i = 0; i < port_count; i++){
    pthread_mutex_lock(recall_dssi_mutex);

    specifier = g_strdup(recall_dssi->plugin_descriptor->LADSPA_Plugin->PortNames[i]);

    pthread_mutex_unlock(recall_dssi_mutex);

    list = list_start;
    
    while(list != NULL){
      gboolean success;
      
      current_port = list->data;

      /* get port mutex */
      pthread_mutex_lock(ags_port_get_class_mutex());

      port_mutex = current_port->obj_mutex;
      
      pthread_mutex_unlock(ags_port_get_class_mutex());

      /* check specifier */
      pthread_mutex_lock(port_mutex);

      current_specifier = g_strdup(current_port->specifier);
      
      pthread_mutex_unlock(port_mutex);
      
      success = (!g_strcmp0(specifier,
			    current_specifier)) ? TRUE: FALSE;
      g_free(current_specifier);
	
      if(success){
	GValue value = {0,};
	  
	g_value_init(&value,
		     G_TYPE_FLOAT);
	ags_port_safe_read(current_port,
			   &value);
	
	recall_dssi_run->port_data[i] = g_value_get_float(&value);

	g_value_unset(&value);
	
	break;
      }

      list = list->next;
    }

    g_free(specifier);
  }

  g_object_get(recall_dssi,
	       "bank", &bank,
	       "program", &program,
	       NULL);
  
  if(select_program != NULL){    
    for(i = 0; i < i_stop; i++){
      select_program(recall_dssi_run->ladspa_handle[i],
		     (unsigned long) bank,
		     (unsigned long) program);

      //      g_message("b p %u %u", bank, program);
    }
  }

  /* reset port data */    
  for(i = 0; i < port_count; i++){
    pthread_mutex_lock(recall_dssi_mutex);

    specifier = g_strdup(recall_dssi->plugin_descriptor->LADSPA_Plugin->PortNames[i]);

    pthread_mutex_unlock(recall_dssi_mutex);

    list = list_start;
    current_port = NULL;
    
    while(list != NULL){
      gboolean success;
      
      current_port = list->data;

      /* get port mutex */
      pthread_mutex_lock(ags_port_get_class_mutex());

      port_mutex = current_port->obj_mutex;
      
      pthread_mutex_unlock(ags_port_get_class_mutex());

      /* check specifier */
      pthread_mutex_lock(port_mutex);

      current_specifier = g_strdup(current_port->specifier);
      
      pthread_mutex_unlock(port_mutex);
      
      success = (!g_strcmp0(specifier,
			    current_specifier)) ? TRUE: FALSE;
      g_free(current_specifier);

      if(success){
	break;
      }

      list = list->next;
    }

    g_free(specifier);

    if(list != NULL){
      GValue value = {0,};
      
      g_value_init(&value,
		   G_TYPE_FLOAT);
      port_data = recall_dssi_run->port_data[i];

      g_value_set_float(&value,
			port_data);
      ags_port_safe_write(current_port,
			  &value);

      g_value_unset(&value);
    }
  }

  g_list_free_full(list_start,
		   g_object_unref);
  
  /* process data */
  pthread_mutex_lock(recall_dssi_mutex);

  run_synth = recall_dssi->plugin_descriptor->run_synth;
  run = recall_dssi->plugin_descriptor->LADSPA_Plugin->run;
  
  pthread_mutex_unlock(recall_dssi_mutex);

  g_object_get(recall_dssi_run,
	       "note", &note_start,
	       NULL);
  
  note = note_start;

  while(note != NULL){    
    if(run_synth != NULL){
      if(recall_dssi_run->event_buffer != NULL){
	event_buffer = recall_dssi_run->event_buffer;
	event_count = recall_dssi_run->event_count;
      
	while(*event_buffer != NULL){
	  if(event_buffer[0]->type == SND_SEQ_EVENT_NOTEON){
	    run_synth(recall_dssi_run->ladspa_handle[0],
		      (unsigned long) (output_lines * buffer_size),
		      event_buffer[0],
		      event_count[0]);
	  }
	  
	  event_buffer++;
	  event_count++;
	}
      }
    }else if(run != NULL){
      run(recall_dssi_run->ladspa_handle[0],
	  (unsigned long) buffer_size);
    }

    note = note->next;
  }

  g_list_free_full(note_start,
		   g_object_unref);
  
  /* copy data */
  if(recall_dssi_run->output != NULL){
    ags_audio_buffer_util_clear_buffer(audio_signal->stream_current->data, 1,
				       buffer_size, ags_audio_buffer_util_format_from_soundcard(audio_signal->format));
    
    ags_audio_buffer_util_copy_buffer_to_buffer(audio_signal->stream_current->data, 1, 0,
						recall_dssi_run->output, output_lines, 0,
						buffer_size, copy_mode_out);
  }

ags_recall_dssi_run_run_pre_END:
  
  g_object_unref(recall_id);

  g_object_unref(recycling_context);

  g_object_unref(parent_recycling_context);

  g_object_unref(recall_recycling);
    
  g_object_unref(recall_channel_run);

  g_object_unref(recall_dssi);

  g_object_unref(count_beats_audio_run);
}
Beispiel #5
0
void
ags_play_audio_signal_run_inter(AgsRecall *recall)
{
  AgsDevout *devout;
  AgsRecycling *recycling;
  AgsAudioSignal *source;
  AgsPlayChannel *play_channel;
  AgsPlayAudioSignal *play_audio_signal;
  GList *stream;
  signed short *buffer0, *buffer1;
  guint audio_channel;
  gboolean muted;
  GValue muted_value = {0,};
  GValue audio_channel_value = {0,};

  play_audio_signal = AGS_PLAY_AUDIO_SIGNAL(recall);

  devout = AGS_DEVOUT(AGS_RECALL(play_audio_signal)->devout);
  source = AGS_AUDIO_SIGNAL(AGS_RECALL_AUDIO_SIGNAL(play_audio_signal)->source);
  stream = source->stream_current;

  if(devout == NULL){
    g_warning("no devout\0");
    return;
  }

  if(stream == NULL){
    ags_recall_done(recall);

    return;
  }

  if((AGS_DEVOUT_BUFFER0 & devout->flags) != 0){
    buffer0 = devout->buffer[1];
    buffer1 = devout->buffer[2];
  }else if((AGS_DEVOUT_BUFFER1 & devout->flags) != 0){
    buffer0 = devout->buffer[2];
    buffer1 = devout->buffer[3];
  }else if((AGS_DEVOUT_BUFFER2 & devout->flags) != 0){
    buffer0 = devout->buffer[3];
    buffer1 = devout->buffer[0];
  }else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
    buffer0 = devout->buffer[0];
    buffer1 = devout->buffer[1];
  }else{
    g_warning("no output buffer\0");
    return;
  }

  play_channel = AGS_PLAY_CHANNEL(AGS_RECALL_CHANNEL_RUN(recall->parent->parent)->recall_channel);

  g_value_init(&muted_value, G_TYPE_BOOLEAN);
  ags_port_safe_read(play_channel->muted,
		     &muted_value);

  muted = g_value_get_boolean(&muted_value);

  if(muted){
    return;
  }

  g_value_init(&audio_channel_value, G_TYPE_UINT);
  ags_port_safe_read(play_channel->audio_channel,
		     &audio_channel_value);

  audio_channel = g_value_get_uint(&audio_channel_value);

  if((AGS_RECALL_INITIAL_RUN & (AGS_RECALL_AUDIO_SIGNAL(recall)->flags)) != 0){
    AGS_RECALL_AUDIO_SIGNAL(recall)->flags &= (~AGS_RECALL_INITIAL_RUN);
    ags_audio_signal_copy_buffer_to_buffer(&(buffer0[audio_channel + source->attack * devout->pcm_channels]),
					   devout->pcm_channels,
					   (signed short *) stream->data, 1,
					   AGS_DEVOUT_DEFAULT_BUFFER_SIZE - source->attack);
  }else{
    ags_audio_signal_copy_buffer_to_buffer(&(buffer0[audio_channel]), devout->pcm_channels,
					   (signed short *) stream->data, 1,
					   devout->buffer_size);
  }

  /* call parent */
  AGS_RECALL_CLASS(ags_play_audio_signal_parent_class)->run_inter(recall);
}
void
ags_stream_audio_signal_run_post(AgsRecall *recall)
{
  AgsStreamChannel *stream_channel;
  AgsStreamChannelRun *stream_channel_run;
  AgsStreamAudioSignal *stream_audio_signal;

  stream_audio_signal = AGS_STREAM_AUDIO_SIGNAL(recall);
  
  if(recall->parent != NULL &&
     recall->parent->parent != NULL){
    stream_channel_run = recall->parent->parent;
    stream_channel = AGS_RECALL_CHANNEL_RUN(stream_channel_run)->recall_channel;
  }else{
    stream_channel_run = NULL;
    stream_channel = NULL;
  }
  
  if(AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current != NULL){
    if(stream_channel != NULL &&
       AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current->next == NULL){
      GValue value = {0,};
      
      g_value_init(&value, G_TYPE_BOOLEAN);
      ags_port_safe_read(stream_channel->auto_sense,
			 &value);

      if(g_value_get_boolean(&value)){
	signed short *buffer;
	guint buffer_size;
	guint i;
	gboolean add_stream;

	buffer = AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current->data;
	
	buffer_size = AGS_RECALL_AUDIO_SIGNAL(recall)->source->buffer_size;
	add_stream = FALSE;
	
	for(i = buffer_size - 1; i > buffer_size / 2; i--){
	  if(buffer[i] != 0){
	    add_stream = TRUE;
	    break;
	  }
	}
	
	if(add_stream){
	  ags_audio_signal_add_stream(AGS_RECALL_AUDIO_SIGNAL(recall)->source);
	}
      }
    }
    
    AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current = AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current->next;

    /* call parent */
    AGS_RECALL_CLASS(ags_stream_audio_signal_parent_class)->run_post(recall);
  }else{
    /* call parent */
    AGS_RECALL_CLASS(ags_stream_audio_signal_parent_class)->run_post(recall);

    if(recall->parent != NULL){
      ags_recycling_remove_audio_signal(AGS_RECALL_RECYCLING(recall->parent)->source,
					AGS_RECALL_AUDIO_SIGNAL(recall)->source);
    }

    ags_recall_done(recall);
  }
}
Beispiel #7
0
/**
 * ags_audiorec_indicator_queue_draw_timeout:
 * @widget: the widget
 *
 * Queue draw widget
 *
 * Returns: %TRUE if proceed with redraw, otherwise %FALSE
 *
 * Since: 2.0.0
 */
gboolean
ags_audiorec_indicator_queue_draw_timeout(AgsAudiorec *audiorec)
{
  if(g_hash_table_lookup(ags_audiorec_indicator_queue_draw,
			 audiorec) != NULL){
    AgsAudio *audio;
    AgsChannel *start_channel;
    AgsChannel *channel, *next_channel;
    
    GList *list, *list_start;

    guint i;

    audio = AGS_MACHINE(audiorec)->audio;
    g_object_get(audio,
		 "output", &start_channel,
		 NULL);
    
    list_start = 
      list = gtk_container_get_children((GtkContainer *) audiorec->hindicator_vbox);
    
    /* check members */
    channel = start_channel;

    if(channel != NULL){
      g_object_ref(channel);
    }

    next_channel = NULL;
    
    for(i = 0; list != NULL; i++){
      GtkAdjustment *adjustment;
      GtkWidget *child;

      AgsPort *current;

      GList *start_port;
      
      gdouble average_peak;
      gdouble peak;
	
      GValue value = {0,};
	
      child = list->data;
      
      average_peak = 0.0;
      
      start_port = ags_channel_collect_all_channel_ports_by_specifier_and_context(channel,
										  "./peak[0]",
										  TRUE);

      current = NULL;

      if(start_port != NULL){
	current = start_port->data;
      }
      
      /* recall port - read value */
      g_value_init(&value, G_TYPE_FLOAT);
      ags_port_safe_read(current,
			 &value);
      
      peak = g_value_get_float(&value);
      g_value_unset(&value);

      /* calculate peak */
      average_peak += ((1.0 / (1.0 / peak)) * 10.0);
      
      /* apply */
      g_object_get(child,
		   "adjustment", &adjustment,
		   NULL);
	
      gtk_adjustment_set_value(adjustment,
			       average_peak);

      /* queue draw */
      gtk_widget_queue_draw(child);

      g_list_free_full(start_port,
		       g_object_unref);
      
      /* iterate */
      list = list->next;

      next_channel = ags_channel_next(channel);

      g_object_unref(channel);

      channel = next_channel;
    }

    if(start_channel != NULL){
      g_object_unref(start_channel);
    }

    if(next_channel != NULL){
      g_object_unref(next_channel);
    }
    
    g_list_free(list_start);
    
    return(TRUE);
  }else{
    return(FALSE);
  }
}
Beispiel #8
0
void
ags_delay_audio_change_tact(AgsTactable *tactable, gdouble new_tact)
{
  AgsDevout *devout;
  AgsDelayAudio *delay_audio;
  gdouble old_tact;
  gdouble sequencer_delay, notation_delay;
  gdouble sequencer_duration, notation_duration;
  gdouble factor;
  GValue value = {0,};
  
  delay_audio = AGS_DELAY_AUDIO(tactable);

  devout = AGS_DEVOUT(AGS_RECALL(delay_audio)->devout);

  /* retrieve old tact */
  g_value_init(&value, G_TYPE_DOUBLE);

  ags_port_safe_read(delay_audio->tact, &value);
  old_tact = g_value_get_double(&value);

  /* retrieve sequencer_delay */
  g_value_reset(&value);

  ags_port_safe_read(delay_audio->sequencer_delay, &value);
  sequencer_delay = g_value_get_double(&value);

  /* retrieve notation_delay */
  g_value_reset(&value);

  ags_port_safe_read(delay_audio->notation_delay, &value);
  notation_delay = g_value_get_double(&value);

  /* retrieve sequencer_duration */
  g_value_reset(&value);

  ags_port_safe_read(delay_audio->sequencer_duration, &value);
  sequencer_duration = g_value_get_double(&value);

  /* retrieve notation_duration */
  g_value_reset(&value);

  ags_port_safe_read(delay_audio->notation_duration, &value);
  notation_duration = g_value_get_double(&value);

  /* -- start adjust -- */
  factor = (new_tact / old_tact);

  /* notation-delay */
  g_value_reset(&value);

  g_value_set_double(&value, notation_delay * factor);
  ags_port_safe_write(delay_audio->notation_delay, &value);

  /* sequencer-delay */
  g_value_reset(&value);

  g_value_set_double(&value, sequencer_delay * factor);
  ags_port_safe_write(delay_audio->sequencer_delay, &value);

  /**/
  g_value_reset(&value);

  g_value_set_double(&value, new_tact);
  ags_port_safe_write(delay_audio->tact, &value);

  /* notation-duration */
  g_value_reset(&value);

  g_value_set_double(&value, notation_duration * factor);
  ags_port_safe_write(delay_audio->notation_duration, &value);

  /* sequencer-duration */
  g_value_reset(&value);

  g_value_set_double(&value, sequencer_duration * factor);
  ags_port_safe_write(delay_audio->sequencer_duration, &value);

  /* -- finish adjust -- */

  /* emit changed */
  ags_delay_audio_sequencer_duration_changed(delay_audio);
}
void
ags_stream_audio_signal_run_post(AgsRecall *recall)
{
  AgsAudioSignal *source;
  AgsStreamChannel *stream_channel;
  AgsStreamChannelRun *stream_channel_run;
  AgsStreamRecycling *stream_recycling;
  AgsStreamAudioSignal *stream_audio_signal;
  
  void (*parent_class_run_post)(AgsRecall *recall);

  stream_audio_signal = (AgsStreamAudioSignal *) recall;

  /* get parent class */
  pthread_mutex_lock(ags_recall_get_class_mutex());

  parent_class_run_post = AGS_RECALL_CLASS(ags_stream_audio_signal_parent_class)->run_post;

  pthread_mutex_unlock(ags_recall_get_class_mutex());

  g_object_get(stream_audio_signal,
	       "parent", &stream_recycling,
	       "source", &source,
	       NULL);
  
  g_object_get(stream_recycling,
	       "parent", &stream_channel_run,
	       NULL);

  g_object_get(stream_channel_run,
	       "recall-channel", &stream_channel,
	       NULL);

#ifdef AGS_DEBUG
  g_message("stream[%d] %x %d: %d", AGS_RECALL_CHANNEL(stream_channel)->source->line, source, g_list_length(source->stream), g_list_length(source->stream_current));
#endif
  
  if(source->stream_current != NULL){
    if(source->stream_current->next == NULL){
      AgsPort *port;

      gboolean auto_sense;
      
      GValue value = {0,};

      g_object_get(stream_channel,
		   "auto-sense", &port,
		   NULL);
      
      g_value_init(&value,
		   G_TYPE_BOOLEAN);
      
      ags_port_safe_read(port,
			 &value);

      auto_sense = g_value_get_boolean(&value);

      g_value_unset(&value);

      g_object_unref(port);
      
      if(auto_sense){
	void *buffer;
	guint buffer_size;
	guint format;
	guint i;
	gboolean add_stream;

	buffer = source->stream_current->data;

	g_object_get(source,
		     "buffer-size", &buffer_size,
		     "format", &format,
		     NULL);
	
	add_stream = FALSE;
	
	for(i = buffer_size - 1; i > buffer_size / 2 && !add_stream; i--){
	  switch(format){
	  case AGS_SOUNDCARD_SIGNED_8_BIT:
	    {
	      if(((gint8 *) buffer)[i] != 0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  case AGS_SOUNDCARD_SIGNED_16_BIT:
	    {
	      if(((gint16 *) buffer)[i] != 0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  case AGS_SOUNDCARD_SIGNED_24_BIT:
	    {
	      if(((gint32 *) buffer)[i] != 0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  case AGS_SOUNDCARD_SIGNED_32_BIT:
	    {
	      if(((gint32 *) buffer)[i] != 0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  case AGS_SOUNDCARD_SIGNED_64_BIT:
	    {
	      if(((gint64 *) buffer)[i] != 0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  case AGS_SOUNDCARD_FLOAT:
	    {
	      if(((gfloat *) buffer)[i] != 0.0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  case AGS_SOUNDCARD_DOUBLE:
	    {
	      if(((gdouble *) buffer)[i] != 0.0){
		add_stream = TRUE;
	      }
	    }
	    break;
	  default:
	    g_critical("unsupported soundcard format");
	  }
	}
	
	if(add_stream){
	  ags_audio_signal_add_stream(source);
	}
      }

      g_value_unset(&value);
    }

    source->stream_current = source->stream_current->next;
      
    /* call parent */
    parent_class_run_post(recall);
  }else{
    /* call parent */
    parent_class_run_post(recall);

    ags_recall_done(recall);
  }

  g_object_unref(stream_recycling);

  g_object_unref(source);

  g_object_unref(stream_channel_run);

  g_object_unref(stream_channel);
}
Beispiel #10
0
void
ags_matrix_map_recall(AgsMachine *machine)
{
  AgsMatrix *matrix;

  AgsAudio *audio;
  AgsChannel *channel;
  AgsPattern *pattern;

  AgsDelayAudio *play_delay_audio;
  AgsDelayAudioRun *play_delay_audio_run;
  AgsCountBeatsAudio *play_count_beats_audio;
  AgsCountBeatsAudioRun *play_count_beats_audio_run;
  AgsCopyPatternAudio *recall_copy_pattern_audio;
  AgsCopyPatternAudioRun *recall_copy_pattern_audio_run;
  AgsPlayNotationAudio  *play_notation;
  AgsCopyPatternChannel *copy_pattern_channel;

  GList *notation;
  GList *list;

  guint i, j;

  GValue value = {0,};

  if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0 ||
     (AGS_MACHINE_PREMAPPED_RECALL & (machine->flags)) != 0){
    return;
  }

  audio = machine->audio;
  matrix = AGS_MATRIX(machine);

  /* ags-delay */
  ags_recall_factory_create(audio,
			    NULL, NULL,
			    "ags-delay\0",
			    0, 0,
			    0, 0,
			    (AGS_RECALL_FACTORY_OUTPUT |
			     AGS_RECALL_FACTORY_ADD |
			     AGS_RECALL_FACTORY_PLAY),
			    0);

  list = ags_recall_find_type(audio->play, AGS_TYPE_DELAY_AUDIO_RUN);

  if(list != NULL){
    play_delay_audio_run = AGS_DELAY_AUDIO_RUN(list->data);
    //    AGS_RECALL(play_delay_audio_run)->flags |= AGS_RECALL_PERSISTENT;
  }
  
  /* ags-count-beats */
  ags_recall_factory_create(audio,
			    NULL, NULL,
			    "ags-count-beats\0",
			    0, 0,
			    0, 0,
			    (AGS_RECALL_FACTORY_OUTPUT |
			     AGS_RECALL_FACTORY_ADD |
			     AGS_RECALL_FACTORY_PLAY),
			    0);
  
  list = ags_recall_find_type(audio->play, AGS_TYPE_COUNT_BEATS_AUDIO_RUN);

  if(list != NULL){
    play_count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(list->data);

    /* set dependency */  
    g_object_set(G_OBJECT(play_count_beats_audio_run),
		 "delay-audio-run\0", play_delay_audio_run,
		 NULL);
  }

  /* ags-copy-pattern */
  ags_recall_factory_create(audio,
			    NULL, NULL,
			    "ags-copy-pattern\0",
			    0, audio->audio_channels,
			    0, audio->input_lines,
			    (AGS_RECALL_FACTORY_INPUT |
			     AGS_RECALL_FACTORY_ADD |
			     AGS_RECALL_FACTORY_RECALL),
			    0);

  list = ags_recall_find_type(audio->recall, AGS_TYPE_COPY_PATTERN_AUDIO_RUN);

  if(list != NULL){
    recall_copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(list->data);

    /* set dependency */
    g_object_set(G_OBJECT(recall_copy_pattern_audio_run),
		 "delay-audio-run\0", play_delay_audio_run,
		 "count-beats-audio-run\0", play_count_beats_audio_run,
		 NULL);

  }

  /* set pattern object on port */
  channel = ags_channel_pad_nth(audio->input, 0);
      
  for(i = 0; i < audio->input_pads; i++){
    for(j = 0; j < audio->audio_channels; j++){
      list = ags_recall_template_find_type(channel->recall, AGS_TYPE_COPY_PATTERN_CHANNEL);
      copy_pattern_channel = AGS_COPY_PATTERN_CHANNEL(list->data);

      list = channel->pattern;
      pattern = AGS_PATTERN(list->data);

      copy_pattern_channel->pattern->port_value.ags_port_object = (GObject *) pattern;
	  
      ags_portlet_set_port(AGS_PORTLET(pattern), copy_pattern_channel->pattern);
	  
      channel = channel->next;
    }
  }

  /*  */
  list = audio->recall;

  while((list = ags_recall_find_type(list,
				     AGS_TYPE_PLAY_NOTATION_AUDIO)) != NULL){
    play_notation = AGS_PLAY_NOTATION_AUDIO(list->data);

    ags_port_safe_read(play_notation->notation,
		       &value);

    if(g_value_get_object(&value) == NULL){
      notation = audio->notation;
	
      while(notation != NULL){
	g_object_set(G_OBJECT(play_notation),
		     "notation\0", notation->data,
		     NULL);
	
	notation = notation->next;
      }
    }
	
    list = list->next;
  }


  /* depending on destination */
  ags_matrix_input_map_recall(matrix, 0);

  /* depending on destination */
  ags_matrix_output_map_recall(matrix, 0);

  AGS_MACHINE_CLASS(ags_matrix_parent_class)->map_recall(machine);
}
void
ags_recall_lv2_run_run_init_pre(AgsRecall *recall)
{
  AgsRecallLv2 *recall_lv2;
  AgsRecallChannelRun *recall_channel_run;
  AgsRecallRecycling *recall_recycling;
  AgsRecallLv2Run *recall_lv2_run;
  AgsAudioSignal *audio_signal;

  AgsLv2Plugin *lv2_plugin;
  
  AgsConfig *config;

  LV2_Handle *lv2_handle;
  
  float *output, *input;
  
  guint output_lines, input_lines;
  guint samplerate;
  guint buffer_size;
  guint port_count;
  guint i, i_stop;
  
  void (*parent_class_run_init_pre)(AgsRecall *recall);

  void (*connect_port)(LV2_Handle instance,
		       uint32_t port,
		       void *data_location);
  void (*activate)(LV2_Handle instance);
  
  pthread_mutex_t *recall_lv2_mutex;

  /* get recall mutex */
  pthread_mutex_lock(ags_recall_get_class_mutex());

  parent_class_run_init_pre = AGS_RECALL_CLASS(ags_recall_lv2_run_parent_class)->run_init_pre;
  
  pthread_mutex_unlock(ags_recall_get_class_mutex());

  /* call parent */
  parent_class_run_init_pre(recall);

  recall_lv2_run = AGS_RECALL_LV2_RUN(recall);

  g_object_get(recall,
	       "parent", &recall_recycling,
	       NULL);

  g_object_get(recall_recycling,
	       "parent", &recall_channel_run,
	       NULL);

  g_object_get(recall_channel_run,
	       "recall-channel", &recall_lv2,
	       NULL);

  /* set up buffer */
  g_object_get(recall_lv2_run,
	       "source", &audio_signal,
	       NULL);

  g_object_get(audio_signal,
	       "samplerate", &samplerate,
	       "buffer-size", &buffer_size,
	       NULL);
  
  /* get recall lv2 mutex */
  pthread_mutex_lock(ags_recall_get_class_mutex());
  
  recall_lv2_mutex = AGS_RECALL(recall_lv2)->obj_mutex;
  
  pthread_mutex_unlock(ags_recall_get_class_mutex());

  /* get some fields */
  pthread_mutex_lock(recall_lv2_mutex);

  lv2_plugin = recall_lv2->plugin;

  output_lines = recall_lv2->output_lines;
  input_lines = recall_lv2->input_lines;

  connect_port = recall_lv2->plugin_descriptor->connect_port;
  activate = recall_lv2->plugin_descriptor->activate;
  
  pthread_mutex_unlock(recall_lv2_mutex);
  
  /* set up buffer */
  input = NULL;
  output = NULL;
  
  if(input_lines > 0){
    input = (float *) malloc(input_lines *
			     buffer_size *
			     sizeof(float));
  }

  output = (float *) malloc(output_lines *
			    buffer_size *
			    sizeof(float));

  recall_lv2_run->output = output;
  recall_lv2_run->input = input;
  
  /* instantiate lv2 */  
  lv2_handle = (LV2_Handle *) ags_base_plugin_instantiate((AgsBasePlugin *) lv2_plugin,
							  samplerate, buffer_size);

  recall_lv2_run->lv2_handle = lv2_handle;
  
#ifdef AGS_DEBUG
  g_message("instantiate LV2 handle");
#endif

  ags_recall_lv2_run_load_ports(recall_lv2_run);

  /* can't be done in ags_recall_lv2_run_run_init_inter since possebility of overlapping buffers */
  pthread_mutex_lock(recall_lv2_mutex);

  /* connect audio port */
  for(i = 0; i < input_lines; i++){
#ifdef AGS_DEBUG
    g_message("connect in port: %d", recall_lv2->input_port[i]);
#endif
    
    connect_port(recall_lv2_run->lv2_handle[0],
		 recall_lv2->input_port[i],
		 recall_lv2_run->input);
  }

  for(i = 0; i < output_lines; i++){
#ifdef AGS_DEBUG
    g_message("connect out port: %d", recall_lv2->output_port[i]);
#endif
    
    connect_port(recall_lv2_run->lv2_handle[0],
		 recall_lv2->output_port[i],
		 recall_lv2_run->output);
  }

  /* connect event port */
  if(ags_recall_lv2_test_flags(recall_lv2, AGS_RECALL_LV2_HAS_EVENT_PORT)){
    recall_lv2_run->event_port = ags_lv2_plugin_alloc_event_buffer(AGS_RECALL_LV2_DEFAULT_MIDI_LENGHT);
    
    connect_port(recall_lv2_run->lv2_handle[0],
		 recall_lv2->event_port,
		 recall_lv2_run->event_port);
  }
  
  /* connect atom port */
  if(ags_recall_lv2_test_flags(recall_lv2, AGS_RECALL_LV2_HAS_ATOM_PORT)){
    recall_lv2_run->atom_port = ags_lv2_plugin_alloc_atom_sequence(AGS_RECALL_LV2_DEFAULT_MIDI_LENGHT);
    
    connect_port(recall_lv2_run->lv2_handle[0],
		 recall_lv2->atom_port,
		 recall_lv2_run->atom_port);   
  }
  
  /* activate */
  if(activate != NULL){
    activate(recall_lv2_run->lv2_handle[0]);
  }

  pthread_mutex_unlock(recall_lv2_mutex);

  /* set program */
  if(ags_lv2_plugin_test_flags(lv2_plugin, AGS_LV2_PLUGIN_HAS_PROGRAM_INTERFACE)){
    AgsPort *current_port;

    GList *plugin_port_start, *plugin_port;
    GList *port;
    GList *list;
    
    gchar *specifier, *current_specifier;

    float *port_data;

    guint bank, program;
    guint port_count;

    pthread_mutex_t *base_plugin_mutex;
    
    pthread_mutex_lock(recall_lv2_mutex);

    port = g_list_copy(AGS_RECALL(recall_lv2)->port);

    bank = recall_lv2->bank;
    program = recall_lv2->program;
    
    pthread_mutex_unlock(recall_lv2_mutex);

    /* get base plugin mutex */
    pthread_mutex_lock(ags_base_plugin_get_class_mutex());
  
    base_plugin_mutex = AGS_BASE_PLUGIN(lv2_plugin)->obj_mutex;
  
    pthread_mutex_unlock(ags_base_plugin_get_class_mutex());
    
    /* get plugin port */
    pthread_mutex_lock(base_plugin_mutex);

    plugin_port_start = g_list_copy(AGS_BASE_PLUGIN(lv2_plugin)->plugin_port);

    pthread_mutex_unlock(base_plugin_mutex);

    /* create port data */
    port_count = g_list_length(plugin_port_start);
    
    port_data = (float *) malloc(port_count * sizeof(float));

    plugin_port = plugin_port_start;
    
    for(i = 0; i < port_count && plugin_port != NULL; ){
      AgsPluginPort *current_plugin_port;

      pthread_mutex_t *plugin_port_mutex;

      current_plugin_port = AGS_PLUGIN_PORT(plugin_port->data);

      /* get plugin port mutex */
      pthread_mutex_lock(ags_plugin_port_get_class_mutex());
      
      plugin_port_mutex = current_plugin_port->obj_mutex;

      pthread_mutex_unlock(ags_plugin_port_get_class_mutex());

      /* get specifier */
      pthread_mutex_lock(plugin_port_mutex);

      specifier = g_strdup(current_plugin_port->port_name);
 	
      pthread_mutex_unlock(plugin_port_mutex);

      list = ags_port_find_specifier(port, specifier);

      if(list != NULL){
	GValue value = {0,};
	
	current_port = list->data;

	g_value_init(&value,
		     G_TYPE_FLOAT);

	ags_port_safe_read(current_port,
			   &value);
	port_data[i] = g_value_get_float(&value);

	g_value_unset(&value);
      }else{
	port_data[i] = 0.0;
      }

      g_free(specifier);

      /* iterate plugin port */
      plugin_port = plugin_port->next;
    }

    ags_lv2_plugin_change_program(lv2_plugin,
				  recall_lv2_run->lv2_handle[0],
				  bank,
				  program);

    /* reset port data */    
    plugin_port = plugin_port_start;

    for(i = 0; i < port_count && plugin_port != NULL;){
      AgsPluginPort *current_plugin_port;

      pthread_mutex_t *plugin_port_mutex;

      current_plugin_port = AGS_PLUGIN_PORT(plugin_port->data);

      /* get plugin port mutex */
      pthread_mutex_lock(ags_plugin_port_get_class_mutex());
      
      plugin_port_mutex = current_plugin_port->obj_mutex;

      pthread_mutex_unlock(ags_plugin_port_get_class_mutex());

      /* get specifier */
      pthread_mutex_lock(plugin_port_mutex);

      specifier = g_strdup(current_plugin_port->port_name);
 	
      pthread_mutex_unlock(plugin_port_mutex);

      list = ags_port_find_specifier(port, specifier);

      if(list != NULL){
	GValue value = {0,};
	
	current_port = list->data;

	g_value_init(&value,
		     G_TYPE_FLOAT);
	g_value_set_float(&value, port_data[i]);
	
	ags_port_safe_write_raw(current_port,
				&value);

	g_value_unset(&value);
      }
      
      /* iterate plugin port */
      plugin_port = plugin_port->next;
    }
    
    g_free(port_data);

    g_list_free(port);
    g_list_free(plugin_port_start);
  }

  g_object_unref(recall_recycling);

  g_object_unref(recall_channel_run);

  g_object_unref(recall_lv2);

  g_object_unref(audio_signal);
}