/* OGMRip - A library for DVD ripping and encoding
 * Copyright (C) 2004-2012 Olivier Rolland <billl@users.sourceforge.net>
 *
 * This library is free software; you can redisectionibute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is disectionibuted 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <glib/gi18n.h>
#include <glade/glade.h>

#include "ogmrip-helper.h"
#include "ogmrip-options-plugin.h"
#include "ogmrip-plugin.h"
#include "ogmrip-settings.h"
#include "ogmrip-xvid.h"

#define OGMRIP_GLADE_FILE "ogmrip/ogmrip-xvid.glade"
#define OGMRIP_GLADE_ROOT "root"

#define OGMRIP_TYPE_XVID_DIALOG          (ogmrip_xvid_dialog_get_type ())
#define OGMRIP_XVID_DIALOG(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), OGMRIP_TYPE_XVID_DIALOG, OGMRipXvidDialog))
#define OGMRIP_XVID_DIALOG_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), OGMRIP_TYPE_XVID_DIALOG, OGMRipXvidDialogClass))
#define OGMRIP_IS_XVID_DIALOG(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OGMRIP_TYPE_XVID_DIALOG))
#define OGMRIP_IS_XVID_DIALOG_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), OGMRIP_TYPE_XVID_DIALOG))

#define OGMRIP_XVID_KEY_B_ADAPT          OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_B_ADAPT
#define OGMRIP_XVID_KEY_BFRAMES          OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_BFRAMES
#define OGMRIP_XVID_KEY_BQUANT_OFFSET    OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_BQUANT_OFFSET
#define OGMRIP_XVID_KEY_BQUANT_RATIO     OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_BQUANT_RATIO
#define OGMRIP_XVID_KEY_BVHQ             OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_BVHQ
#define OGMRIP_XVID_KEY_CHROMA_ME        OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_CHROMA_ME
#define OGMRIP_XVID_KEY_CHROMA_OPT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_CHROMA_OPT
#define OGMRIP_XVID_KEY_CLOSED_GOP       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_CLOSED_GOP
#define OGMRIP_XVID_KEY_FRAME_DROP_RATIO OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_FRAME_DROP_RATIO
#define OGMRIP_XVID_KEY_GMC              OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_GMC
#define OGMRIP_XVID_KEY_INTERLACING      OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_INTERLACING
#define OGMRIP_XVID_KEY_MAX_BQUANT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MAX_BQUANT
#define OGMRIP_XVID_KEY_MAX_IQUANT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MAX_IQUANT
#define OGMRIP_XVID_KEY_MAX_PQUANT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MAX_PQUANT
#define OGMRIP_XVID_KEY_ME_QUALITY       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_ME_QUALITY
#define OGMRIP_XVID_KEY_MIN_BQUANT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MIN_BQUANT
#define OGMRIP_XVID_KEY_MIN_IQUANT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MIN_IQUANT
#define OGMRIP_XVID_KEY_MIN_PQUANT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MIN_PQUANT
#define OGMRIP_XVID_KEY_MAX_KEYINT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_MAX_KEYINT
#define OGMRIP_XVID_KEY_PACKED           OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_PACKED
#define OGMRIP_XVID_KEY_PAR_HEIGHT       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_PAR_HEIGHT
#define OGMRIP_XVID_KEY_PAR              OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_PAR
#define OGMRIP_XVID_KEY_PAR_WIDTH        OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_PAR_WIDTH
#define OGMRIP_XVID_KEY_PROFILE          OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_PROFILE
#define OGMRIP_XVID_KEY_QUANT_TYPE       OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_QUANT_TYPE
#define OGMRIP_XVID_KEY_VHQ              OGMRIP_XVID_SECTION "/" OGMRIP_XVID_PROP_VHQ

typedef struct _OGMRipXvidDialog      OGMRipXvidDialog;
typedef struct _OGMRipXvidDialogClass OGMRipXvidDialogClass;

struct _OGMRipXvidDialog
{
  OGMRipPluginDialog parent_instance;

  GtkWidget *b_adapt_check;
  GtkWidget *bquant_offset_spin;
  GtkWidget *bquant_ratio_spin;
  GtkWidget *bvhq_check;
  GtkWidget *chroma_me_check;
  GtkWidget *chroma_opt_check;
  GtkWidget *closed_gop_check;
  GtkWidget *frame_drop_ratio_spin;
  GtkWidget *gmc_check;
  GtkWidget *interlacing_check;
  GtkWidget *max_bframes_spin;
  GtkWidget *max_bquant_spin;
  GtkWidget *max_iquant_spin;
  GtkWidget *max_pquant_spin;
  GtkWidget *me_quality_combo;
  GtkWidget *min_bquant_spin;
  GtkWidget *min_iquant_spin;
  GtkWidget *min_pquant_spin;
  GtkWidget *max_keyint_spin;
  GtkWidget *packed_check;
  GtkWidget *par_combo;
  GtkWidget *par_height_spin;
  GtkWidget *par_width_spin;
  GtkWidget *profile_combo;
  GtkWidget *quant_type_combo;
  GtkWidget *vhq_combo;
};

struct _OGMRipXvidDialogClass
{
  OGMRipPluginDialogClass parent_class;
};

static void ogmrip_xvid_dialog_set_section   (OGMRipPluginDialog *dialog,
                                              const gchar        *section);

static gboolean xvid_have_b_adapt = FALSE;

G_DEFINE_TYPE (OGMRipXvidDialog, ogmrip_xvid_dialog, OGMRIP_TYPE_PLUGIN_DIALOG)

static void
ogmrip_xvid_dialog_class_init (OGMRipXvidDialogClass *klass)
{
  OGMRipPluginDialogClass *dialog_class;

  dialog_class = (OGMRipPluginDialogClass *) klass;
  dialog_class->set_section = ogmrip_xvid_dialog_set_section;
}

static void
ogmrip_xvid_dialog_b_adapt_toggled (OGMRipXvidDialog *dialog)
{
  gboolean sensitive;

  sensitive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->b_adapt_check));
  gtk_widget_set_sensitive (dialog->max_bframes_spin, !sensitive);

  if (sensitive)
    gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->max_bframes_spin), 0.0);
}

static void
ogmrip_xvid_dialog_par_changed (OGMRipXvidDialog *dialog)
{
  gint active;

  active = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->par_combo));
  gtk_widget_set_sensitive (dialog->par_width_spin, active == 6);
  gtk_widget_set_sensitive (dialog->par_height_spin, active == 6);
}

static void
ogmrip_xvid_dialog_max_bframes_changed (OGMRipXvidDialog *dialog)
{
  gint bframes;

  bframes = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->max_bframes_spin));
  gtk_widget_set_sensitive (dialog->frame_drop_ratio_spin, bframes == 0);
}

static void
ogmrip_xvid_dialog_init (OGMRipXvidDialog *dialog)
{
  GtkWidget *area, *widget;
  GladeXML *xml;

  xml = glade_xml_new (OGMRIP_DATA_DIR "/" OGMRIP_GLADE_FILE, OGMRIP_GLADE_ROOT, NULL);
  if (!xml)
  {
    g_warning ("Could not find " OGMRIP_GLADE_FILE);
    return;
  }

#if !GTK_CHECK_VERSION(2,22,0)
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
#endif
  gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);

  gtk_window_set_title (GTK_WINDOW (dialog), _("XviD Options"));
  gtk_window_set_icon_from_stock (GTK_WINDOW (dialog), GTK_STOCK_PREFERENCES);

  area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

  widget = glade_xml_get_widget (xml, OGMRIP_GLADE_ROOT);
  gtk_container_add (GTK_CONTAINER (area), widget);
  gtk_widget_show (widget);

  dialog->bquant_offset_spin = glade_xml_get_widget (xml, "bquant_offset-spin");
  dialog->bquant_ratio_spin = glade_xml_get_widget (xml, "bquant_ratio-spin");
  dialog->bvhq_check = glade_xml_get_widget (xml, "bvhq-check");
  dialog->chroma_me_check = glade_xml_get_widget (xml, "chroma_me-check");
  dialog->chroma_opt_check = glade_xml_get_widget (xml, "chroma_opt-check");
  dialog->closed_gop_check = glade_xml_get_widget (xml, "closed_gop-check");
  dialog->frame_drop_ratio_spin = glade_xml_get_widget (xml, "frame_drop_ratio-spin");
  dialog->gmc_check = glade_xml_get_widget (xml, "gmc-check");
  dialog->interlacing_check = glade_xml_get_widget (xml, "interlacing-check");
  dialog->max_bquant_spin = glade_xml_get_widget (xml, "max_bquant-spin");
  dialog->max_iquant_spin = glade_xml_get_widget (xml, "max_iquant-spin");
  dialog->max_pquant_spin = glade_xml_get_widget (xml, "max_pquant-spin");
  dialog->me_quality_combo = glade_xml_get_widget (xml, "me_quality-combo");
  dialog->min_bquant_spin = glade_xml_get_widget (xml, "min_bquant-spin");
  dialog->min_iquant_spin = glade_xml_get_widget (xml, "min_iquant-spin");
  dialog->min_pquant_spin = glade_xml_get_widget (xml, "min_pquant-spin");
  dialog->max_keyint_spin = glade_xml_get_widget (xml, "max_keyint-spin");
  dialog->packed_check = glade_xml_get_widget (xml, "packed-check");
  dialog->profile_combo = glade_xml_get_widget (xml, "profile-combo");
  dialog->quant_type_combo = glade_xml_get_widget (xml, "quant_type-combo");
  dialog->vhq_combo = glade_xml_get_widget (xml, "vhq-combo");

  dialog->par_width_spin = glade_xml_get_widget (xml, "par_width-spin");
  gtk_widget_set_sensitive (dialog->par_width_spin, FALSE);

  dialog->par_height_spin = glade_xml_get_widget (xml, "par_height-spin");
  gtk_widget_set_sensitive (dialog->par_height_spin, FALSE);

  dialog->par_combo = glade_xml_get_widget (xml, "par-combo");
  dialog->max_bframes_spin = glade_xml_get_widget (xml, "max_bframes-spin");

  dialog->b_adapt_check = glade_xml_get_widget (xml, "b_adapt-check");
  gtk_widget_set_sensitive (dialog->b_adapt_check, xvid_have_b_adapt);

  g_signal_connect_swapped (dialog->b_adapt_check, "toggled",
      G_CALLBACK (ogmrip_xvid_dialog_b_adapt_toggled), dialog);

  g_signal_connect_swapped (dialog->par_combo, "changed",
      G_CALLBACK (ogmrip_xvid_dialog_par_changed), dialog);

  g_signal_connect_swapped (dialog->max_bframes_spin, "value-changed",
      G_CALLBACK (ogmrip_xvid_dialog_max_bframes_changed), dialog);

  g_object_unref (xml);
}

static void
ogmrip_xvid_dialog_set_section (OGMRipPluginDialog *plugin_dialog, const gchar *section)
{
  OGMRipSettings *settings;

  settings = ogmrip_settings_get_default ();
  if (settings)
  {
    OGMRipXvidDialog *dialog;

    dialog = OGMRIP_XVID_DIALOG (plugin_dialog);

    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_PROFILE, G_OBJECT (dialog->profile_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_QUANT_TYPE, G_OBJECT (dialog->quant_type_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_ME_QUALITY, G_OBJECT (dialog->me_quality_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_VHQ, G_OBJECT (dialog->vhq_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_PAR, G_OBJECT (dialog->par_combo), "active");

    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_GMC, G_OBJECT (dialog->gmc_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_INTERLACING, G_OBJECT (dialog->interlacing_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_PACKED, G_OBJECT (dialog->packed_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_CLOSED_GOP, G_OBJECT (dialog->closed_gop_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_CHROMA_ME, G_OBJECT (dialog->chroma_me_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_CHROMA_OPT, G_OBJECT (dialog->chroma_opt_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_BVHQ, G_OBJECT (dialog->bvhq_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_B_ADAPT, G_OBJECT (dialog->b_adapt_check), "active");

    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MIN_IQUANT, G_OBJECT (dialog->min_iquant_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MAX_IQUANT, G_OBJECT (dialog->max_iquant_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MIN_PQUANT, G_OBJECT (dialog->min_pquant_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MAX_PQUANT, G_OBJECT (dialog->max_pquant_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MIN_BQUANT, G_OBJECT (dialog->min_bquant_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MAX_BQUANT, G_OBJECT (dialog->max_bquant_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_FRAME_DROP_RATIO, G_OBJECT (dialog->frame_drop_ratio_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_BQUANT_RATIO, G_OBJECT (dialog->bquant_ratio_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_BQUANT_OFFSET, G_OBJECT (dialog->bquant_offset_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_PAR_WIDTH, G_OBJECT (dialog->par_width_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_PAR_HEIGHT, G_OBJECT (dialog->par_height_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_BFRAMES, G_OBJECT (dialog->max_bframes_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_XVID_KEY_MAX_KEYINT, G_OBJECT (dialog->max_keyint_spin), "value");
  }
}

static OGMRipVideoOptionsPlugin xvid_options_plugin =
{
  NULL,
  G_TYPE_NONE,
  G_TYPE_NONE
};

OGMRipVideoOptionsPlugin *
ogmrip_init_options_plugin (void)
{
  GModule *module;

  xvid_options_plugin.type = ogmrip_plugin_get_video_codec_by_name ("xvid");
  if (xvid_options_plugin.type == G_TYPE_NONE)
    return NULL;

  module = ogmrip_plugin_get_video_codec_module (xvid_options_plugin.type);
  if (module)
  {
    gboolean *symbol;

    if (g_module_symbol (module, "xvid_have_b_adapt", (gpointer *) &symbol))
      xvid_have_b_adapt = *symbol;
  }

  xvid_options_plugin.dialog = OGMRIP_TYPE_XVID_DIALOG;

  return &xvid_options_plugin;
}

