# $Id: Transcode.pm,v 1.20 2006/08/16 19:34:38 joern Exp $

#-----------------------------------------------------------------------
# Copyright (C) 2001-2006 Jörn Reder <joern AT zyn.de>.
# All Rights Reserved. See file COPYRIGHT for details.
#
# This module is part of Video::DVDRip, which is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.
#-----------------------------------------------------------------------

package Video::DVDRip::GUI::Project::Transcode;

use base qw( Video::DVDRip::GUI::Base );

use Locale::TextDomain qw (video.dvdrip);

use Carp;
use strict;

sub new {
    my $class = shift;

    my $self = $class->SUPER::new(@_);

    $self->get_context->set_object( "transcode" => $self );

    return $self;
}

sub build_factory {
    my $self = shift;

    my $context = $self->get_context;

    return Gtk2::Ex::FormFactory::VBox->new(
        object      => "title",
        title       => '[gtk-convert]'.__ "Transcode",
        active_cond => sub {
            $self->selected_title
                && $self->project
                && $self->project->created;
        },
        active_depends => "project.created",
        no_frame       => 1,
        content        => [
            Video::DVDRip::GUI::Main->build_selected_title_factory,
            Gtk2::Ex::FormFactory::Table->new(
                expand => 1,
                layout => "
+>>>>>>>>>>>>>>>>>>>>>+>>>>>>>>>>>>>>>>>>>>>+
| Video & Bitrate     ^ Audio & General     |
+---------------------+---------------------|
^ Calculated Storage  | Operate             |
+---------------------+---------------------+
",
                content => [
                    Gtk2::Ex::FormFactory::VBox->new(
                        content => [
                            $self->build_container_factory,
                            $self->build_video_factory,
                            $self->build_video_bitrate_factory,
                        ],
                    ),
                    Gtk2::Ex::FormFactory::VBox->new(
                        content => [
                            $self->build_audio_factory,
                            $self->build_general_options_factory,
                        ],
                    ),
                    $self->build_calc_storage_factory,
                    $self->build_operate_factory,
                ],
            ),
        ],
    );
}

sub build_container_factory {
    my $self = shift;

    return Gtk2::Ex::FormFactory::Form->new(
        title   => __ "Container options",
        content => [
            Gtk2::Ex::FormFactory::Popup->new(
                label       => __ "Select container",
                label_group => "video_labels",
                attr        => "title.tc_container",
                expand_h    => 0,
                width       => 70,
            ),
        ],
    );
}

