Skip to content
sj-main.c 26.2 KiB
Newer Older
/* 
 * Copyright (C) 2003 Ross Burton <ross@burtonini.com>
 *
 * Sound Juicer - sj-main.c
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Authors: Ross Burton <ross@burtonini.com>
 */

#include "sound-juicer.h"

Ross Burton's avatar
Ross Burton committed
#include <string.h>
Ross Burton's avatar
Ross Burton committed
#include <unistd.h>
Ross Burton's avatar
Ross Burton committed
#include <gtk/gtk.h>
Ross Burton's avatar
Ross Burton committed
#include <gconf/gconf-client.h>
#include "sj-about.h"
Ross Burton's avatar
Ross Burton committed
#include "sj-musicbrainz.h"
#include "sj-extractor.h"
Ross Burton's avatar
Ross Burton committed
#include "sj-structures.h"
Ross Burton's avatar
Ross Burton committed
#include "sj-error.h"
Ross Burton's avatar
Ross Burton committed
#include "sj-util.h"
#include "sj-prefs.h"
Ross Burton's avatar
Ross Burton committed

GladeXML *glade;

SjExtractor *extractor;
Ross Burton's avatar
Ross Burton committed

GConfClient *gconf_client;
Ross Burton's avatar
Ross Burton committed

GtkWidget *main_window;
static GtkWidget *title_label, *artist_label, *duration_label;
static GtkWidget *track_listview, *reread_button, *extract_button;
static GtkWidget *extract_menuitem, *select_all_menuitem, *deselect_all_menuitem;
GtkListStore *track_store;
const char *base_path, *path_pattern, *file_pattern;
static const char *device;
gboolean strip_chars;
gboolean extracting = FALSE;
#define DEFAULT_PARANOIA 4

Ross Burton's avatar
Ross Burton committed
/**
 * Clicked Quit
 */
void on_quit_activate (GtkMenuItem *item, gpointer user_data)
{
  gtk_main_quit ();
}

/**
 * Clicked Eject
 */
void on_eject_activate (GtkMenuItem *item, gpointer user_data)
{
  char *command;
  /*
   * Hey, its a hack. But it is very portable :)
   */
  command = g_strdup_printf ("eject %s", device);
  system (command);
  g_free (command);
}

Ross Burton's avatar
Ross Burton committed
gboolean on_destory_event (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
  if (extracting) {
Ross Burton's avatar
Ross Burton committed
    GtkWidget *dialog;
    int response;

    dialog = gtk_message_dialog_new (GTK_WINDOW (main_window), GTK_DIALOG_MODAL,
                                     GTK_MESSAGE_QUESTION,
                                     GTK_BUTTONS_NONE,
                                     _("You are currently extracting a CD. Do you want to quit now or contine?"));
Ross Burton's avatar
Ross Burton committed
    gtk_dialog_add_button (GTK_DIALOG (dialog), "gtk-quit", GTK_RESPONSE_ACCEPT);
Ross Burton's avatar
Ross Burton committed
    gtk_dialog_add_button (GTK_DIALOG (dialog), _("Continue"), GTK_RESPONSE_REJECT);
    g_signal_connect_swapped (GTK_OBJECT (dialog), 
                              "response", 
                              G_CALLBACK (gtk_widget_destroy),
                              GTK_OBJECT (dialog));
Ross Burton's avatar
Ross Burton committed
    gtk_widget_show_all (dialog);
    response = gtk_dialog_run (GTK_DIALOG (dialog));
    return response != GTK_RESPONSE_ACCEPT;
  }
  return FALSE;
}

Ross Burton's avatar
Ross Burton committed
static gboolean select_all_foreach_cb (GtkTreeModel *model,
                                      GtkTreePath *path,
                                      GtkTreeIter *iter,
                                      gpointer data)
{
Ross Burton's avatar
Ross Burton committed
  gboolean b = (gboolean)GPOINTER_TO_INT (data);
  gtk_list_store_set (track_store, iter, COLUMN_EXTRACT, b, -1);
Ross Burton's avatar
Ross Burton committed
  return FALSE;
}

