/* vi:set expandtab sw=2 sts=2: */
/*-
 * Copyright (c) 2008 Jannis Pohlmann <jannis@xfce.org>
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <glib/gi18n.h>

#include <gst/gst.h>
#include <gst/audio/mixerutils.h>
#include <gst/interfaces/mixer.h>

#include "libxfce4mixer/libxfce4mixer.h"

#include "xfce-mixer.h"
#include "xfce-mixer-window.h"
#include "xfce-mixer-controls-dialog.h"



static void     xfce_mixer_window_class_init             (XfceMixerWindowClass *klass);
static void     xfce_mixer_window_init                   (XfceMixerWindow      *window);
static void     xfce_mixer_window_dispose                (GObject              *object);
static void     xfce_mixer_window_finalize               (GObject              *object);
static void     xfce_mixer_window_soundcard_changed      (XfceMixerCardCombo   *combo,
                                                          GstElement           *card,
                                                          XfceMixerWindow      *window);
static void     xfce_mixer_window_action_select_controls (GtkAction            *action,
                                                          XfceMixerWindow      *window);
static void     xfce_mixer_window_action_use_card        (GtkAction            *action,
                                                          XfceMixerWindow      *window);
static void     xfce_mixer_window_close                  (GtkAction            *action,
                                                          XfceMixerWindow      *window);
static gboolean xfce_mixer_window_closed                 (GtkWidget            *window,
                                                          GdkEvent             *event,
                                                          XfceMixerWindow      *mixer_window);
static void     xfce_mixer_window_update_contents        (XfceMixerWindow      *window);



struct _XfceMixerWindowClass
{
  GtkDialogClass __parent__;
};

struct _XfceMixerWindow
{
  GtkDialog __parent__;

  XfceMixerPreferences *preferences;

  GtkActionGroup       *action_group;

  GtkWidget            *soundcard_combo;

  /* Active mixer control set */
  GtkWidget            *mixer_frame;
  GtkWidget            *mixer;

  GtkWidget            *select_controls_button;
  GtkWidget            *use_card_button;
};



static const GtkActionEntry action_entries[] =
{
  { "quit", GTK_STOCK_QUIT, N_ ("_OK"), NULL, N_ ("Exit the mixer"),
    G_CALLBACK (xfce_mixer_window_close) },
  { "use-card", NULL, N_ ("Make _Default"), NULL, N_ ("Make this card the default output"),
    G_CALLBACK (xfce_mixer_window_action_use_card) },
  { "select-controls", NULL, N_ ("_Select Controls..."), NULL, N_ ("Select which controls are displayed"),
    G_CALLBACK (xfce_mixer_window_action_select_controls) },
};

static const GtkToggleActionEntry toggle_action_entries[] =
{
};



static GObjectClass *xfce_mixer_window_parent_class = NULL;



GType
xfce_mixer_window_get_type (void)
{
  static GType type = G_TYPE_INVALID;

  if (G_UNLIKELY (type == G_TYPE_INVALID))
    {
      static const GTypeInfo info =
        {
          sizeof (XfceMixerWindowClass),
          NULL,
          NULL,
          (GClassInitFunc) xfce_mixer_window_class_init,
          NULL,
          NULL,
          sizeof (XfceMixerWindow),
          0,
          (GInstanceInitFunc) xfce_mixer_window_init,
          NULL,
        };

      type = g_type_register_static (gtk_dialog_get_type (), "XfceMixerWindow", &info, 0);

    }

  return type;
}



static void
xfce_mixer_window_class_init (XfceMixerWindowClass *klass)
{
  GObjectClass *gobject_class;

  /* Determine parent type class */
  xfce_mixer_window_parent_class = g_type_class_peek_parent (klass);

  gobject_class = G_OBJECT_CLASS (klass);
  gobject_class->dispose = xfce_mixer_window_dispose;
  gobject_class->finalize = xfce_mixer_window_finalize;
}