sub build_video_factory {
    my $self = shift;

    return Gtk2::Ex::FormFactory::Table->new(
        title      => __ "Video options",
        properties => { column_spacing => 5, },
        layout     => "
+>------------+[>--------------+[>--------------------+
| Codec Label | VC Popup       | Cfg Button           |
+-------------+[---------------+--------------+-------+
| ffmpeg Label| ffmpeg Entry   | KFI Label    | KFI   |
+-------------+[---------------+--------------+-------+
| FRate Label | Frame-Rate     |                      |
+-------------+[---------------+----------------------+
| 2pass Label | 2pass Yes/No   | Reuse log            | 
+-------------+----------------+----------------------+
| Deint Label | Deinterlacing                         |
+-------------+---------------------------------------+
| Filt Label  | Filters Button                        |
+-------------+---------------------------------------+
",
        content => [

            #-- 1st row
            Gtk2::Ex::FormFactory::Label->new(
                label       => __ "Video codec",
                label_group => "video_labels",
            ),
            Gtk2::Ex::FormFactory::Combo->new(
                attr  => "title.tc_video_codec",
                width => 80,
                tip   => __ "Choose a video codec here. If you don't "
                    . "find the codec you want in the list, just "
                    . "enter its transcode name by hand",
            ),
            Gtk2::Ex::FormFactory::Button->new(
                object => "title",
                label  => __ "Configure...",
                stock  => "gtk-preferences",
                tip => __ "The xvid4 video codec may be configured in detail "
                    . "if you have the xvid4conf utility installed",
                clicked_hook => sub {
                    $self->open_video_configure_window;
                },
                active_cond => sub {
                    $_[0] ? $_[0]->tc_video_codec =~ /^(xvid|xvid4)$/ : 0;
                },
                active_depends => ["title.tc_video_codec"],
            ),

            #-- 2nd row
            Gtk2::Ex::FormFactory::Label->new(
                label => __ "ffmpeg/af6 codec",
                for   => "sibling(1)"
            ),
            Gtk2::Ex::FormFactory::Combo->new(
                attr  => "title.tc_video_af6_codec",
                width => 80,
                tip   => __ "Some transcode video export modules support "
                    . "multiple video codecs, e.g. the ffmpeg module. "
                    . "Enter the name of the video codec the module "
                    . "should use here"
            ),
            Gtk2::Ex::FormFactory::Label->new( label => __ "Keyframes", ),
            Gtk2::Ex::FormFactory::Combo->new(
                attr  => "title.tc_keyframe_interval",
                width => 50,
                tip   => __ "This setting controls the number of frames "
                    . "after which a keyframe should be inserted "
                    . "into the video stream. The lower this value "
                    . "the better the quality, but filesize may "
                    . "increase as well",
                rules => ["positive-integer"],
            ),

            #-- 3rd row
            Gtk2::Ex::FormFactory::Label->new(
                label => __ "Video framerate",
            ),
            Gtk2::Ex::FormFactory::Combo->new(
                attr  => "title.tc_video_framerate",
                width => 80,
                tip   => __ "This is the video framerate of this movie. "
                    . "Only change this if transcode detected the "
                    . "framerate wrong, which may happen sometimes. "
                    . "If you want true framerate conversion check "
                    . "out the Filters dialog, which provides some "
                    . "video filters for this task",
                rules => ["positive-float"],
            ),

            #-- 4th row
            Gtk2::Ex::FormFactory::Label->new(
                label => __ "2-pass encoding",
            ),
            Gtk2::Ex::FormFactory::YesNo->new(
                attr => "title.tc_multipass",
                tip  => __ "2-pass encoding increases video quality and "
                    . "video bitrate accuracy significantly. But the "
                    . "whole transcoding needs nearly twice the time. "
                    . "It's strongly recommended to use 2-pass encoding "
                    . "whenever possible.",
                true_label => __"Yes",
                false_label  => __"No",
            ),
            Gtk2::Ex::FormFactory::CheckButton->new(
                label => __ "Reuse log",
                attr  => "title.tc_multipass_reuse_log",
                tip   => __ "During the first pass of a 2-pass transcoding "
                    . "a logfile with statistic information about the "
                    . "movie is written. If you didn't change any "
                    . "parameters affecting the video you may reuse "
                    . "this logfile for subsequent transcodings "
                    . "by activating this button. dvd::rip "
                    . "will skip the first pass saving much time."
            ),

            #-- 5th row
            Gtk2::Ex::FormFactory::Label->new(
                label => __ "Deinterlace mode",
            ),
            Gtk2::Ex::FormFactory::Popup->new(
                attr     => "title.tc_deinterlace",
                expand_h => 0,
                width    => 160,
                tip      => __ "Choose a deinterlacer algorithm here if the "
                    . "movie is interlaced, otherwise the transcoded "
                    . "movie is likely to have many artefacts. The "
                    . "'Smart deinterlacing' setting is recommended."
            ),

            #-- 5th row
            Gtk2::Ex::FormFactory::Label->new( label => __ "Filters", ),
            Gtk2::Ex::FormFactory::Button->new(
                object => "title",
                label => __ "Configure filters & preview...",
                tip   => __ "This opens a dialog which gives you access "
                    . "all filters transcode supports.",
                clicked_hook => sub {
                    $self->open_filters_window;
                },
            ),

        ],
    );
}

sub build_audio_factory {
    my $self = shift;

    return Gtk2::Ex::FormFactory::Table->new(
        title  => __ "Audio options",
        object => "audio_track",
        layout => "
+-----------+>------------+-------+
| DVD Track | Popup       | Multi |
+---------------------------------+
| Settings Notebook               |
|                                 |
+---------------------------------+
",
        content => [
            Gtk2::Ex::FormFactory::Label->new( label => __ "Select track", ),
            Gtk2::Ex::FormFactory::Popup->new(
                attr  => "title.audio_channel",
                width => 120
            ),
            Gtk2::Ex::FormFactory::Button->new(
                label        => __ "Multi...",
                stock        => "dvdrip-audio-matrix",
                clicked_hook => sub {
                    $self->open_multi_audio_window;
                },
                tip => __ "Manage multiple audio tracks"
            ),
            Gtk2::Ex::FormFactory::Notebook->new(
                attr    => "audio_track.tc_audio_codec",
                changed_hook_after => sub {
                    my $audio_track = $self->get_context->get_object("audio_track");
                    return if ! $audio_track;
                    if ( $audio_track->tc_audio_codec =~ /^(?:ac3|pcm)$/ ) {
                        $self->detect_audio_bitrate
                            unless $audio_track->bitrate;
                    }
                },
                content => [
                    $self->build_audio_codec_settings( type => "mp3" ),
                    $self->build_audio_codec_settings( type => "mp2" ),
                    $self->build_audio_codec_settings( type => "vorbis" ),
                    $self->build_audio_codec_settings( type => "ac3" ),
                    $self->build_audio_codec_settings( type => "pcm" ),
                ],
            ),
        ],
    );
}

sub build_audio_codec_settings {
    my $self   = shift;
    my %par    = @_;
    my ($type) = @par{'type'};

    my ( $title, @additional_widgets );

    my $bitrate_entry_class    = "Gtk2::Ex::FormFactory::Combo";
    my $samplerate_entry_class = "Gtk2::Ex::FormFactory::Combo";
    my $bitrate_attr           = "tc_${type}_bitrate";
    my $samplerate_attr        = "tc_${type}_samplerate";
    my $changed_hook;

    if ( $type eq 'mp3' ) {
        $title = "MP3";
        push @additional_widgets,
            Gtk2::Ex::FormFactory::Popup->new(
            attr  => "audio_track.tc_mp3_quality",
            label => __ "Quality",
            ),
            ;
    }
    elsif ( $type eq 'mp2' ) {
        $title                  = "MP2";
        $samplerate_entry_class = "Gtk2::Ex::FormFactory::Entry";

    }
    elsif ( $type eq 'vorbis' ) {
        $title = "Vorbis";
        push @additional_widgets,
            Gtk2::Ex::FormFactory::HBox->new(
            label     => __ "Quality",
            label_for => "tc_vorbis_quality",
            content   => [
                Gtk2::Ex::FormFactory::Combo->new(
                    name  => "tc_vorbis_quality",
                    attr  => "audio_track.tc_vorbis_quality",
                    width => 70,
                    rules => ["positive-integer"],
                ),
                Gtk2::Ex::FormFactory::CheckButton->new(
                    attr  => "audio_track.tc_vorbis_quality_enable",
                    label => __ "Use quality mode",
                ),
            ],
            ),
            ;
    }
    else {
        my $codec = $type eq 'ac3' ? "AC3" : "PCM";
        my $bitrate_attr_method = $bitrate_attr;
        $title = $codec;
        push @additional_widgets,
            Gtk2::Ex::FormFactory::Label->new(
                label => __x(
                    "{ac3_or_pcm} sound is passed through. Bit- and\n"
                        . "samplerate are detected from source,\n"
                        . "so you can't change them here.",
                    ac3_or_pcm => $codec
                ),
            );
        $bitrate_entry_class    = "Gtk2::Ex::FormFactory::Entry";
        $samplerate_entry_class = "Gtk2::Ex::FormFactory::Entry";
        $bitrate_attr           = "bitrate";
        $samplerate_attr        = "sample_rate";
    }

    if ( $type ne 'ac3' and $type ne 'pcm' ) {
        push @additional_widgets, (
            Gtk2::Ex::FormFactory::Popup->new(
                attr  => "audio_track.tc_audio_filter",
                label => __ "Filter",
            ),
            Gtk2::Ex::FormFactory::HBox->new(
                label   => __ "Volume rescale",
                content => [
                    Gtk2::Ex::FormFactory::Entry->new(
                        attr  => "audio_track.tc_volume_rescale",
                        width => 70,
                        rules => [ "positive-float", "or-empty" ],
                    ),
                    Gtk2::Ex::FormFactory::Button->new(
                        label        => __ "Scan value",
                        stock        => "dvdrip-scan-volume",
                        clicked_hook => sub {
                            $self->scan_rescale_volume;
                        },
                        active_cond    => sub { !$self->progress_is_active },
                        active_depends => "progress.is_active",
                    ),
                ],
            ),
            ),
            ;
    }

    return Gtk2::Ex::FormFactory::Form->new(
        attr         => "audio_track.audio_codec_${type}_form",
        inactive     => "invisible",
        title        => $title,
        content      => [
            Gtk2::Ex::FormFactory::HBox->new(
                label   => __ "Bit-/Samplerate",
                content => [
                    $bitrate_entry_class->new(
                        name  => "bit_samplerate_$type",
                        attr  => "audio_track.$bitrate_attr",
                        width => 70,
                        rules => ["positive-integer"],
                    ),
                    Gtk2::Ex::FormFactory::Label->new(
                        label => __ "kbit/s",
                        for   => "bit_samplerate_$type",
                    ),
                    $samplerate_entry_class->new(
                        name  => $type . $samplerate_attr,
                        attr  => "audio_track.$samplerate_attr",
                        width => 70,
                        rules => ["positive-integer"],
                    ),
                    Gtk2::Ex::FormFactory::Label->new(
                        label => __ "hz",
                        for   => $type . $samplerate_attr,
                    ),
                ],
            ),
            @additional_widgets,
        ],
    );
}

sub build_video_bitrate_factory {
    my $self = shift;

    my $context = $self->get_context;

    return Gtk2::Ex::FormFactory::Notebook->new(
        attr           => "title.tc_video_bitrate_mode",
        title          => __ "Video bitrate calculation",
        expand         => 1,
        active_cond    => sub { $_[0] ? $_[0]->tc_video_codec ne 'VCD' : 1 },
        active_depends => "title.tc_video_codec",
        content        => [
            Gtk2::Ex::FormFactory::Form->new(
                title   => __ "By target size",
                content => [
                    Gtk2::Ex::FormFactory::HBox->new(
                        label       => __ "Target media",
                        label_group => "vbr_calc_group",
                        content     => [
                            Gtk2::Ex::FormFactory::Popup->new(
                                attr  => "title.tc_disc_cnt",
                                width => 70,
                                tip   => __
                                    "Choose the desired number of discs here. "
                                    . "dvd::rip computes the target size from it "
                                    . "and optionally splits the result file accordingly.",
                            ),
                            Gtk2::Ex::FormFactory::Label->new(
                                label => "x",
                            ),
                            Gtk2::Ex::FormFactory::Combo->new(
                                width => 60,
                                attr  => "title.tc_disc_size",
                                tip   => __
                                    "Select the size of your media here (several "
                                    . "CD and DVD form factors). The unit is a true "
                                    . "megabyte (1024KB). You may enter an arbitrary "
                                    . "value if the preset don't fit your needs.",
                                rules => [ "positive-integer", "not-zero" ],
                            ),
                            Gtk2::Ex::FormFactory::Label->new(
                                label => __ "MB",
                            ),
                        ],
                    ),
                    Gtk2::Ex::FormFactory::HBox->new(
                        label       => __ "Target size",
                        label_group => "vbr_calc_group",
                        content     => [
                            Gtk2::Ex::FormFactory::Entry->new(
                                attr  => "title.tc_target_size",
                                width => 50,
                                tip   => __
                                    "This entry is computed based on the settings above, "
                                    . "but you may enter an arbitrary value as well.",
                                rules => [ "positive-integer", "not-zero" ],
                            ),
                            Gtk2::Ex::FormFactory::Label->new(
                                label => __ "MB",
                            ),
                            Gtk2::Ex::FormFactory::CheckButton->new(
                                attr  => "title.tc_video_bitrate_range",
                                label => __ "Consider frame range",
                                tip   => __
                                    "If you specified a frame range in the 'General options' "
                                    . "section activate this checkbutton if the video bitrate "
                                    . "calculation should be based on this frame range, and not on "
                                    . "the full title length. You need this if you entered the frame "
                                    . "range not just for testing purposes but also for the final "
                                    . "transcoding, e.g. for cutting off credits."
                            ),
                        ],
                    ),
                ],
            ),
            Gtk2::Ex::FormFactory::Form->new(
                title   => __ "By quality",
                content => [
                    Gtk2::Ex::FormFactory::Combo->new(
                        attr        => "title.tc_video_bpp_manual",
                        label       => __ "BPP value",
                        label_group => "vbr_calc_group",
                        width       => 80,
                        expand_h    => 0,
                        tip         => __
                            "BPP stands for Bits Per Pixel and is a measure for "
                            . "the video quality. Values around 0.25 give fair results "
                            . "(VHS quality), 0.4-0.5 very good quality near DVD.",
                        rules => [ "positive-float", "not-zero" ],
                    ),
                ],
            ),
            Gtk2::Ex::FormFactory::Form->new(
                title   => __ "Manually",
                content => [
                    Gtk2::Ex::FormFactory::HBox->new(
                        label       => __ "Video bitrate",
                        label_group => "vbr_calc_group",
                        content     => [
                            Gtk2::Ex::FormFactory::Entry->new(
                                attr     => "title.tc_video_bitrate_manual",
                                width    => 60,
                                expand_h => 0,
                                tip      => __
                                    "If you don't want a calculated video bitrate "
                                    . "just enter an arbitrary value here.",
                                rules => [ "positive-integer", "not-zero" ],
                            ),
                            Gtk2::Ex::FormFactory::Label->new(
                                label => __ "kbit/s",
                            ),
                        ],
                    ),
                ],
            ),
        ],
    );
}

sub build_general_options_factory {
    my $self = shift;

    my $context = $self->get_context;

    return Gtk2::Ex::FormFactory::Form->new(
        title   => __ "General options",
        expand  => 1,
        content => [
            Gtk2::Ex::FormFactory::HBox->new(
                label   => __ "Frame range",
                content => [
                    Gtk2::Ex::FormFactory::Entry->new(
                        attr  => "title.tc_start_frame",
                        width => 60,
                        rules => [
                            "positive-integer",
                            "or-empty",
                            sub {
                                my ($start) = @_;
                                my $title   = $self->selected_title;
                                my $end     = $title->tc_end_frame;
                                return __x( "Movie has only {number} frames",
                                    number => $title->frames )
                                    if $start > $title->frames;
                                $end ne ''
                                    && $start >= $end
                                    ? __
                                    "Start frame number must be smaller than end frame number"
                                    : "";
                            },
                        ],
                    ),
                    Gtk2::Ex::FormFactory::Label->new( label => " - ", ),
                    Gtk2::Ex::FormFactory::Entry->new(
                        attr  => "title.tc_end_frame",
                        width => 60,
                        rules => [
                            "positive-integer",
                            "or-empty",
                            sub {
                                my ($end) = @_;
                                my $title = $self->selected_title;
                                my $start = $title->tc_start_frame;
                                return __x( "Movie has only {number} frames",
                                    number => $title->frames )
                                    if $end > $title->frames;
                                $start ne ''
                                    && $start >= $end
                                    ? __
                                    "End frame number must be greated than start frame number"
                                    : "";
                            },
                        ],
                    ),
                ],
            ),
            Gtk2::Ex::FormFactory::Entry->new(
                attr  => "title.tc_options",
                label => __ "transcode options",
                width => 20,
            ),
            Gtk2::Ex::FormFactory::Combo->new(
                attr     => "title.tc_nice",
                label    => __ "Process nice level",
                width    => 60,
                expand_h => 0,
                rules    => [ "integer", "or-empty" ],
            ),
            Gtk2::Ex::FormFactory::YesNo->new(
                attr  => "title.tc_preview",
                label => __ "Preview window",
                true_label => __"Yes",
                false_label  => __"No",
            ),
            Gtk2::Ex::FormFactory::YesNo->new(
                attr  => "title.tc_psu_core",
                label => __ "Use PSU core",
                true_label => __"Yes",
                false_label  => __"No",
            ),
            Gtk2::Ex::FormFactory::HBox->new(
                label   => __ "Execute afterwards",
                content => [
                    Gtk2::Ex::FormFactory::Entry->new(
                        attr   => "title.tc_execute_afterwards",
                        expand => 1,
                        width  => 20,
                    ),
                    Gtk2::Ex::FormFactory::CheckButton->new(
                        attr  => "title.tc_exit_afterwards",
                        label => __ "and exit",
                    ),
                ],
            ),
        ],
    );
}

sub build_operate_factory {
    my $self = shift;

    return Gtk2::Ex::FormFactory::VBox->new(
        title   => __ "Operate",
        content => [
            Gtk2::Ex::FormFactory::HBox->new(
                content => [
                    Gtk2::Ex::FormFactory::Button->new(
                        label        => __ "Transcode",
                        stock        => "gtk-convert",
                        widget_group => "operate_buttons",
                        expand       => 1,
                        clicked_hook => sub {
                            $self->transcode;
                        },
                        active_cond    => sub { !$self->progress_is_active },
                        active_depends => "progress.is_active",
                    ),
                    Gtk2::Ex::FormFactory::Button->new(
                        label        => __ "View",
                        stock        => "gtk-media-play",
                        widget_group => "operate_buttons",
                        expand       => 1,
                        clicked_hook => sub {
                            $self->view_avi,;
                        },
                        active_cond    => sub { !$self->progress_is_active },
                        active_depends => "progress.is_active",
                    ),
                    Gtk2::Ex::FormFactory::Button->new(
                        label        => __ "Add to cluster",
                        stock        => "gtk-network",
                        widget_group => "operate_buttons",
                        expand       => 1,
                        clicked_hook => sub {
                            $self->add_to_cluster;
                        },
                        active_cond    => sub {
                            my $title = $self->selected_title;
                            return 0 if not $title;
                            return $title->tc_container ne 'vcd';
                        },
                        active_depends => "title.tc_container",
                    ),
                ],
            ),
            Gtk2::Ex::FormFactory::CheckButton->new(
                attr  => "title.tc_split",
                label => __ "Split files on transcoding",
            ),

        ],
    );
}

sub build_calc_storage_factory {
    my $self = shift;

    return Gtk2::Ex::FormFactory::Table->new(
        title  => __ "Calculated storage",
        layout => "
+>---------------+>--------]+>--+>---------------+>---------]+-----+
| V-Rate         | Value    | X | Video Size     |     Value | MB  |
+----------------+---------]+---+----------------+----------]+-----+
| BPP            | Value    |   | Audio Size     |     Value | MB  |
+----------------+----------+---+----------------+----------]+-----+
|                           |   | Other Size     |     Value | MB  |
+[---------------+----------+---+----------------+-----------+-----+
|                           |   | Separator                        |
|                           +---+----------------+----------]+-----+
_ Details                   |   | Total Size     |     Value | MB  |
+----------------+----------+---+----------------+-----------+-----+
",
        content => [

            #-- 1st row
            Gtk2::Ex::FormFactory::Label->new( label => __ "V-Rate:", ),
            Gtk2::Ex::FormFactory::Label->new(
                attr => "title.tc_video_bitrate",
            ),
            Gtk2::Ex::FormFactory::Label->new( label => "    " ),
            Gtk2::Ex::FormFactory::Label->new( label => __ "Video size:", ),
            Gtk2::Ex::FormFactory::Label->new(
                attr => "title.storage_video_size",
            ),
            Gtk2::Ex::FormFactory::Label->new( label => __ "MB", ),

            #		Gtk2::Ex::FormFactory::Label->new ( label => " " ),

            #-- 2nd row
            Gtk2::Ex::FormFactory::Label->new( label => __ "BPP:", ),
            Gtk2::Ex::FormFactory::Label->new(
                attr => "title.tc_video_bpp",
            ),
            Gtk2::Ex::FormFactory::Label->new( label => __ "Audio size:", ),
            Gtk2::Ex::FormFactory::Label->new(
                attr => "title.storage_audio_size",
            ),
            Gtk2::Ex::FormFactory::Label->new( label => __ "MB", ),

            #-- 3rd row
            Gtk2::Ex::FormFactory::Label->new( label => __ "Other size:", ),
            Gtk2::Ex::FormFactory::Label->new(
                attr => "title.storage_other_size",
            ),
            Gtk2::Ex::FormFactory::Label->new( label => __ "MB", ),

            #-- 4th row
            Gtk2::Ex::FormFactory::Button->new(
                label        => __ "Details...",
                stock        => "gtk-zoom-in",
                clicked_hook => sub {
                    $self->open_bitrate_calc_details;
                },
            ),
            Gtk2::Ex::FormFactory::HSeparator->new,

            #-- 5th row
            Gtk2::Ex::FormFactory::Label->new(
                label       => "<b>" . __("Total size:") . "</b>",
                with_markup => 1,
            ),
            Gtk2::Ex::FormFactory::Label->new(
                attr => "title.storage_total_size",
                bold => 1,
            ),
            Gtk2::Ex::FormFactory::Label->new(
                label       => "<b>" . __("MB") . "</b>",
                with_markup => 1,
            ),
        ],
    );
}