void on_select_all_activate (GtkMenuItem *item, gpointer user_data)
{
Ross Burton's avatar
Ross Burton committed
  gtk_tree_model_foreach (GTK_TREE_MODEL (track_store), select_all_foreach_cb, GINT_TO_POINTER (TRUE));
}

void on_deselect_all_activate (GtkMenuItem *item, gpointer user_data)
{
  gtk_tree_model_foreach (GTK_TREE_MODEL (track_store), select_all_foreach_cb, GINT_TO_POINTER (FALSE));
Ross Burton's avatar
Ross Burton committed
}

Ross Burton's avatar
Ross Burton committed
/**
 * GtkTreeView cell renderer callback to render durations
 */
static void duration_cell_data_cb (GtkTreeViewColumn *tree_column,
                                GtkCellRenderer *cell,
                                GtkTreeModel *tree_model,
                                GtkTreeIter *iter,
                                gpointer data)
{
  int duration;
Ross Burton's avatar
Ross Burton committed

  gtk_tree_model_get (tree_model, iter, COLUMN_DURATION, &duration, -1);
  if (duration != 0) {
    string = g_strdup_printf("%d:%02d", duration / 60, duration % 60);
Ross Burton's avatar
Ross Burton committed
  } else {
    string = g_strdup(_("(unknown)"));
Ross Burton's avatar
Ross Burton committed
  }
  g_object_set (G_OBJECT (cell), "text", string, NULL);
  g_free (string);
Ross Burton's avatar
Ross Burton committed
}

/**
 * Utility function to update the UI for a given Album
 */
static void update_ui_for_album (AlbumDetails *album)
{
  GList *l;
Ross Burton's avatar
Ross Burton committed
  int album_duration = 0;
  char* duration_text;

Ross Burton's avatar
Ross Burton committed
  if (album == NULL) {
    gtk_label_set_text (GTK_LABEL (title_label), "");
    gtk_label_set_text (GTK_LABEL (artist_label), "");
Ross Burton's avatar
Ross Burton committed
    gtk_label_set_text (GTK_LABEL (duration_label), "");
Ross Burton's avatar
Ross Burton committed
    gtk_list_store_clear (track_store);
    gtk_widget_set_sensitive (extract_button, FALSE);
Ross Burton's avatar
Ross Burton committed
    gtk_widget_set_sensitive (extract_menuitem, FALSE);
    gtk_widget_set_sensitive (select_all_menuitem, FALSE);
    gtk_widget_set_sensitive (deselect_all_menuitem, FALSE);
Ross Burton's avatar
Ross Burton committed
  } else {
    gtk_label_set_text (GTK_LABEL (title_label), album->title);
    gtk_label_set_text (GTK_LABEL (artist_label), album->artist);
    gtk_widget_set_sensitive (extract_button, TRUE);
Ross Burton's avatar
Ross Burton committed
    gtk_widget_set_sensitive (extract_menuitem, TRUE);
    gtk_widget_set_sensitive (select_all_menuitem, TRUE);
    gtk_widget_set_sensitive (deselect_all_menuitem, TRUE);
Ross Burton's avatar
Ross Burton committed
    
    gtk_list_store_clear (track_store);
    for (l = album->tracks; l; l=g_list_next (l)) {
      GtkTreeIter iter;
      TrackDetails *track = (TrackDetails*)l->data;
Ross Burton's avatar
Ross Burton committed
      album_duration += track->duration;
Ross Burton's avatar
Ross Burton committed
      gtk_list_store_append (track_store, &iter);
      gtk_list_store_set (track_store, &iter,
Ross Burton's avatar
Ross Burton committed
                          COLUMN_EXTRACT, TRUE,
                          COLUMN_NUMBER, track->number,
Ross Burton's avatar
Ross Burton committed
                          COLUMN_TITLE, track->title,
                          COLUMN_ARTIST, track->artist,
                          COLUMN_DURATION, track->duration,
                          COLUMN_DETAILS, track,
                          -1);
    }
Ross Burton's avatar
Ross Burton committed
    /* Some albums don't have track durations :( */
    if (album_duration) {
      duration_text = g_strdup_printf("%d:%02d", album_duration / 60, album_duration % 60);
      gtk_label_set_text (GTK_LABEL (duration_label), duration_text);
      g_free (duration_text);
    } else {
      gtk_label_set_text (GTK_LABEL (duration_label), _("(unknown)"));
    }
Ross Burton's avatar
Ross Burton committed
  }
}

