xmlNode*
ags_xorg_application_context_write(AgsFile *file, xmlNode *parent, GObject *application_context)
{
    xmlNode *node, *child;
    gchar *id;

    id = ags_id_generator_create_uuid();

    node = xmlNewNode(NULL,
                      "ags-application-context\0");

    ags_file_add_id_ref(file,
                        g_object_new(AGS_TYPE_FILE_ID_REF,
                                     "application-context\0", file->application_context,
                                     "file\0", file,
                                     "node\0", node,
                                     "xpath\0", g_strdup_printf("xpath=//*[@id='%s']\0", id),
                                     "reference\0", application_context,
                                     NULL));

    xmlNewProp(node,
               AGS_FILE_CONTEXT_PROP,
               "xorg\0");

    xmlNewProp(node,
               AGS_FILE_ID_PROP,
               id);

    xmlNewProp(node,
               AGS_FILE_FLAGS_PROP,
               g_strdup_printf("%x\0", ((~AGS_APPLICATION_CONTEXT_CONNECTED) & (AGS_APPLICATION_CONTEXT(application_context)->flags))));

    xmlNewProp(node,
               AGS_FILE_VERSION_PROP,
               AGS_APPLICATION_CONTEXT(application_context)->version);

    xmlNewProp(node,
               AGS_FILE_BUILD_ID_PROP,
               AGS_APPLICATION_CONTEXT(application_context)->build_id);

    /* add to parent */
    xmlAddChild(parent,
                node);

    ags_file_write_window(file,
                          node,
                          AGS_XORG_APPLICATION_CONTEXT(application_context)->window);

    return(node);
}
void
ags_application_context_connect(AgsConnectable *connectable)
{
  AgsApplicationContext *application_context;

  application_context = AGS_APPLICATION_CONTEXT(connectable);

  if((AGS_APPLICATION_CONTEXT_CONNECTED & (application_context->flags)) != 0)
    return;

  application_context->flags |= AGS_APPLICATION_CONTEXT_CONNECTED;

  if((AGS_APPLICATION_CONTEXT_DEFAULT & (application_context->flags)) != 0){
    GList *list;

    list = application_context->sibling;

    while(list != NULL){
      if(application_context != list->data){
	ags_connectable_connect(AGS_CONNECTABLE(list->data));
      }

      list = list->next;
    }
  }

  /* note main loop won't connect here */
}
void
ags_application_context_get_property(GObject *gobject,
				     guint prop_id,
				     GValue *value,
				     GParamSpec *param_spec)
{
  AgsApplicationContext *application_context;

  application_context = AGS_APPLICATION_CONTEXT(gobject);

  switch(prop_id){
  case PROP_CONFIG:
    {
      g_value_set_object(value, application_context->config);
    }
    break;
  case PROP_MAIN_LOOP:
    {
      g_value_set_object(value, application_context->main_loop);
    }
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
    break;
  }
}
void
ags_application_context_finalize(GObject *gobject)
{
  AgsApplicationContext *application_context;

  G_OBJECT_CLASS(ags_application_context_parent_class)->finalize(gobject);

  application_context = AGS_APPLICATION_CONTEXT(gobject);

  //TODO:JK: implement me
}
void
ags_application_context_set_property(GObject *gobject,
				     guint prop_id,
				     const GValue *value,
				     GParamSpec *param_spec)
{
  AgsApplicationContext *application_context;

  application_context = AGS_APPLICATION_CONTEXT(gobject);

  switch(prop_id){
  case PROP_CONFIG:
    {
      AgsConfig *config;
      
      config = (AgsApplicationContext *) g_value_get_object(value);

      if(config == application_context->config)
	return;

      if(application_context->config != NULL)
	g_object_unref(application_context->config);

      if(config != NULL)
	g_object_ref(G_OBJECT(config));

      application_context->config = (GObject *) config;
    }
    break;
  case PROP_MAIN_LOOP:
    {
      GObject *main_loop;
      
      main_loop = (GObject *) g_value_get_object(value);

      if(main_loop == application_context->main_loop)
	return;

      if(application_context->main_loop != NULL)
	g_object_unref(application_context->main_loop);

      if(main_loop != NULL)
	g_object_ref(G_OBJECT(main_loop));

      application_context->main_loop = main_loop;
    }
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
    break;
  }
  
}
void
ags_xorg_application_context_disconnect(AgsConnectable *connectable)
{
    AgsXorgApplicationContext *xorg_application_context;

    xorg_application_context = AGS_XORG_APPLICATION_CONTEXT(connectable);

    if((AGS_APPLICATION_CONTEXT_CONNECTED & (AGS_APPLICATION_CONTEXT(xorg_application_context)->flags)) == 0) {
        return;
    }

    ags_xorg_application_context_parent_connectable_interface->disconnect(connectable);
}
GList*
ags_application_context_find_main_loop(GList *application_context)
{
  while(application_context != NULL){
    if(AGS_APPLICATION_CONTEXT(application_context->data)->main_loop != NULL){
      break;
    }
    
    application_context = application_context->next;
  }
  
  return(application_context);
}
AgsApplicationContext*
ags_application_context_find_default(GList *application_context)
{
  while(application_context != NULL){
    if((AGS_APPLICATION_CONTEXT_DEFAULT & (AGS_APPLICATION_CONTEXT(application_context->data)->flags)) != 0){
      return(application_context->data);
    }
    
    application_context = application_context->next;
  }

  return(NULL);
}
void
ags_xorg_application_context_connect(AgsConnectable *connectable)
{
    AgsXorgApplicationContext *xorg_application_context;

    xorg_application_context = AGS_XORG_APPLICATION_CONTEXT(connectable);

    if((AGS_APPLICATION_CONTEXT_CONNECTED & (AGS_APPLICATION_CONTEXT(xorg_application_context)->flags)) != 0) {
        return;
    }

    ags_xorg_application_context_parent_connectable_interface->connect(connectable);

    g_message("connecting gui\0");

    ags_connectable_connect(AGS_CONNECTABLE(xorg_application_context->window));
}
void
ags_menu_action_save_callback(GtkWidget *menu_item, gpointer data)
{
  AgsApplicationContext *application_context;
  AgsWindow *window;
  
  GError *error;

  application_context = ags_application_context_get_instance();
  window = (AgsWindow *) ags_ui_provider_get_window(AGS_UI_PROVIDER(application_context));

  if(g_strcmp0(ags_config_get_value(AGS_APPLICATION_CONTEXT(application_context)->config,
				    AGS_CONFIG_GENERIC,
				    "simple-file"),
	       "false")){
    AgsSimpleFile *simple_file;

    simple_file = (AgsSimpleFile *) g_object_new(AGS_TYPE_SIMPLE_FILE,
						 "application-context", application_context,
						 "filename", window->name,
						 NULL);
      
    error = NULL;
    ags_simple_file_rw_open(simple_file,
			    TRUE,
			    &error);
    ags_simple_file_write(simple_file);
    ags_simple_file_close(simple_file);
    g_object_unref(G_OBJECT(simple_file));
  }else{
    AgsFile *file;

    file = (AgsFile *) g_object_new(AGS_TYPE_FILE,
				    "application-context", application_context,
				    "filename", window->name,
				    NULL);
      
    error = NULL;
    ags_file_rw_open(file,
		     TRUE,
		     &error);
    ags_file_write(file);
    ags_file_close(file);
    g_object_unref(G_OBJECT(file));
  }
}
void
ags_menu_action_quit_callback(GtkWidget *menu_item, gpointer data)
{
  AgsApplicationContext *application_context;
  AgsWindow *window;
  GtkDialog *dialog;
  GtkWidget *cancel_button;
  gint response;

  application_context = ags_application_context_get_instance();
  window = (AgsWindow *) ags_ui_provider_get_window(AGS_UI_PROVIDER(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'?", 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){
    AgsFile *file;

    //TODO:JK: revise me
    file = (AgsFile *) g_object_new(AGS_TYPE_FILE,
				    "application-context", application_context,
				    "filename", window->name,
				    NULL);

    ags_file_write(file);
    g_object_unref(G_OBJECT(file));
  }

  if(response != GTK_RESPONSE_CANCEL){
    ags_application_context_quit(AGS_APPLICATION_CONTEXT(application_context));
  }else{
    gtk_widget_destroy(GTK_WIDGET(dialog));
  }
}
void
ags_xorg_application_context_read(AgsFile *file, xmlNode *node, GObject **application_context)
{
    AgsXorgApplicationContext *gobject;
    GList *list;
    xmlNode *child;

    if(*application_context == NULL) {
        gobject = g_object_new(AGS_TYPE_XORG_APPLICATION_CONTEXT,
                               NULL);

        *application_context = (GObject *) gobject;
    } else {
        gobject = (AgsApplicationContext *) *application_context;
    }

    file->application_context = gobject;

    g_object_set(G_OBJECT(file),
                 "application-context\0", gobject,
                 NULL);

    ags_file_add_id_ref(file,
                        g_object_new(AGS_TYPE_FILE_ID_REF,
                                     "application-context\0", file->application_context,
                                     "file\0", file,
                                     "node\0", node,
                                     "xpath\0", g_strdup_printf("xpath=//*[@id='%s']\0", xmlGetProp(node, AGS_FILE_ID_PROP)),
                                     "reference\0", gobject,
                                     NULL));

    /* properties */
    AGS_APPLICATION_CONTEXT(gobject)->flags = (guint) g_ascii_strtoull(xmlGetProp(node, AGS_FILE_FLAGS_PROP),
            NULL,
            16);

    AGS_APPLICATION_CONTEXT(gobject)->version = xmlGetProp(node,
            AGS_FILE_VERSION_PROP);

    AGS_APPLICATION_CONTEXT(gobject)->build_id = xmlGetProp(node,
            AGS_FILE_BUILD_ID_PROP);

    //TODO:JK: check version compatibelity

    /* child elements */
    child = node->children;

    while(child != NULL) {
        if(child->type == XML_ELEMENT_NODE) {
            if(!xmlStrncmp("ags-window\0",
                           child->name,
                           11)) {
                ags_file_read_window(file,
                                     child,
                                     &(gobject->window));
            }
        }

        child = child->next;
    }
}
AgsThread*
ags_xorg_application_context_get_task_thread(AgsConcurrencyProvider *concurrency_provider)
{
    return(AGS_APPLICATION_CONTEXT(concurrency_provider)->task_thread);
}
AgsThread*
ags_xorg_application_context_get_main_loop(AgsConcurrencyProvider *concurrency_provider)
{
    return(AGS_APPLICATION_CONTEXT(concurrency_provider)->main_loop);
}
void
ags_xorg_application_context_init(AgsXorgApplicationContext *xorg_application_context)
{
    AgsWindow *window;

    AgsServer *server;

    AgsAudioLoop *audio_loop;
    GObject *soundcard;

    AgsConfig *config;

    struct passwd *pw;
    uid_t uid;
    gchar *wdir, *config_file;

    AGS_APPLICATION_CONTEXT(xorg_application_context)->log = (AgsLog *) g_object_new(AGS_TYPE_LOG,
            "file\0", stderr,
            NULL);

    /**/
    config = ags_config_new(NULL);
    AGS_APPLICATION_CONTEXT(xorg_application_context)->config = config;
    g_object_set(config,
                 "application-context\0", xorg_application_context,
                 NULL);

    uid = getuid();
    pw = getpwuid(uid);

    wdir = g_strdup_printf("%s/%s\0",
                           pw->pw_dir,
                           AGS_DEFAULT_DIRECTORY);

    config_file = g_strdup_printf("%s/%s\0",
                                  wdir,
                                  AGS_DEFAULT_CONFIG);

    ags_config_load_from_file(config,
                              config_file);

    g_free(wdir);
    g_free(config_file);

    /* AgsSoundcard */
    soundcard = ags_devout_new(xorg_application_context);
    xorg_application_context->soundcard = g_list_prepend(xorg_application_context->soundcard,
                                          soundcard);
    g_object_ref(G_OBJECT(soundcard));

    /* AgsWindow */
    window = ags_window_new(xorg_application_context);
    g_object_set(window,
                 "soundcard\0", soundcard,
                 NULL);
    AGS_XORG_APPLICATION_CONTEXT(xorg_application_context)->window = window;
    g_object_ref(G_OBJECT(window));

    gtk_window_set_default_size((GtkWindow *) window, 500, 500);
    gtk_paned_set_position((GtkPaned *) window->paned, 300);

    ags_connectable_connect(AGS_CONNECTABLE(window));
    gtk_widget_show_all((GtkWidget *) window);

    /* AgsServer */
    xorg_application_context->server = ags_server_new(xorg_application_context);

    /* AgsMainLoop */
    audio_loop = (AgsThread *) ags_audio_loop_new((GObject *) soundcard,
                 xorg_application_context);
    g_object_set(xorg_application_context,
                 "main-loop\0", audio_loop,
                 NULL);

    g_object_ref(audio_loop);
    ags_connectable_connect(AGS_CONNECTABLE(audio_loop));

    /* AgsTaskThread */
    AGS_APPLICATION_CONTEXT(xorg_application_context)->task_thread = (AgsThread *) ags_task_thread_new();
    ags_thread_add_child(AGS_THREAD(audio_loop), AGS_APPLICATION_CONTEXT(xorg_application_context)->task_thread);

    /* AgsSoundcardThread */
    xorg_application_context->soundcard_thread = (AgsThread *) ags_soundcard_thread_new(soundcard);
    ags_thread_add_child(AGS_THREAD(audio_loop), xorg_application_context->soundcard_thread);

    /* AgsExportThread */
    xorg_application_context->export_thread = (AgsThread *) ags_export_thread_new(soundcard,
            NULL);
    ags_thread_add_child(AGS_THREAD(audio_loop), xorg_application_context->export_thread);

    /* AgsGuiThread */
    xorg_application_context->gui_thread = (AgsThread *) ags_gui_thread_new();
    ags_thread_add_child(AGS_THREAD(audio_loop), xorg_application_context->gui_thread);

    /* AgsThreadPool */
    AGS_XORG_APPLICATION_CONTEXT(xorg_application_context)->thread_pool = ags_thread_pool_new(AGS_APPLICATION_CONTEXT(xorg_application_context)->task_thread);
}
void
ags_menu_action_save_as_callback(GtkWidget *menu_item, gpointer data)
{
  AgsApplicationContext *application_context;
  AgsWindow *window;
  GtkFileChooserDialog *file_chooser;
  
  gint response;
        
  application_context = ags_application_context_get_instance();
  window = (AgsWindow *) ags_ui_provider_get_window(AGS_UI_PROVIDER(application_context));

  file_chooser = (GtkFileChooserDialog *) gtk_file_chooser_dialog_new("save file as",
								      (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){
    gchar *filename;
    gchar *str;
    
    GError *error;
    
    filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
    
    if(g_strcmp0(ags_config_get_value(AGS_APPLICATION_CONTEXT(application_context)->config,
				      AGS_CONFIG_GENERIC,
				      "simple-file"),
		 "false")){
      AgsSimpleFile *simple_file;

      simple_file = (AgsSimpleFile *) g_object_new(AGS_TYPE_SIMPLE_FILE,
						   "application-context", application_context,
						   "filename", filename,
						   NULL);
      
      error = NULL;
      ags_simple_file_rw_open(simple_file,
			      TRUE,
			      &error);
      ags_simple_file_write(simple_file);
      ags_simple_file_close(simple_file);
      g_object_unref(G_OBJECT(simple_file));
    }else{
      AgsFile *file;

      file = (AgsFile *) g_object_new(AGS_TYPE_FILE,
				      "application-context", application_context,
				      "filename", filename,
				      NULL);
      
      error = NULL;
      ags_file_rw_open(file,
		       TRUE,
		       &error);
      ags_file_write(file);
      ags_file_close(file);
      g_object_unref(G_OBJECT(file));
    }

    if(window->name != NULL){
      g_free(window->name);
    }
    
    window->name = g_strdup(filename);

    str = g_strconcat("GSequencer - ", window->name, NULL);
    gtk_window_set_title((GtkWindow *) window, str);

    g_free(str);
  }

  gtk_widget_destroy((GtkWidget *) file_chooser);
}