sub open_bitrate_calc_details {
    my $self = shift;

    require Video::DVDRip::GUI::BitrateCalc;

    my $bc = Video::DVDRip::GUI::BitrateCalc->new(
        form_factory => $self->get_form_factory );

    $bc->open_window;

    1;

}

sub open_filters_window {
    my $self = shift;

    require Video::DVDRip::GUI::Filters;

    my $filters = Video::DVDRip::GUI::Filters->new(
        form_factory => $self->get_form_factory );

    $filters->open_window;

    1;

}

sub open_multi_audio_window {
    my $self = shift;

    require Video::DVDRip::GUI::MultiAudio;

    my $maudio = Video::DVDRip::GUI::MultiAudio->new(
        form_factory => $self->get_form_factory );

    $maudio->open_window;

    1;
}

sub transcode {
    my $self            = shift;
    my %par             = @_;
    my ($subtitle_test) = @par{'subtitle_test'};

    return 1 if $self->progress_is_active;
    my $title = $self->selected_title;
    return 1 if not $title;

    my $job_planner   = $self->get_context->get_object("job_planner");
    my $exec_flow_gui = $self->get_context->get_object("exec_flow_gui");
    my $job           = $job_planner->build_transcode_job();

    $exec_flow_gui->start_job($job);

    1;
}