/**
 * Called by the Multiple Album dialog when the user hits return in
 * the list view
 */
static void album_row_activated (GtkTreeView *treeview,
                                 GtkTreePath *arg1,
                                 GtkTreeViewColumn *arg2,
                                 gpointer user_data)
{
  GtkDialog *dialog = GTK_DIALOG (user_data);
  gtk_dialog_response (dialog, GTK_RESPONSE_OK);
}

/**
 * Utility function for when there are more than one albums available
 */
AlbumDetails* multiple_album_dialog(GList *albums)
{
  static GtkWidget *dialog = NULL, *albums_listview;
  static GtkListStore *albums_store;
  static GtkTreeSelection *selection;
  AlbumDetails *album;
  GtkTreeIter iter;
  int response;

  if (dialog == NULL) {
    GtkTreeViewColumn *column;
    GtkCellRenderer *text_renderer = text_renderer = gtk_cell_renderer_text_new ();

    dialog = glade_xml_get_widget (glade, "multiple_dialog");
    g_assert (dialog != NULL);
    gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
    albums_listview = glade_xml_get_widget (glade, "albums_listview");
    /* TODO: A little hacky */
    g_signal_connect (albums_listview, "row-activated", G_CALLBACK (album_row_activated), dialog);

    albums_store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Title"),
Ross Burton's avatar
Ross Burton committed
                                                       text_renderer,
                                                       "text", 0,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (albums_listview), column);

Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Artist"),
Ross Burton's avatar
Ross Burton committed
                                                       text_renderer,
                                                       "text", 1,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (albums_listview), column);
    gtk_tree_view_set_model (GTK_TREE_VIEW (albums_listview), GTK_TREE_MODEL (albums_store));
    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (albums_listview));
    gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
  }

  gtk_list_store_clear (albums_store);
  for (; albums ; albums = g_list_next (albums)) {
    GtkTreeIter iter;
    AlbumDetails *album = (AlbumDetails*)(albums->data);
    gtk_list_store_append (albums_store, &iter);
    gtk_list_store_set (albums_store, &iter,
                        0, album->title,
                        1, album->artist,
                        2, album,
                        -1);
  }
  /*
   * TODO: focus is a little broken here. The first row should be
   * selected, so just hitting return works.
   */
Ross Burton's avatar
Ross Burton committed
  gtk_widget_grab_focus (albums_listview);
  gtk_widget_show_all (dialog);
  response = gtk_dialog_run (GTK_DIALOG (dialog));
  gtk_widget_hide (dialog);

  if (response == GTK_RESPONSE_DELETE_EVENT) {
    return NULL;
  }
  gtk_tree_selection_get_selected (selection, NULL, &iter);
  gtk_tree_model_get (GTK_TREE_MODEL (albums_store), &iter, 2, &album, -1);
  return album;
}

/**
 * The GConf key for the base path changed
 */
void basepath_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  g_assert (strcmp (entry->key, GCONF_BASEPATH) == 0);
  if (entry->value == NULL) {
    base_path = g_strdup (g_get_home_dir ());
  } else {
    base_path = gconf_value_get_string (entry->value);
  }
  /* TODO: sanity check the path somewhat */
}

/**
 * The GConf key for the directory pattern changed
 */
void path_pattern_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  g_assert (strcmp (entry->key, GCONF_PATH_PATTERN) == 0);
  if (entry->value == NULL) {
    /* TODO: this value and the value in sj-prefs need to be in one place */
    path_pattern = g_strdup ("%aa/%at");
  } else {
    path_pattern = gconf_value_get_string (entry->value);
  }
  /* TODO: sanity check the pattern */
}

/**
 * The GConf key for the filename pattern changed
 */
