Пример #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));
}
void
ags_menu_bar_save_as_callback(GtkWidget *menu_item, AgsMenuBar *menu_bar)
{
  AgsWindow *window;
  GtkFileChooserDialog *file_chooser;
  gint response;

  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) menu_bar);

  file_chooser = (GtkFileChooserDialog *) gtk_file_chooser_dialog_new("save file as\0",
								      (GtkWindow *) window,
								      GTK_FILE_CHOOSER_ACTION_SAVE,
								      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
								      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
								      NULL);
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(file_chooser), FALSE);
  gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(file_chooser), TRUE);
  gtk_widget_show_all((GtkWidget *) file_chooser);

  response = gtk_dialog_run(GTK_DIALOG(file_chooser));

  if(response == GTK_RESPONSE_ACCEPT){
    AgsSaveFile *save_file;

    AgsThread *main_loop;
    AgsTaskThread *task_thread;

    AgsApplicationContext *application_context;

    AgsFile *file;
    char *filename;

    application_context = window->application_context;
    
    main_loop = application_context->main_loop;
    
    task_thread = ags_thread_find_type(main_loop,
				       AGS_TYPE_TASK_THREAD);

    filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
    window->name = filename;
    
    file = (AgsFile *) g_object_new(AGS_TYPE_FILE,
				    "application-context\0", application_context,
				    "filename\0", filename,
				    NULL);

    save_file = ags_save_file_new(file);
    ags_task_thread_append_task(task_thread,
				AGS_TASK(save_file));
  }

  gtk_widget_destroy((GtkWidget *) file_chooser);
}
void
ags_menu_bar_add_drum_callback(GtkWidget *menu_item, AgsMenuBar *menu_bar)
{
  AgsWindow *window;
  AgsDrum *drum;

  AgsAddAudio *add_audio;

  AgsThread *main_loop;
  AgsTaskThread *task_thread;

  AgsApplicationContext *application_context;

  window = (AgsWindow *) gtk_widget_get_ancestor((GtkWidget *) menu_bar, AGS_TYPE_WINDOW);

  application_context = window->application_context;
  
  main_loop = application_context->main_loop;
  task_thread = ags_thread_find_type(main_loop,
				     AGS_TYPE_TASK_THREAD);

  drum = ags_drum_new(G_OBJECT(window->soundcard));

  add_audio = ags_add_audio_new(window->soundcard,
				AGS_MACHINE(drum)->audio);
  ags_task_thread_append_task(task_thread,
			      AGS_TASK(add_audio));
  
  gtk_box_pack_start((GtkBox *) window->machines,
		     GTK_WIDGET(drum),
		     FALSE, FALSE, 0);

  /* connect everything */
  ags_connectable_connect(AGS_CONNECTABLE(drum));

  /* */
  gtk_widget_show_all(GTK_WIDGET(drum));

  /* */
  drum->machine.audio->audio_channels = 2;

  /* AgsDrumInputPad */
  ags_audio_set_pads(drum->machine.audio, AGS_TYPE_INPUT, 8);
  ags_audio_set_pads(drum->machine.audio, AGS_TYPE_OUTPUT, 1);

  ags_machine_find_port(AGS_MACHINE(drum));

  gtk_widget_show_all(drum->output_pad);
  gtk_widget_show_all(drum->input_pad);
}
Пример #4
0
void
ags_machine_popup_destroy_activate_callback(GtkWidget *widget, AgsMachine *machine)
{
  AgsWindow *window;
  AgsRemoveAudio *remove_audio;

  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);

  remove_audio = ags_remove_audio_new(window->devout,
				      machine->audio);
  ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(window->ags_main)->main_loop)->task_thread),
			      AGS_TASK(remove_audio));

  ags_connectable_disconnect(AGS_CONNECTABLE(machine));
  gtk_widget_destroy((GtkWidget *) machine);
}
Пример #5
0
void
ags_drum_length_spin_callback(GtkWidget *spin_button, AgsDrum *drum)
{
  AgsWindow *window;
  AgsApplySequencerLength *apply_sequencer_length;
  gdouble length;

  window = (AgsWindow *) gtk_widget_get_toplevel(GTK_WIDGET(drum));

  length = GTK_SPIN_BUTTON(spin_button)->adjustment->value;

  apply_sequencer_length = ags_apply_sequencer_length_new(G_OBJECT(AGS_MACHINE(drum)->audio),
							  length);

  ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(window->ags_main)->main_loop)->task_thread),
			      AGS_TASK(apply_sequencer_length));
}
void
ags_menu_bar_add_lv2_bridge_callback(GtkWidget *menu_item, AgsMenuBar *menu_bar)
{
  AgsWindow *window;
  AgsLv2Bridge *lv2_bridge;
  AgsAddAudio *add_audio;
  AgsThread *main_loop;
  AgsTaskThread *task_thread;
  AgsApplicationContext *application_context;

  window = (AgsWindow *) gtk_widget_get_ancestor((GtkWidget *) menu_bar, AGS_TYPE_WINDOW);

  application_context = window->application_context;
  
  main_loop = application_context->main_loop;
  task_thread = ags_thread_find_type(main_loop,
				     AGS_TYPE_TASK_THREAD);

  lv2_bridge = ags_lv2_bridge_new(G_OBJECT(window->soundcard),
				  g_object_get_data(menu_item,
						    AGS_MENU_BAR_LV2_FILENAME_KEY),
				  g_object_get_data(menu_item,
						    AGS_MENU_BAR_LV2_URI_KEY));
  
  add_audio = ags_add_audio_new(window->soundcard,
				AGS_MACHINE(lv2_bridge)->audio);
  ags_task_thread_append_task(task_thread,
			      AGS_TASK(add_audio));

  gtk_box_pack_start((GtkBox *) window->machines,
		     (GtkWidget *) lv2_bridge,
		     FALSE, FALSE, 0);
  ags_lv2_bridge_load(lv2_bridge);
  
  ags_connectable_connect(AGS_CONNECTABLE(lv2_bridge));

  //  lv2_bridge->machine.audio->frequence = ;
  lv2_bridge->machine.audio->audio_channels = 2;
  ags_audio_set_pads(AGS_MACHINE(lv2_bridge)->audio, AGS_TYPE_INPUT, 1);
  ags_audio_set_pads(AGS_MACHINE(lv2_bridge)->audio, AGS_TYPE_OUTPUT, 1);

  ags_machine_find_port(AGS_MACHINE(lv2_bridge));

  gtk_widget_show_all((GtkWidget *) lv2_bridge);
}
void
ags_menu_bar_add_panel_callback(GtkWidget *menu_item, AgsMenuBar *menu_bar)
{
  AgsWindow *window;
  AgsPanel *panel;
  AgsAddAudio *add_audio;
  AgsThread *main_loop;
  AgsTaskThread *task_thread;
  AgsApplicationContext *application_context;

  window = (AgsWindow *) gtk_widget_get_ancestor((GtkWidget *) menu_bar, AGS_TYPE_WINDOW);

  application_context = window->application_context;
  
  main_loop = application_context->main_loop;
  task_thread = ags_thread_find_type(main_loop,
				     AGS_TYPE_TASK_THREAD);

  panel = ags_panel_new(G_OBJECT(window->soundcard));

  add_audio = ags_add_audio_new(window->soundcard,
				AGS_MACHINE(panel)->audio);
  ags_task_thread_append_task(task_thread,
			      AGS_TASK(add_audio));

  gtk_box_pack_start((GtkBox *) window->machines,
		     GTK_WIDGET(panel),
		     FALSE, FALSE, 0);

  ags_connectable_connect(AGS_CONNECTABLE(panel));

  gtk_widget_show_all(GTK_WIDGET(panel));

  AGS_MACHINE(panel)->audio->audio_channels = 2;
  ags_audio_set_pads(AGS_MACHINE(panel)->audio,
		     AGS_TYPE_INPUT, 1);
  ags_audio_set_pads(AGS_MACHINE(panel)->audio,
		     AGS_TYPE_OUTPUT, 1);

  ags_machine_find_port(AGS_MACHINE(panel));

  gtk_widget_show_all(panel->vbox);
}
void
ags_menu_bar_add_ffplayer_callback(GtkWidget *menu_item, AgsMenuBar *menu_bar)
{
  AgsWindow *window;
  AgsFFPlayer *ffplayer;
  AgsAddAudio *add_audio;
  AgsThread *main_loop;
  AgsTaskThread *task_thread;
  AgsApplicationContext *application_context;

  window = (AgsWindow *) gtk_widget_get_ancestor((GtkWidget *) menu_bar, AGS_TYPE_WINDOW);

  application_context = window->application_context;
  
  main_loop = application_context->main_loop;
  task_thread = ags_thread_find_type(main_loop,
				     AGS_TYPE_TASK_THREAD);

  ffplayer = ags_ffplayer_new(G_OBJECT(window->soundcard));

  add_audio = ags_add_audio_new(window->soundcard,
				AGS_MACHINE(ffplayer)->audio);
  ags_task_thread_append_task(task_thread,
			      AGS_TASK(add_audio));

  gtk_box_pack_start((GtkBox *) window->machines,
		     (GtkWidget *) ffplayer,
		     FALSE, FALSE, 0);

  ags_connectable_connect(AGS_CONNECTABLE(ffplayer));

  //  ffplayer->machine.audio->frequence = ;
  ffplayer->machine.audio->audio_channels = 2;
  ags_audio_set_pads(AGS_MACHINE(ffplayer)->audio, AGS_TYPE_INPUT, 78);
  ags_audio_set_pads(AGS_MACHINE(ffplayer)->audio, AGS_TYPE_OUTPUT, 1);

  ags_machine_find_port(AGS_MACHINE(ffplayer));

  gtk_widget_show_all((GtkWidget *) ffplayer);
}
gboolean
ags_window_delete_event_callback(GtkWidget *widget, gpointer data)
{
    AgsWindow *window;
    GtkDialog *dialog;
    GtkWidget *cancel_button;

    AgsApplicationContext *application_context;

    gint response;

    window = AGS_WINDOW(widget);

    application_context = window->application_context;

    /* ask the user if he wants save to a file */
    dialog = (GtkDialog *) gtk_message_dialog_new(GTK_WINDOW(window),
             GTK_DIALOG_DESTROY_WITH_PARENT,
             GTK_MESSAGE_QUESTION,
             GTK_BUTTONS_YES_NO,
             "Do you want to save '%s'?\0", window->name);
    cancel_button = gtk_dialog_add_button(dialog,
                                          GTK_STOCK_CANCEL,
                                          GTK_RESPONSE_CANCEL);
    gtk_widget_grab_focus(cancel_button);

    response = gtk_dialog_run(dialog);

    if(response == GTK_RESPONSE_YES) {
        AgsThread *main_loop;
        AgsTaskThread *task_thread;
        AgsSaveFile *save_file;

        AgsFile *file;

        char *filename;

        main_loop = application_context->main_loop;

        task_thread = ags_thread_find_type(main_loop,
                                           AGS_TYPE_TASK_THREAD);

        filename = window->name;

        file = (AgsFile *) g_object_new(AGS_TYPE_FILE,
                                        "application-context\0", application_context,
                                        "filename\0", g_strdup(filename),
                                        NULL);

        save_file = ags_save_file_new(file);
        ags_task_thread_append_task(task_thread,
                                    AGS_TASK(save_file));

        g_object_unref(G_OBJECT(file));
    }

    if(response != GTK_RESPONSE_CANCEL) {
        ags_main_quit(application_context);
    } else {
        gtk_widget_destroy(GTK_WIDGET(dialog));
    }

    return(TRUE);
}
Пример #10
0
void
ags_drum_run_callback(GtkWidget *toggle_button, AgsDrum *drum)
{
  AgsDevout *devout;
  AgsAudioLoop *audio_loop;
  AgsTaskThread *task_thread;
  AgsDevoutThread *devout_thread;

  devout = AGS_DEVOUT(AGS_MACHINE(drum)->audio->devout);

  audio_loop = AGS_AUDIO_LOOP(AGS_MAIN(devout->ags_main)->main_loop);
  task_thread = AGS_TASK_THREAD(audio_loop->task_thread);
  devout_thread = AGS_DEVOUT_THREAD(audio_loop->devout_thread);

  if(GTK_TOGGLE_BUTTON(toggle_button)->active){
    AgsInitAudio *init_audio;
    AgsAppendAudio *append_audio;
    AgsStartDevout *start_devout;
    GList *tasks;

    printf("drum: on\n\0");

    tasks = NULL;

    /* create init task */
    init_audio = ags_init_audio_new(AGS_MACHINE(drum)->audio,
				    FALSE, TRUE, FALSE);
    g_signal_connect_after(init_audio, "launch\0",
			   G_CALLBACK(ags_drum_init_audio_launch_callback), drum);

    tasks = g_list_prepend(tasks,
			   init_audio);

    /* create append task */
    append_audio = ags_append_audio_new(G_OBJECT(audio_loop),
					G_OBJECT(AGS_MACHINE(drum)->audio));

    tasks = g_list_prepend(tasks,
			   append_audio);

    /* create start task */
    start_devout = ags_start_devout_new(devout);

    tasks = g_list_prepend(tasks,
			   start_devout);

    /* append tasks */
    tasks = g_list_reverse(tasks);
    
    ags_task_thread_append_tasks(task_thread,
				 tasks);
  }else{
    printf("drum: off\n\0");

    /* abort code */
    if(ags_audio_is_playing(AGS_MACHINE(drum)->audio)){
      AgsCancelAudio *cancel_audio;

      /* create cancel task */
      cancel_audio = ags_cancel_audio_new(AGS_MACHINE(drum)->audio,
					  FALSE, TRUE, FALSE);

      /* append AgsCancelAudio */
      ags_task_thread_append_task(task_thread,
				  AGS_TASK(cancel_audio));
    }
  }
}
Пример #11
0
void
ags_export_window_export_callback(GtkWidget *toggle_button,
				  AgsExportWindow *export_window)
{
  AgsAudioLoop *audio_loop;
  AgsWindow *window;
  AgsMachine *machine;
  GList *machines_start;
  gboolean success;

  window = AGS_MAIN(export_window->ags_main)->window;
  audio_loop = AGS_AUDIO_LOOP(AGS_MAIN(window->ags_main)->main_loop);
  
  machines_start = NULL;

  if(gtk_toggle_button_get_active(toggle_button)){
    AgsExportOutput *export_output;
    AgsExportThread *export_thread;
    GList *machines;
    gchar *filename;
    gboolean live_performance;

    export_thread = audio_loop->export_thread;

    filename = gtk_entry_get_text(export_window->filename);

    if(filename == NULL ||
       strlen(filename) == 0){
      return;
    }

    live_performance = gtk_toggle_button_get_active(export_window->live_export);

    machines_start = 
      machines = gtk_container_get_children(GTK_CONTAINER(window->machines));

    success = FALSE;

    while(machines != NULL){
      machine = AGS_MACHINE(machines->data);

      if((AGS_MACHINE_IS_SEQUENCER & (machine->flags)) != 0 ||
	 (AGS_MACHINE_IS_SYNTHESIZER & (machine->flags)) != 0){
	printf("found machine to play!\n\0");

	ags_machine_set_run(machine,
			    TRUE);
	success = TRUE;
      }

      machines = machines->next;
    }

    /* create start task */
    if(success){
      guint tic;
      gdouble delay;

      delay = (1.0 / window->devout->frequency / window->devout->buffer_size) * (60.0 / AGS_DEVOUT_DEFAULT_BPM);

      tic = (gtk_spin_button_get_value(export_window->tact) + 1) * delay;

      export_output = ags_export_output_new(export_thread,
					    window->devout,
					    filename,
					    tic,
					    live_performance);
      g_signal_connect(export_thread, "stop\0",
		       G_CALLBACK(ags_export_window_stop_callback), export_window);

      /* append AgsStartDevout */
      ags_task_thread_append_task(AGS_TASK_THREAD(audio_loop->task_thread),
				  export_output);

      ags_navigation_set_seeking_sensitive(window->navigation,
					   FALSE);
    }
  }else{
    GList *machines;

    machines_start = 
      machines = gtk_container_get_children(GTK_CONTAINER(window->machines));

    while(machines != NULL){
      machine = AGS_MACHINE(machines->data);

      if((AGS_MACHINE_IS_SEQUENCER & (machine->flags)) !=0 ||
	 (AGS_MACHINE_IS_SYNTHESIZER & (machine->flags)) != 0){
	printf("found machine to stop!\n\0");
    
	ags_machine_set_run(machine,
			    FALSE);
	
	success = TRUE;
      }

      machines = machines->next;
    }

    if(success){
      ags_navigation_set_seeking_sensitive(window->navigation,
					   TRUE);
    }
  }

  g_list_free(machines_start);
}
Пример #12
0
void
ags_test_launch_filename(gchar *filename,
			 gboolean single_thread)
{
  AgsThread *audio_loop, *polling_thread, *gui_thread, *task_thread;
  AgsThreadPool *thread_pool;

  AgsConfig *config;

  GList *start_queue;  
    
  /* get threads, thread pool and config */
  g_object_get(ags_application_context,
	       "config", &config,
	       "main-loop", &audio_loop,
	       "task-thread", &task_thread,
	       NULL);

  g_object_get(task_thread,
	       "thread-pool", &thread_pool,
	       NULL);

  polling_thread = ags_thread_find_type(audio_loop,
					AGS_TYPE_POLLING_THREAD);
  gui_thread = ags_thread_find_type(audio_loop,
				    AGS_TYPE_GUI_THREAD);

  /* open file */
  if(g_strcmp0(ags_config_get_value(config,
				    AGS_CONFIG_GENERIC,
				    "simple-file\0"),
		 "false\0")){
    AgsSimpleFile *simple_file;

    AgsSimpleFileRead *simple_file_read;
      
    GError *error;

    simple_file = (AgsSimpleFile *) g_object_new(AGS_TYPE_SIMPLE_FILE,
						 "application-context\0", ags_application_context,
						 "filename\0", filename,
						 NULL);
    error = NULL;
    ags_simple_file_open(simple_file,
			 &error);

    if(error != NULL){
      ags_test_show_file_error(filename,
			       error);
      ags_application_context_quit(ags_application_context);
    }
    
    /* start engine */  
    pthread_mutex_lock(audio_loop->start_mutex);
    
    start_queue = NULL;
    start_queue = g_list_prepend(start_queue,
				 polling_thread);
    start_queue = g_list_prepend(start_queue,
				 task_thread);
    //    start_queue = g_list_prepend(start_queue,
    //				 gui_thread);
    g_atomic_pointer_set(&(audio_loop->start_queue),
			 start_queue);
  
    pthread_mutex_unlock(audio_loop->start_mutex);

    /* start audio loop and thread pool */
    ags_thread_start(audio_loop);

    ags_thread_pool_start(thread_pool);

    if(!single_thread){
      /* wait for audio loop */
      pthread_mutex_lock(audio_loop->start_mutex);

      if(g_atomic_int_get(&(audio_loop->start_wait)) == TRUE){	
	g_atomic_int_set(&(audio_loop->start_done),
			 FALSE);
      
	while(g_atomic_int_get(&(audio_loop->start_wait)) == TRUE &&
	      g_atomic_int_get(&(audio_loop->start_done)) == FALSE){
	  pthread_cond_wait(audio_loop->start_cond,
			    audio_loop->start_mutex);
	}
      }
    
      pthread_mutex_unlock(audio_loop->start_mutex);

      /* start gui thread */
      ags_thread_start(gui_thread);

      /* wait for gui thread */
      pthread_mutex_lock(gui_thread->start_mutex);

      if(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
      
      	g_atomic_int_set(&(gui_thread->start_wait),
      			 TRUE);

    	while(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
    	  g_atomic_int_set(&(gui_thread->start_wait),
    			   TRUE);
	
    	  pthread_cond_wait(gui_thread->start_cond,
    			    gui_thread->start_mutex);
    	}
      }
    
      pthread_mutex_unlock(gui_thread->start_mutex);     
      
      /* autosave thread */
      if(!g_strcmp0(ags_config_get_value(config,
					 AGS_CONFIG_GENERIC,
					 "autosave-thread\0"),
		    "true\0")){
	pthread_mutex_lock(audio_loop->start_mutex);

	start_queue = g_atomic_pointer_get(&(audio_loop->start_queue));
	start_queue = g_list_prepend(start_queue,
				     task_thread);

	g_atomic_pointer_set(&(audio_loop->start_queue),
			     start_queue);
	
	pthread_mutex_unlock(audio_loop->start_mutex);
      }
    
      /* now start read task */
      simple_file_read = ags_simple_file_read_new(simple_file);
      ags_task_thread_append_task((AgsTaskThread *) task_thread,
				  (AgsTask *) simple_file_read);      
    }else{
      AgsFile *file;

      GError *error;
    
      file = g_object_new(AGS_TYPE_FILE,
			  "application-context\0", ags_application_context,
			  "filename\0", filename,
			  NULL);
      error = NULL;
      ags_file_open(file,
		    &error);

      if(error != NULL){
	ags_test_show_file_error(filename,
				 error);
	
	ags_application_context_quit(ags_application_context);
      }
    
      ags_file_read(file);
      ags_file_close(file);
    }
  }
}
Пример #13
0
void
ags_link_editor_apply(AgsApplicable *applicable)
{
  AgsLinkEditor *link_editor;
  GtkTreeIter iter;

  link_editor = AGS_LINK_EDITOR(applicable);

  if(gtk_combo_box_get_active_iter(link_editor->combo,
				   &iter)){
    AgsWindow *window;
    AgsMachine *link_machine;
    AgsMachineEditor *machine_editor;
    AgsLineEditor *line_editor;
    GtkTreeModel *model;

    AgsChannel *channel, *link;
    AgsLinkChannel *link_channel;

    AgsThread *main_loop, *current;
    AgsTaskThread *task_thread;

    AgsApplicationContext *application_context;
    
    line_editor = AGS_LINE_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(link_editor),
							  AGS_TYPE_LINE_EDITOR));

    machine_editor = gtk_widget_get_ancestor(line_editor,
					     AGS_TYPE_MACHINE_EDITOR);

    window = machine_editor->parent;
      
    application_context = window->application_context;

    channel = line_editor->channel;

    main_loop = application_context->main_loop;
    task_thread = ags_thread_find_type(main_loop,
				       AGS_TYPE_TASK_THREAD);

    model = gtk_combo_box_get_model(link_editor->combo);
    gtk_tree_model_get(model,
		       &iter,
		       1, &link_machine,
		       -1);
    
    if(link_machine == NULL){
      /* create task */
      link_channel = ags_link_channel_new(channel, NULL);
      
      /* append AgsLinkChannel */
      ags_task_thread_append_task(task_thread,
				  AGS_TASK(link_channel));
    }else{
      guint link_line;

      link_line = (guint) gtk_spin_button_get_value_as_int(link_editor->spin_button);

      if(AGS_IS_INPUT(channel))
	link = ags_channel_nth(link_machine->audio->output,
			       link_line);
      else
	link = ags_channel_nth(link_machine->audio->input,
			       link_line);

      /* create task */
      link_channel = ags_link_channel_new(channel, link);
      
      /* append AgsLinkChannel */
      ags_task_thread_append_task(task_thread,
				  AGS_TASK(link_channel));
    }
  }
}