sub view_avi {
    my $self    = shift;
    my %par     = @_;
    my ($title) = @par{'title'};

    $title ||= $self->selected_title;
    return 1 if not $title;

    my $command = $title->get_view_avi_command(
        command_tmpl => $self->config('play_file_command'), );

    system( $command. " &" );
}

sub scan_rescale_volume {
    my $self = shift;

    my $title = $self->selected_title;
    return 1 if $self->progress_is_active;
    return 1 if not $title;

    if ( not $title->is_ripped ) {
        $self->message_window(
            message => __ "You first have to rip this title." );
        return 1;
    }

    my $job_planner   = $self->get_context->get_object("job_planner");
    my $exec_flow_gui = $self->get_context->get_object("exec_flow_gui");
    my $job           = $job_planner->build_scan_volume_job($title);

    $job->get_post_callbacks->add(sub {
        $self->get_context->update_object_attr_widgets(
            "audio_track.tc_volume_rescale", );
        1;
    });

    $exec_flow_gui->start_job($job);

    1;
}

sub add_to_cluster {
    my $self = shift;

    my $title = $self->selected_title;
    return 1 if not $title;

    if ( $title->tc_use_chapter_mode ) {
        $self->message_window(
            message => __ "Titles in chapter mode are not supported" );
        return 1;
    }

    if ( $title->tc_psu_core ) {
        $self->message_window(
            message => __ "PSU core mode currently not supported" );
        return 1;
    }

    if ( $title->project->rip_mode ne 'rip' ) {
        $self->message_window( message => __
                "Cluster mode is only supported\nfor ripped DVD's." );
        return 1;
    }

    if ( not $title->is_ripped ) {
        $self->message_window(
            message => __ "You first have to rip this title." );
        return 1;
    }

    if ( $title->tc_container eq 'vcd' ) {
        $self->message_window( message => __
                "MPEG processing is not supported for cluster mode." );
        return 1;
    }

    if (   $title->tc_start_frame ne ''
        or $title->tc_end_frame ne '' ) {
        $self->message_window(
            message => __ "WARNING: your frame range setting\n"
                . "is ignored in cluster mode" );
    }

    # calculate program stream units, if not already done
    $title->calc_program_stream_units
        if not $title->program_stream_units
        or not @{ $title->program_stream_units };

    $self->get_context_object("main")->cluster_control;

    my $cluster_gui = eval { $self->get_context_object('cluster_gui') };
    return if not $cluster_gui;
    return if not $cluster_gui->master;

    $cluster_gui->add_project(
        project => $self->project,
        title   => $title,
    );

    1;
}