void file_pattern_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
  g_assert (strcmp (entry->key, GCONF_FILE_PATTERN) == 0);
  if (entry->value == NULL) {
    /* TODO: this value and the value in sj-prefs need to be in one place */
    file_pattern = g_strdup ("%tN-%tt");
    file_pattern = gconf_value_get_string (entry->value);
  }
  /* TODO: sanity check the pattern */
}

/**
 * The GConf key for the paranoia mode has changed
 */
void paranoia_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  g_assert (strcmp (entry->key, GCONF_PARANOIA) == 0);
  if (entry->value == NULL) {
    sj_extractor_set_paranoia (extractor, DEFAULT_PARANOIA);
  } else {
    int value = gconf_value_get_int (entry->value);
    if (value == 0 || value == 4 || value == 255) {
      sj_extractor_set_paranoia (extractor, value);
    }
  }
}

/**
 * The GConf key for the strip characters option changed
 */
void strip_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  g_assert (strcmp (entry->key, GCONF_STRIP) == 0);
  if (entry->value == NULL) {
    strip_chars = FALSE;
  } else {
    strip_chars = gconf_value_get_bool (entry->value);
  }
}

Ross Burton's avatar
Ross Burton committed
/**
 * Utility function to reread a CD
 */
void reread_cd (void)
{
  GList *albums;
  GError *error = NULL;
  GdkCursor *cursor;
  gboolean realized = GTK_WIDGET_REALIZED (main_window);
  
  /* Set watch cursor */
  if (realized) {
    cursor = gdk_cursor_new_for_display (gdk_drawable_get_display (main_window->window),
					 GDK_WATCH);
    gdk_window_set_cursor (main_window->window, cursor);
    gdk_cursor_unref (cursor);
    gdk_display_sync (gdk_drawable_get_display (main_window->window));
  }
  
Ross Burton's avatar
Ross Burton committed
  albums = sj_musicbrainz_list_albums(&error);

  if (realized)
    gdk_window_set_cursor (main_window->window, NULL);
  
Ross Burton's avatar
Ross Burton committed
  if (error) {
Ross Burton's avatar
Ross Burton committed
    GtkWidget *dialog;
    dialog = gtk_message_dialog_new (realized ? GTK_WINDOW (main_window) : NULL, 0,
Ross Burton's avatar
Ross Burton committed
                                     GTK_MESSAGE_ERROR,
                                     GTK_BUTTONS_CLOSE,
                                     g_strdup_printf ("<b>%s</b>\n\n%s\n%s: %s",
                                                     _("Could not read the CD"),
                                                     _("Sound Juicer could not read the track listing on this CD."),
                                                     _("Reason"),
                                                     error->message));
Ross Burton's avatar
Ross Burton committed
    gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE);
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);
Ross Burton's avatar
Ross Burton committed
    g_error_free (error);
    update_ui_for_album (NULL);
Ross Burton's avatar
Ross Burton committed
    return;
  }

  /* If there is more than one album... */
  if (g_list_next (albums)) {
    update_ui_for_album (multiple_album_dialog (albums));
Ross Burton's avatar
Ross Burton committed
  } else {
    update_ui_for_album (albums ? albums->data : NULL);
  }
}

/**
 * The GConf key for the device changed
 */
void device_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  g_assert (strcmp (entry->key, GCONF_DEVICE) == 0);

  if (entry->value == NULL) {
Ross Burton's avatar
Ross Burton committed
    device = prefs_get_default_device();
Ross Burton's avatar
Ross Burton committed
    if (device == NULL) {
#ifndef IGNORE_MISSING_CD
Ross Burton's avatar
Ross Burton committed
      GtkWidget *dialog;
Ross Burton's avatar
Ross Burton committed
      dialog = gtk_message_dialog_new (GTK_WINDOW (main_window), 0,
Ross Burton's avatar
Ross Burton committed
                                       GTK_MESSAGE_ERROR,
                                       GTK_BUTTONS_CLOSE,
                                       g_strdup_printf ("<b>%s</b>\n\n%s",
                                                        _("No CD-ROM drives found"),
                                                        _("Sound Juicer could not find any CD-ROM drives to read.")));
Ross Burton's avatar
Ross Burton committed
      gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE);
      gtk_dialog_run (GTK_DIALOG (dialog));
Ross Burton's avatar
Ross Burton committed
#endif
    }
  } else {
    device = gconf_value_get_string (entry->value);
Ross Burton's avatar
Ross Burton committed
    if (access (device, R_OK) != 0) {
      GtkWidget *dialog;
      char *message;
      message = g_strdup_printf (_("Sound Juicer could not access the CD-ROM device '%s'"), device);
Ross Burton's avatar
Ross Burton committed
      dialog = gtk_message_dialog_new (GTK_WINDOW (main_window), 0,
                                       GTK_MESSAGE_ERROR,
                                       GTK_BUTTONS_CLOSE,
                                       g_strdup_printf ("<b>%s</b>\n\n%s\n%s: %s",
                                                        _("Could not read the CD"),
                                                        message,
                                                        _("Reason"),
                                                        strerror (errno)));
      g_free (message);
Ross Burton's avatar
Ross Burton committed
      gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE);
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      /* Set a null device */
      device = NULL;
    }
