/* 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 redistribute 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 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
 * 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-x264.h"

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

#define OGMRIP_TYPE_X264_DIALOG          (ogmrip_x264_dialog_get_type ())
#define OGMRIP_X264_DIALOG(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), OGMRIP_TYPE_X264_DIALOG, OGMRipX264Dialog))
#define OGMRIP_X264_DIALOG_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), OGMRIP_TYPE_X264_DIALOG, OGMRipX264DialogClass))
#define OGMRIP_IS_X264_DIALOG(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OGMRIP_TYPE_X264_DIALOG))
#define OGMRIP_IS_X264_DIALOG_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), OGMRIP_TYPE_X264_DIALOG))

#define OGMRIP_X264_PROP_PROFILE      "profile"
#define OGMRIP_X264_DEFAULT_PROFILE   OGMRIP_X264_PROFILE_HIGH

#define OGMRIP_X264_KEY_8X8DCT        OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_8X8DCT
#define OGMRIP_X264_KEY_AUD           OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_AUD
#define OGMRIP_X264_KEY_BFRAMES       OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_BFRAMES
#define OGMRIP_X264_KEY_B_ADAPT       OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_B_ADAPT
#define OGMRIP_X264_KEY_B_PYRAMID     OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_B_PYRAMID
#define OGMRIP_X264_KEY_BRDO          OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_BRDO
#define OGMRIP_X264_KEY_CABAC         OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_CABAC
#define OGMRIP_X264_KEY_CQM           OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_CQM
#define OGMRIP_X264_KEY_DIRECT        OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_DIRECT
#define OGMRIP_X264_KEY_FRAMEREF      OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_FRAMEREF
#define OGMRIP_X264_KEY_GLOBAL_HEADER OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_GLOBAL_HEADER
#define OGMRIP_X264_KEY_KEYINT        OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_KEYINT
#define OGMRIP_X264_KEY_LEVEL_IDC     OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_LEVEL_IDC
#define OGMRIP_X264_KEY_ME            OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_ME
#define OGMRIP_X264_KEY_MERANGE       OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_MERANGE
#define OGMRIP_X264_KEY_MIXED_REFS    OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_MIXED_REFS
#define OGMRIP_X264_KEY_PARTITIONS    OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_PARTITIONS
#define OGMRIP_X264_KEY_PROFILE       OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_PROFILE
#define OGMRIP_X264_KEY_PSY_RD        OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_PSY_RD
#define OGMRIP_X264_KEY_PSY_TRELLIS   OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_PSY_TRELLIS
#define OGMRIP_X264_KEY_RC_LOOKAHEAD  OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_RC_LOOKAHEAD
#define OGMRIP_X264_KEY_SUBQ          OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_SUBQ
#define OGMRIP_X264_KEY_VBV_BUFSIZE   OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_VBV_BUFSIZE
#define OGMRIP_X264_KEY_VBV_MAXRATE   OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_VBV_MAXRATE
#define OGMRIP_X264_KEY_WEIGHT_B      OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_WEIGHT_B
#define OGMRIP_X264_KEY_WEIGHT_P      OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_WEIGHT_P

typedef struct _OGMRipX264Dialog      OGMRipX264Dialog;
typedef struct _OGMRipX264DialogClass OGMRipX264DialogClass;

struct _OGMRipX264Dialog
{
  OGMRipPluginDialog parent_instance;

  GtkWidget *aud_check;
  GtkWidget *b_pyramid_check;
  GtkWidget *brdo_check;
  GtkWidget *cabac_check;
  GtkWidget *global_header_check;
  GtkWidget *mixed_refs_check;
  GtkWidget *partitions_check;
  GtkWidget *weight_b_check;
  GtkWidget *x88dct_check;

  GtkWidget *b_adapt_spin;
  GtkWidget *bframes_spin;
  GtkWidget *frameref_spin;
  GtkWidget *keyint_spin;
  GtkWidget *level_idc_spin;
  GtkWidget *merange_spin;
  GtkWidget *psy_rd_spin;
  GtkWidget *psy_trellis_spin;
  GtkWidget *rc_lookahead_spin;
  GtkWidget *subq_spin;
  GtkWidget *vbv_bufsize_spin;
  GtkWidget *vbv_maxrate_spin;

  GtkWidget *b_pyramid_combo;
  GtkWidget *cqm_combo;
  GtkWidget *direct_combo;
  GtkWidget *me_combo;
  GtkWidget *profile_combo;
  GtkWidget *weight_p_combo;
};

struct _OGMRipX264DialogClass
{
  OGMRipPluginDialogClass parent_class;
};

enum
{
  OGMRIP_X264_PROFILE_BASELINE,
  OGMRIP_X264_PROFILE_MAIN,
  OGMRIP_X264_PROFILE_HIGH
};

GType ogmrip_x264_get_type ();

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

static gboolean x264_have_8x8dct     = FALSE;
static gboolean x264_have_aud        = FALSE;
static gboolean x264_have_b_pyramid  = FALSE;
static gboolean x264_have_brdo       = FALSE;
static gboolean x264_have_lookahead  = FALSE;
static gboolean x264_have_me         = FALSE;
static gboolean x264_have_me_tesa    = FALSE;
static gboolean x264_have_mixed_refs = FALSE;
static gboolean x264_have_psy        = FALSE;
static gboolean x264_have_weight_p   = FALSE;

static void
ogmrip_x264_dialog_profile_changed (OGMRipX264Dialog *dialog)
{
  gint profile;

  profile = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->profile_combo));

  if (profile != OGMRIP_X264_PROFILE_HIGH)
  {
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->x88dct_check), FALSE);
    gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->cqm_combo), 0);
  }

  gtk_widget_set_sensitive (dialog->x88dct_check, x264_have_8x8dct && profile == OGMRIP_X264_PROFILE_HIGH);
  gtk_widget_set_sensitive (dialog->cqm_combo, profile == OGMRIP_X264_PROFILE_HIGH);

  if (profile == OGMRIP_X264_PROFILE_BASELINE)
  {
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->cabac_check), FALSE);
    gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->weight_p_combo), 0);
    gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->bframes_spin), 0);
  }

  gtk_widget_set_sensitive (dialog->cabac_check, profile != OGMRIP_X264_PROFILE_BASELINE);
  gtk_widget_set_sensitive (dialog->weight_p_combo, x264_have_weight_p && profile != OGMRIP_X264_PROFILE_BASELINE);
  gtk_widget_set_sensitive (dialog->bframes_spin, profile != OGMRIP_X264_PROFILE_BASELINE);
}

static void
ogmrip_x264_dialog_bframes_changed (OGMRipX264Dialog *dialog)
{
  gint bframes;

  bframes = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->bframes_spin));

  gtk_widget_set_sensitive (dialog->b_pyramid_check, bframes > 1);
  gtk_widget_set_sensitive (dialog->b_pyramid_combo, bframes > 1);
  gtk_widget_set_sensitive (dialog->weight_b_check, bframes > 1);

  if (bframes <= 1)
  {
    gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->b_pyramid_combo), 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->b_pyramid_check), FALSE);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->weight_b_check), FALSE);
  }
}

static void
ogmrip_x264_dialog_subq_changed (OGMRipX264Dialog *dialog)
{
  gint subq;

  subq = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->subq_spin));

  gtk_widget_set_sensitive (dialog->brdo_check, x264_have_brdo && subq > 5);
  gtk_widget_set_sensitive (dialog->psy_rd_spin, x264_have_psy && subq > 5);

  if (subq <= 5)
  {
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->brdo_check), FALSE);
    gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->psy_rd_spin), 0.0);
  }
}

static void
ogmrip_x264_dialog_frameref_changed (OGMRipX264Dialog *dialog)
{
  gint frameref;

  frameref = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->frameref_spin));

  gtk_widget_set_sensitive (dialog->mixed_refs_check, x264_have_mixed_refs && frameref > 1);
  if (frameref <= 1)
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->mixed_refs_check), FALSE);
}

static void
ogmrip_x264_dialog_vbv_maxrate_changed (OGMRipX264Dialog *dialog)
{
  gtk_widget_set_sensitive (dialog->vbv_bufsize_spin,
      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (dialog->vbv_maxrate_spin)) > 0);
}

G_DEFINE_TYPE (OGMRipX264Dialog, ogmrip_x264_dialog, OGMRIP_TYPE_PLUGIN_DIALOG)

static void
ogmrip_x264_dialog_class_init (OGMRipX264DialogClass *klass)
{
  OGMRipPluginDialogClass *dialog_class;

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

static void
ogmrip_x264_dialog_init (OGMRipX264Dialog *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;
  }

  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
      NULL);
  gtk_window_set_title (GTK_WINDOW (dialog), _("X264 Options"));
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
#if !GTK_CHECK_VERSION(2,22,0)
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
#endif
  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
  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->profile_combo = glade_xml_get_widget (xml, "profile-combo");
  g_signal_connect_swapped (dialog->profile_combo, "changed",
      G_CALLBACK (ogmrip_x264_dialog_profile_changed), dialog);

  dialog->bframes_spin = glade_xml_get_widget (xml, "bframes-spin");
  g_signal_connect_swapped (dialog->bframes_spin, "value-changed",
      G_CALLBACK (ogmrip_x264_dialog_bframes_changed), dialog);

  dialog->cabac_check = glade_xml_get_widget (xml, "cabac-check");
  dialog->cqm_combo = glade_xml_get_widget (xml, "cqm-combo");

  dialog->subq_spin = glade_xml_get_widget (xml, "subq-spin");
  g_signal_connect_swapped (dialog->subq_spin, "value-changed",
      G_CALLBACK (ogmrip_x264_dialog_subq_changed), dialog);
  
  dialog->global_header_check = glade_xml_get_widget (xml, "global_header-check");
  dialog->weight_b_check = glade_xml_get_widget (xml, "weight_b-check");
  dialog->partitions_check = glade_xml_get_widget (xml, "partitions-check");

  dialog->weight_p_combo = glade_xml_get_widget (xml, "weight_p-combo");
  gtk_widget_set_sensitive (dialog->weight_p_combo, x264_have_weight_p);
  gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->weight_p_combo), 0);
  
  dialog->b_pyramid_check = glade_xml_get_widget (xml, "b_pyramid-check");
  g_object_set (dialog->b_pyramid_check, "visible", !x264_have_b_pyramid, NULL);

  dialog->b_pyramid_combo = glade_xml_get_widget (xml, "b_pyramid-combo");
  g_object_set (dialog->b_pyramid_combo, "visible", x264_have_b_pyramid, NULL);

  widget = glade_xml_get_widget (xml, "b_pyramid-label");
  g_object_set (widget, "visible", x264_have_b_pyramid, NULL);

  dialog->frameref_spin = glade_xml_get_widget (xml, "frameref-spin");
  g_signal_connect_swapped (dialog->frameref_spin, "value-changed",
      G_CALLBACK (ogmrip_x264_dialog_frameref_changed), dialog);
  
  dialog->me_combo = glade_xml_get_widget (xml, "me-combo");
  gtk_widget_set_sensitive (dialog->me_combo, x264_have_me);

  if (x264_have_me_tesa)
  {
    GtkTreeModel *model;
    GtkTreeIter iter;

    model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->me_combo));
    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
    gtk_list_store_set (GTK_LIST_STORE (model), &iter,
        0, _("Transformed Exhaustive search (tesa - even slower)"), -1);
  }

  dialog->merange_spin = glade_xml_get_widget (xml, "merange-spin");
  gtk_widget_set_sensitive (dialog->merange_spin, x264_have_me);

  dialog->x88dct_check = glade_xml_get_widget (xml, "dct8x8-check");
  gtk_widget_set_sensitive (dialog->x88dct_check, x264_have_8x8dct);

  dialog->mixed_refs_check = glade_xml_get_widget (xml, "mixed_refs-check");
  gtk_widget_set_sensitive (dialog->mixed_refs_check, x264_have_mixed_refs);
  
  dialog->brdo_check = glade_xml_get_widget (xml, "brdo-check");
  gtk_widget_set_sensitive (dialog->brdo_check, x264_have_brdo);

  dialog->vbv_maxrate_spin = glade_xml_get_widget (xml, "vbv_maxrate-spin");
  g_signal_connect_swapped (dialog->vbv_maxrate_spin, "value-changed",
      G_CALLBACK (ogmrip_x264_dialog_vbv_maxrate_changed), dialog);
  
  dialog->vbv_bufsize_spin = glade_xml_get_widget (xml, "vbv_bufsize-spin");
  dialog->level_idc_spin = glade_xml_get_widget (xml, "level_idc-spin");
  dialog->direct_combo = glade_xml_get_widget (xml, "direct-combo");
  dialog->b_adapt_spin = glade_xml_get_widget (xml, "b_adapt-spin");
  dialog->keyint_spin = glade_xml_get_widget (xml, "keyint-spin");

  dialog->psy_rd_spin = glade_xml_get_widget (xml, "psy_rd-spin");
  gtk_widget_set_sensitive (dialog->psy_rd_spin, x264_have_psy);

  dialog->psy_trellis_spin = glade_xml_get_widget (xml, "psy_trellis-spin");
  gtk_widget_set_sensitive (dialog->psy_trellis_spin, x264_have_psy);

  dialog->aud_check = glade_xml_get_widget (xml, "aud-check");
  gtk_widget_set_sensitive (dialog->aud_check, x264_have_aud);

  dialog->rc_lookahead_spin = glade_xml_get_widget (xml, "rc_lookahead-spin");
  gtk_widget_set_sensitive (dialog->rc_lookahead_spin, x264_have_lookahead);

  g_object_unref (xml);
}

static void
ogmrip_x264_get_me (GObject *object, const gchar *property, GValue *value, gpointer data)
{
  gint active;

  g_object_get (object, "active", &active, NULL);
  g_value_set_uint (value, active + 1);
}

static void
ogmrip_x264_set_me (GObject *object, const gchar *property, const GValue *value, gpointer data)
{
  gint active;

  if (G_VALUE_HOLDS (value, G_TYPE_UINT))
    active = g_value_get_uint (value);
  else
    active = g_value_get_int (value);

  g_object_set (object, "active", active - 1, NULL);
}

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

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

    dialog = OGMRIP_X264_DIALOG (plugin_dialog);

    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_BFRAMES, G_OBJECT (dialog->bframes_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_SUBQ, G_OBJECT (dialog->subq_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_FRAMEREF, G_OBJECT (dialog->frameref_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_MERANGE, G_OBJECT (dialog->merange_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_VBV_MAXRATE, G_OBJECT (dialog->vbv_maxrate_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_VBV_BUFSIZE, G_OBJECT (dialog->vbv_bufsize_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_LEVEL_IDC, G_OBJECT (dialog->level_idc_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_B_ADAPT, G_OBJECT (dialog->b_adapt_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_KEYINT, G_OBJECT (dialog->keyint_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_PSY_RD, G_OBJECT (dialog->psy_rd_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_PSY_TRELLIS, G_OBJECT (dialog->psy_trellis_spin), "value");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_RC_LOOKAHEAD, G_OBJECT (dialog->rc_lookahead_spin), "value");

    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_CABAC, G_OBJECT (dialog->cabac_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_WEIGHT_B, G_OBJECT (dialog->weight_b_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_8X8DCT, G_OBJECT (dialog->x88dct_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_MIXED_REFS, G_OBJECT (dialog->mixed_refs_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_GLOBAL_HEADER, G_OBJECT (dialog->global_header_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_PARTITIONS, G_OBJECT (dialog->partitions_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_BRDO, G_OBJECT (dialog->brdo_check), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_AUD, G_OBJECT (dialog->aud_check), "active");

    ogmrip_settings_bind_custom (settings, section,
        OGMRIP_X264_KEY_ME, G_OBJECT (dialog->me_combo), "active",
        ogmrip_x264_get_me, ogmrip_x264_set_me, NULL);
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_DIRECT, G_OBJECT (dialog->direct_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_CQM, G_OBJECT (dialog->cqm_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_WEIGHT_P, G_OBJECT (dialog->weight_p_combo), "active");
    ogmrip_settings_bind (settings, section,
        OGMRIP_X264_KEY_PROFILE, G_OBJECT (dialog->profile_combo), "active");

    if (x264_have_b_pyramid)
      ogmrip_settings_bind (settings, section,
          OGMRIP_X264_KEY_B_PYRAMID, G_OBJECT (dialog->b_pyramid_combo), "active");
    else
      ogmrip_settings_bind (settings, section,
          OGMRIP_X264_KEY_B_PYRAMID, G_OBJECT (dialog->b_pyramid_check), "active");
  }
}

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

OGMRipVideoOptionsPlugin *
ogmrip_init_options_plugin (void)
{
  OGMRipSettings *settings;
  GModule *module;

  x264_options_plugin.type = ogmrip_plugin_get_video_codec_by_name ("x264");
  if (x264_options_plugin.type == G_TYPE_NONE)
    return NULL;

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

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

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

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

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

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

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

    if (x264_have_me && g_module_symbol (module, "x264_have_me_tesa", (gpointer *) &symbol))
      x264_have_me_tesa = *symbol;

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

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

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

  settings = ogmrip_settings_get_default ();
  if (settings)
  {
    ogmrip_settings_install_key (settings,
        g_param_spec_uint (OGMRIP_X264_SECTION "/" OGMRIP_X264_PROP_PROFILE, "Profile property", "Set profile",
          OGMRIP_X264_PROFILE_BASELINE, OGMRIP_X264_PROFILE_HIGH, OGMRIP_X264_DEFAULT_PROFILE, G_PARAM_READWRITE));
  }

  x264_options_plugin.dialog = OGMRIP_TYPE_X264_DIALOG;

  return &x264_options_plugin;
}