sub create_wav {
    my $self = shift;

    my $title = $self->selected_title;
    return 1 if not $title;

    my $job_planner   = $self->get_context->get_object("job_planner");
    my $exec_flow_gui = $self->get_context->get_object("exec_flow_gui");
    my $job           = $job_planner->build_create_wav_job($title);

    $exec_flow_gui->start_job($job);

    1;
}

sub detect_audio_bitrate {
    my $self = shift;
    my ($codec_attr) = @_;

    my $title = $self->selected_title;
    return 1 if not $title;

    my $job_planner   = $self->get_context->get_object("job_planner");
    my $exec_flow_gui = $self->get_context->get_object("exec_flow_gui");
    my $job           = $job_planner->build_detect_audio_bitrate_job($title, $codec_attr);

    $exec_flow_gui->start_job($job);

    1;
}

sub open_video_configure_window {
    my $self = shift;

    my $title = $self->selected_title;
    return 1 if not $title;

    my $in_filename  = $title->multipass_log_dir . "/xvid4.cfg";
    my $out_filename = $in_filename;

    if ( not -f $in_filename ) {
        system(
            "xvid4conf '$out_filename' '$ENV{HOME}/.transcode/xvid4.cfg' &");
    }
    else {
        system("xvid4conf '$out_filename' '$in_filename' &");
    }

    1;
}

1;