Ross Burton's avatar
Ross Burton committed
  }
  sj_musicbrainz_set_cdrom (device);
  sj_extractor_set_device (extractor, device);
Ross Burton's avatar
Ross Burton committed

  reread_cd();
}

/**
 * The /apps/sound-juicer/format key has changed.
 */
void format_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  char* value;
  GEnumValue* enumvalue;
  g_assert (strcmp (entry->key, GCONF_FORMAT) == 0);
  if (!entry->value) return;
  value = g_ascii_strup (gconf_value_get_string (entry->value), -1);
  /* TODO: this line is pretty convoluted */
  enumvalue = g_enum_get_value_by_name (g_type_class_peek (encoding_format_get_type()), value);
  if (enumvalue == NULL) {
    g_warning (_("Unknown format %s"), value);
    g_free (value);
    return;
  g_object_set (extractor, "format", enumvalue->value, NULL);
  g_free (value);
/**
 * The GConf key for the HTTP proxy changed.
 */
void http_proxy_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  const char* value;
  g_assert (strcmp (entry->key, GCONF_HTTP_PROXY) == 0);
  if (entry->value == NULL) return;
  value = gconf_value_get_string (entry->value);
  sj_musicbrainz_set_proxy (value);
}

/**
 * The GConf key for the HTTP proxy port changed.
 */
void http_proxy_port_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
{
  int value;
  g_assert (strcmp (entry->key, GCONF_HTTP_PROXY_PORT) == 0);
  if (entry->value == NULL) return;
  value = gconf_value_get_int (entry->value);
  sj_musicbrainz_set_proxy_port (value);
}

/**
 * Clicked on Reread in the UI (button/menu)
 */
void on_reread_activate (GtkWidget *button, gpointer user_data)
{
  reread_cd ();
}

 * Called when the user clicked on the Extract column check boxes
Ross Burton's avatar
Ross Burton committed
static void on_extract_toggled (GtkCellRendererToggle *cellrenderertoggle,
                                gchar *path,
                                gpointer user_data)
{
  gboolean extract;
  GtkTreeIter iter;
  gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (track_store), &iter, path);
  gtk_tree_model_get (GTK_TREE_MODEL (track_store), &iter, COLUMN_EXTRACT, &extract, -1);
  gtk_list_store_set (track_store, &iter, COLUMN_EXTRACT, !extract, -1);
}

static void on_cell_edited (GtkCellRendererText *renderer,
                 gchar *path, gchar *string,
                 gpointer column_data)
{
  ViewColumn column = GPOINTER_TO_INT (column_data);
  GtkTreeIter iter;
  TrackDetails *track;
  char *artist, *title;
  gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (track_store), &iter, path);
  gtk_tree_model_get (GTK_TREE_MODEL (track_store), &iter,
                      COLUMN_ARTIST, &artist,
                      COLUMN_TITLE, &title,
                      COLUMN_DETAILS, &track,
                      -1);
  switch (column) {
  case COLUMN_TITLE:
    g_free (title);
    g_free (track->title);
    track->title = g_strdup (string);
    gtk_list_store_set (track_store, &iter, COLUMN_TITLE, track->title, -1);
    break;
  case COLUMN_ARTIST:
    g_free (artist);
    g_free (track->artist);
    track->artist = g_strdup (string);
    gtk_list_store_set (track_store, &iter, COLUMN_ARTIST, track->artist, -1);
    break;
  default:
    g_warning (_("Unknown column %d was edited"), column);
  }
  return;
}