static void
xfce_mixer_window_init (XfceMixerWindow *window)
{
  GtkAccelGroup *accel_group;
  GtkAction     *action;
  GtkWidget     *label;
  GtkWidget     *button;
  GtkWidget     *vbox;
  GtkWidget     *hbox;
  GtkWidget     *bbox;
  gchar         *active_card = NULL;
  guint          i;
  gint           width;
  gint           height;

  window->preferences = xfce_mixer_preferences_get ();

  g_object_get (window->preferences, "window-width", &width, "window-height", &height, "sound-card", &active_card, NULL);

  GList           *iter;
  for (iter = xfce_mixer_get_cards (); iter != NULL; iter = g_list_next (iter))
  {
    if (xfce_mixer_is_default_card (iter->data))
        active_card = xfce_mixer_get_card_internal_name (iter->data);
  }

  /* Configure the main window */
  gtk_window_set_icon_name (GTK_WINDOW (window), "multimedia-volume-control");
  gtk_window_set_title (GTK_WINDOW (window), _("Audio Device Settings"));
  gtk_window_set_default_size (GTK_WINDOW (window), width, height);
  gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
  gtk_dialog_set_has_separator (GTK_DIALOG (window), FALSE);
  //xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (window), _("Configure sound card(s) and control the volume of selected tracks"));

  g_signal_connect (window, "delete-event", G_CALLBACK (xfce_mixer_window_closed), window);

  /* Quit mixer when the main window is closed */
  g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL);

  /* Create window action group */
  window->action_group = gtk_action_group_new ("XfceMixerWindow");
  gtk_action_group_set_translation_domain (window->action_group, GETTEXT_PACKAGE);
  gtk_action_group_add_actions (window->action_group, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));

  /* Install action accelerators for the mixer window */
  accel_group = gtk_accel_group_new ();
  for (i = 0; i < G_N_ELEMENTS (action_entries); ++i)
    {
      action = gtk_action_group_get_action (window->action_group, action_entries[i].name);
      gtk_action_set_accel_group (action, accel_group);
      gtk_action_connect_accelerator (action);
      gtk_action_set_sensitive (action, TRUE);
    }
  gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);

  vbox = gtk_dialog_get_content_area (GTK_DIALOG (window));
  gtk_widget_show (vbox);

  hbox = gtk_hbox_new (FALSE, 12);
  gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
  gtk_widget_show (hbox);

  label = gtk_label_new (NULL);
  gtk_label_set_text (GTK_LABEL (label), _("Sound card:"));
  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  window->soundcard_combo = xfce_mixer_card_combo_new (xfce_mixer_get_card (active_card));
  g_signal_connect (window->soundcard_combo, "soundcard-changed", G_CALLBACK (xfce_mixer_window_soundcard_changed), window);
  gtk_container_add (GTK_CONTAINER (hbox), window->soundcard_combo);
  gtk_widget_show (window->soundcard_combo);

  window->mixer_frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (window->mixer_frame), GTK_SHADOW_NONE);
  gtk_container_set_border_width (GTK_CONTAINER (window->mixer_frame), 6);
  gtk_container_add (GTK_CONTAINER (vbox), window->mixer_frame);
  gtk_widget_show (window->mixer_frame);

  bbox = gtk_dialog_get_action_area (GTK_DIALOG (window));
  gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_EDGE);
  gtk_container_set_border_width (GTK_CONTAINER (bbox), 6);

  window->select_controls_button = gtk_button_new ();
  gtk_action_connect_proxy (gtk_action_group_get_action (window->action_group, "select-controls"),
                            window->select_controls_button);
  gtk_button_set_image (GTK_BUTTON (window->select_controls_button),
                        gtk_image_new_from_icon_name ("preferences-desktop", GTK_ICON_SIZE_BUTTON));
  gtk_widget_set_sensitive (window->select_controls_button, FALSE);
  gtk_box_pack_start (GTK_BOX (bbox), window->select_controls_button, FALSE, TRUE, 0);
  gtk_widget_show (window->select_controls_button);

  window->use_card_button = gtk_button_new ();
  gtk_action_connect_proxy (gtk_action_group_get_action (window->action_group, "use-card"),
                            window->use_card_button);
  gtk_widget_set_sensitive (window->use_card_button, FALSE);
  gtk_box_pack_start (GTK_BOX (bbox), window->use_card_button, FALSE, TRUE, 0);
  gtk_widget_show (window->use_card_button);


  button = gtk_button_new ();
  gtk_action_connect_proxy (gtk_action_group_get_action (window->action_group, "quit"), button);
  gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_BUTTON));
  gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 0);
  gtk_widget_show (button);

  /* Re-generate mixer controls for the active sound card */
  xfce_mixer_window_update_contents (window);

  //g_free (active_card);
}



static void
xfce_mixer_window_dispose (GObject *object)
{
  (*G_OBJECT_CLASS (xfce_mixer_window_parent_class)->dispose) (object);
}



static void
xfce_mixer_window_finalize (GObject *object)
{
  XfceMixerWindow *window = XFCE_MIXER_WINDOW (object);

  g_object_unref (G_OBJECT (window->preferences));

  (*G_OBJECT_CLASS (xfce_mixer_window_parent_class)->finalize) (object);
}



GtkWidget*
xfce_mixer_window_new (void)
{
  return g_object_new (TYPE_XFCE_MIXER_WINDOW, NULL);
}