static void error_on_start (GError *error)
{
  GtkWidget *dialog;
  dialog = gtk_message_dialog_new (NULL, 0,
                                   GTK_MESSAGE_ERROR,
                                   GTK_BUTTONS_CLOSE,
                                   g_strdup_printf ("<b>%s</b>\n\n%s: %s.\n%s",
                                                    _("Could not start Sound Juicer"),
                                                    _("Reason"),
                                                    error->message,
                                                    _("Please consult the documentation for assistance.")));
  gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE);
  gtk_dialog_run (GTK_DIALOG (dialog));
}

Ross Burton's avatar
Ross Burton committed
int main (int argc, char **argv)
{
  GError *error = NULL;
  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);
  
  gnome_program_init ("sound-juicer",
		      VERSION, LIBGNOMEUI_MODULE,
		      argc, argv,
		      NULL);
  g_set_application_name (_("Sound Juicer"));
  sj_musicbrainz_init (&error);
  if (error) {
    error_on_start (error);
    exit (1);
  }

  extractor = SJ_EXTRACTOR (sj_extractor_new());
  error = sj_extractor_get_new_error (extractor);
  if (error) {
    error_on_start (error);
Ross Burton's avatar
Ross Burton committed

Ross Burton's avatar
Ross Burton committed
  gconf_client = gconf_client_get_default ();
  if (gconf_client == NULL) {
    g_print (_("Could not create GConf client.\n"));
    exit (1);
  }
Ross Burton's avatar
Ross Burton committed
  gconf_client_add_dir (gconf_client, GCONF_ROOT, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
  gconf_client_notify_add (gconf_client, GCONF_DEVICE, device_changed_cb, NULL, NULL, NULL);
  gconf_client_notify_add (gconf_client, GCONF_BASEPATH, basepath_changed_cb, NULL, NULL, NULL);
  gconf_client_notify_add (gconf_client, GCONF_FORMAT, format_changed_cb, NULL, NULL, NULL);
  gconf_client_notify_add (gconf_client, GCONF_PARANOIA, paranoia_changed_cb, NULL, NULL, NULL);
  gconf_client_notify_add (gconf_client, GCONF_PATH_PATTERN, path_pattern_changed_cb, NULL, NULL, NULL);
  gconf_client_notify_add (gconf_client, GCONF_FILE_PATTERN, file_pattern_changed_cb, NULL, NULL, NULL);
  gconf_client_add_dir (gconf_client, GCONF_PROXY_ROOT, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
  gconf_client_notify_add (gconf_client, GCONF_HTTP_PROXY, http_proxy_changed_cb, NULL, NULL, NULL);
  gconf_client_notify_add (gconf_client, GCONF_HTTP_PROXY_PORT, http_proxy_port_changed_cb, NULL, NULL, NULL);
  glade = glade_xml_new (DATADIR"/sound-juicer.glade", NULL, NULL);
Ross Burton's avatar
Ross Burton committed
  g_assert (glade != NULL);
  glade_xml_signal_autoconnect (glade);

  main_window = glade_xml_get_widget (glade, "main_window");
  gtk_window_set_icon_from_file (GTK_WINDOW (main_window), PIXMAPDIR"/sound-juicer.png", NULL);
Ross Burton's avatar
Ross Burton committed
  select_all_menuitem = glade_xml_get_widget (glade, "select_all");
  deselect_all_menuitem = glade_xml_get_widget (glade, "deselect_all");
Ross Burton's avatar
Ross Burton committed
  extract_menuitem = glade_xml_get_widget (glade, "extract_menuitem");
Ross Burton's avatar
Ross Burton committed
  title_label = glade_xml_get_widget (glade, "title_label");
  artist_label = glade_xml_get_widget (glade, "artist_label");
Ross Burton's avatar
Ross Burton committed
  duration_label = glade_xml_get_widget (glade, "duration_label");
Ross Burton's avatar
Ross Burton committed
  track_listview = glade_xml_get_widget (glade, "track_listview");
  extract_button = glade_xml_get_widget (glade, "extract_button");
  reread_button = glade_xml_get_widget (glade, "reread_button");

  track_store = gtk_list_store_new (COLUMN_TOTAL, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_POINTER);
  gtk_tree_view_set_model (GTK_TREE_VIEW (track_listview), GTK_TREE_MODEL (track_store));
  {
    GtkTreeViewColumn *column;
    GtkCellRenderer *text_renderer, *toggle_renderer;
    
    toggle_renderer = gtk_cell_renderer_toggle_new ();
    g_signal_connect (toggle_renderer, "toggled", G_CALLBACK (on_extract_toggled), NULL);
Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Extract?"),
Ross Burton's avatar
Ross Burton committed
                                                       toggle_renderer,
                                                       "active", COLUMN_EXTRACT,
                                                       NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
Ross Burton's avatar
Ross Burton committed
    gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column);

    text_renderer = gtk_cell_renderer_text_new ();
Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Track"),
Ross Burton's avatar
Ross Burton committed
                                                       text_renderer,
                                                       "text", COLUMN_NUMBER,
                                                       NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
Ross Burton's avatar
Ross Burton committed
    gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column);

    /* TODO: Do I need to create these every time or will a single one do? */
    text_renderer = gtk_cell_renderer_text_new ();
    g_signal_connect (text_renderer, "edited", G_CALLBACK (on_cell_edited), GUINT_TO_POINTER (COLUMN_TITLE));
    g_object_set (G_OBJECT (text_renderer), "editable", TRUE, NULL);
Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Title"),
Ross Burton's avatar
Ross Burton committed
                                                       text_renderer,
                                                       "text", COLUMN_TITLE,
                                                       NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
Ross Burton's avatar
Ross Burton committed
    gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column);

    text_renderer = gtk_cell_renderer_text_new ();
Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Artist"),
Ross Burton's avatar
Ross Burton committed
                                                       text_renderer,
                                                       "text", COLUMN_ARTIST,
                                                       NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
    g_signal_connect (text_renderer, "edited", G_CALLBACK (on_cell_edited), GUINT_TO_POINTER (COLUMN_ARTIST));
    g_object_set (G_OBJECT (text_renderer), "editable", TRUE, NULL);
Ross Burton's avatar
Ross Burton committed
    gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column);
    
    text_renderer = gtk_cell_renderer_text_new ();
Ross Burton's avatar
Ross Burton committed
    column = gtk_tree_view_column_new_with_attributes (_("Duration"),
Ross Burton's avatar
Ross Burton committed
                                                       text_renderer,
                                                       NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
Ross Burton's avatar
Ross Burton committed
    gtk_tree_view_column_set_cell_data_func (column, text_renderer, duration_cell_data_cb, NULL, NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column);

  }
Ross Burton's avatar
Ross Burton committed
  /* YUCK. As bad as Baldrick's trousers */
  basepath_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_BASEPATH, NULL, TRUE, NULL), NULL);
  path_pattern_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_PATH_PATTERN, NULL, TRUE, NULL), NULL);
  file_pattern_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_FILE_PATTERN, NULL, TRUE, NULL), NULL);
Ross Burton's avatar
Ross Burton committed
  device_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_DEVICE, NULL, TRUE, NULL), NULL);
  format_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_FORMAT, NULL, TRUE, NULL), NULL);
  paranoia_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_PARANOIA, NULL, TRUE, NULL), NULL);
  strip_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_STRIP, NULL, TRUE, NULL), NULL);
  http_proxy_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_HTTP_PROXY, NULL, TRUE, NULL), NULL);
  http_proxy_port_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_HTTP_PROXY_PORT, NULL, TRUE, NULL), NULL);

  gtk_widget_show_all (main_window);
  gtk_main ();
  g_object_unref (extractor);
  g_object_unref (gconf_client);
  sj_musicbrainz_destroy ();
Ross Burton's avatar
Ross Burton committed
  return 0;
}