static void
xfce_mixer_window_soundcard_changed (XfceMixerCardCombo *combo,
                                     GstElement         *card,
                                     XfceMixerWindow    *window)
{
  gchar *title;

  g_return_if_fail (IS_XFCE_MIXER_CARD_COMBO (combo));
  g_return_if_fail (IS_XFCE_MIXER_WINDOW (window));
  g_return_if_fail (GST_IS_MIXER (card));

  //title = g_strdup_printf ("%s - %s", _("Audio Device"), xfce_mixer_get_card_display_name (card));
  //gtk_window_set_title (GTK_WINDOW (window), title);
  //g_free (title);

  /* Destroy the current mixer */
  if (G_LIKELY (window->mixer != NULL))
    gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (window->mixer_frame)));

  xfce_mixer_select_card (card);

  /* Create a new XfceMixer for the active sound card */
  window->mixer = xfce_mixer_new (card);

  /* Add the XfceMixer to the window */
  gtk_container_add (GTK_CONTAINER (window->mixer_frame), window->mixer);
  gtk_widget_show (window->mixer);

  /* Make the "Select Controls..." button sensitive */
  gtk_widget_set_sensitive (window->select_controls_button, TRUE);

  /* Make the "Make Default..." button sensitive */
  gtk_widget_set_sensitive (window->use_card_button, TRUE);

  /* Remember the card for next time */
  g_object_set (G_OBJECT (window->preferences), "sound-card", xfce_mixer_get_card_internal_name (card), NULL);
}



static void
xfce_mixer_window_action_select_controls (GtkAction       *action,
                                          XfceMixerWindow *window)
{
  GtkWidget     *dialog;

  dialog = xfce_mixer_controls_dialog_new (window);

  gtk_dialog_run (GTK_DIALOG (dialog));
  gtk_widget_destroy (dialog);

  xfce_mixer_window_update_contents (window);
}


static void
xfce_mixer_window_action_use_card (GtkAction       *action,
                                          XfceMixerWindow *window)
{
  GstElement *card = xfce_mixer_card_combo_get_active_card (XFCE_MIXER_CARD_COMBO (window->soundcard_combo));
  const gchar *id =  xfce_mixer_get_card_id (card);

  xfce_mixer_set_default_card (id);

  xfce_mixer_window_update_contents (window);

  xfce_mixer_card_combo_update (XFCE_MIXER_CARD_COMBO (window->soundcard_combo), card);
}

static void
xfce_mixer_window_close (GtkAction       *action,
                         XfceMixerWindow *window)
{
  /* This is a nasty hack to save the settings before the application quits */
  xfce_mixer_window_closed (GTK_WIDGET (window), NULL, window);

  gtk_main_quit ();
}



static gboolean
xfce_mixer_window_closed (GtkWidget       *window,
                          GdkEvent        *event,
                          XfceMixerWindow *mixer_window)
{
  gint width;
  gint height;

  gtk_window_get_size (GTK_WINDOW (mixer_window), &width, &height);
  g_object_set (G_OBJECT (mixer_window->preferences), "window-width", width, "window-height", height, NULL);

  return FALSE;
}



GstElement *
xfce_mixer_window_get_active_card (XfceMixerWindow *window)
{
  g_return_val_if_fail (IS_XFCE_MIXER_WINDOW (window), NULL);
  return xfce_mixer_card_combo_get_active_card (XFCE_MIXER_CARD_COMBO (window->soundcard_combo));
}



static void
xfce_mixer_window_update_contents (XfceMixerWindow *window)
{
  GstElement *card;

  g_return_if_fail (IS_XFCE_MIXER_WINDOW (window));

  card = xfce_mixer_card_combo_get_active_card (XFCE_MIXER_CARD_COMBO (window->soundcard_combo));

  /* Kind of a hack to regenerate the mixer controls */
  if (G_LIKELY (GST_IS_MIXER (card)))
    xfce_mixer_window_soundcard_changed (XFCE_MIXER_CARD_COMBO (window->soundcard_combo), card, window);
}

void xfce_mixer_window_refresh_device (XfceMixerWindow *window)
{
  GList *iter;
  gchar *active_card;

  for (iter = xfce_mixer_get_cards (); iter != NULL; iter = g_list_next (iter))
  {
    if (xfce_mixer_is_default_card (iter->data)) break;
  }
  if (iter)
  {
    xfce_mixer_window_soundcard_changed (XFCE_MIXER_CARD_COMBO (window->soundcard_combo), iter->data, window);
    xfce_mixer_card_combo_update (XFCE_MIXER_CARD_COMBO (window->soundcard_combo), iter->data);
  }
  else xfce_mixer_card_combo_update (XFCE_MIXER_CARD_COMBO (window->soundcard_combo), xfce_mixer_window_get_active_card (window));

}
