#!/usr/bin/env ruby # Rubyripper - A secure ripper for Linux/BSD/OSX # Copyright (C) 2007 Bouke Woudstra (rubyripperdev@gmail.com) # # This file is part of Rubyripper. Rubyripper 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 3 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, see ICONDIR=[ENV['PWD'], "/usr/local/share/icons/hicolor/128x128/apps"] RUBYDIR=[ENV['PWD'], File.dirname(__FILE__), "/usr/local/lib/ruby/site_ruby/1.8"] found_rrlib = false RUBYDIR.each do |dir| if File.exists?(file = File.join(dir, '/rr_lib.rb')) require file; found_rrlib = true ; break end end if found_rrlib == false puts "The main program logic file 'rr_lib.rb' can't be found!" exit() end begin require 'gtk2' rescue LoadError puts "The ruby-gtk2 library could not be found. Is it installed?"; exit() end class Main #the main window attr_reader :change_display, :instances def initialize @instances = {'Preferences' => false, 'GtkMetadata' => false, 'ShortMessage' => false, 'RipStatus' => false, 'DirExists' => false, 'MultipleFreedbHits' => false, 'Summary' => false} @current_instance = false @gtk_window = Gtk::Window.new('Rubyripper') ICONDIR.each{|dir| if File.exist?(file = File.join(dir, 'rubyripper.png')) : @gtk_window.icon = Gdk::Pixbuf.new(file) ; break end } @gtk_window.set_default_size(520, 400) #width, height @hbox1 = Gtk::HBox.new(false,5) create_buttonbox() create_signals() load_settings() welcome_message() @gtk_window.show_all() #The user interface is up, now load the library scan_drive() end def create_buttonbox #left side of the window, above the statusbar @vbuttonbox1 = Gtk::VButtonBox.new #child of @hbox1 @buttons = [Gtk::Button.new, Gtk::Button.new, Gtk::Button.new, Gtk::Button.new, Gtk::Button.new] @buttons[3].sensitive = false #only activate the RipCdNow button when a disc is found @buttontext = [Gtk::Label.new(_('Preferences')), Gtk::Label.new(_("Scan drive")), Gtk::Label.new(_("Open tray")), Gtk::Label.new(_("Rip cd now!")), Gtk::Label.new(_("Exit"))] @buttonicons = [Gtk::Image.new(Gtk::Stock::PREFERENCES, Gtk::IconSize::LARGE_TOOLBAR), Gtk::Image.new(Gtk::Stock::REFRESH, Gtk::IconSize::LARGE_TOOLBAR), Gtk::Image.new(Gtk::Stock::GOTO_BOTTOM, Gtk::IconSize::LARGE_TOOLBAR), Gtk::Image.new(Gtk::Stock::CDROM, Gtk::IconSize::LARGE_TOOLBAR), Gtk::Image.new(Gtk::Stock::QUIT, Gtk::IconSize::LARGE_TOOLBAR)] @vboxes = [Gtk::VBox.new, Gtk::VBox.new, Gtk::VBox.new, Gtk::VBox.new, Gtk::VBox.new] index = 0 @vboxes.each do |vbox| vbox.add(@buttonicons[index]) vbox.add(@buttontext[index]) @buttons[index].add(@vboxes[index]) index += 1 end @buttons.each{|button| @vbuttonbox1.pack_start(button,false,false)} @hbox1.pack_start(@vbuttonbox1,false,false,0) #pack the buttonbox into the mainwindow @gtk_window.add(@hbox1) end def create_signals @gtk_window.signal_connect("destroy") {savePreferences(); exit()} @gtk_window.signal_connect("delete_event") {savePreferences(); exit()} @buttons[0].signal_connect("released") {savePreferences(); show_info()} @buttons[1].signal_connect("released") {savePreferences(); scan_drive()} @buttons[2].signal_connect("released") {savePreferences(); handle_tray()} @buttons[3].signal_connect("released") {savePreferences(); start_rip()} @buttons[4].signal_connect("released") {savePreferences(); exit()} end def savePreferences if @current_instance == 'Preferences' @buttontext[0].text = _('Preferences') @buttonicons[0].stock = Gtk::Stock::PREFERENCES @instances['Preferences'].save #save any preferences when closing that window end end def exit `killall cdparanoia 2>&1` Gtk.main_quit end def change_display(object) #help function to manage the dynamic part of the window, the object is a class with a variable 'display' which contains everything unless @current_instance == false @hbox1.remove(@hbox1.children[-1]) end @current_instance = object.class.to_s #the name of the instance type @hbox1.add(object.display) object.display.show_all() end def load_settings #first set default settings, then override them with custom settings if a config file is found @settings = $rr_defaultSettings if File.exist?(settingsfile = File.join(ENV['HOME'], '.rubyripper/settings')) file = File.new(settingsfile,'r') while line = file.gets key, value = line.split('=', 2) value.rstrip! # remove the trailing newline character if value == "false" : value = false # replace the string with a bool elsif value == "true" : value = true # replace the string with a bool elsif value == "''" : value = '' #replace a string that contains two quotes with an empty string elsif value[0,1] == "#" : next #name of previous instances should not be loaded elsif value.to_i > 0 || value == '0' : value = value.to_i end if @settings.key?(key) : @settings[key] = value end end file.close() end if @settings['debug'] : Thread.abort_on_exception = true end end def welcome_message @instances['ShortMessage'] = ShortMessage.new(@settings['cdrom']) change_display(@instances['ShortMessage']) end def show_info @buttons.each{|button| button.sensitive = false} Thread.new do if @current_instance != 'Preferences' @buttontext[0].text = _('Disc info') @buttonicons[0].stock = Gtk::Stock::INFO unless @instances['Preferences'] : @instances['Preferences'] = Preferences.new(@settings) end @instances['Preferences'].display.page = 0 change_display(@instances['Preferences']) @buttons[0..2].each{|button| button.sensitive = true} ; if @instances['GtkMetadata'] : @buttons[3].sensitive = true end ; @buttons[4].sensitive = true elsif @instances['GtkMetadata'] change_display(@instances['GtkMetadata']) @buttons.each{|button| button.sensitive = true} else scan_drive() end end end def scan_drive @buttons.each{|button| button.sensitive = false} Thread.new do # Analyze audio-cd, don't look at freedb yet. If the current freedb string is the same don't use yaml for metadata @settings['cd'] = Disc.new(@settings['cdrom'], @settings['freedb'], self, @settings['verbose'], @settings.key?('cd') ? @settings['cd'].freedbString : '') if @settings['cd'].audiotracks != 0 # if true, a cd is found if @buttontext[2].text != _("Open tray") # We know there's a cd inside so make sure that eject is shown instead of close tray @buttontext[2].text = _("Open tray") @buttonicons[2].stock = Gtk::Stock::GOTO_BOTTOM end @instances['GtkMetadata'] = GtkMetadata.new(@settings['cd']) #build the cdinfo for the gui change_display(@instances['GtkMetadata']) #show this info on the display if @settings['freedb'] : @settings['cd'].md.freedb(@settings, @settings['first_hit']) end #Fetch the cddb info if user wants to @buttons.each{|button| button.sensitive = true} else @instances['GtkMetadata'] = false @instances['ShortMessage'].no_disc_found(@settings['cdrom']) change_display(@instances['ShortMessage']) @buttons[0..2].each{|button| button.sensitive = true} ; @buttons[4].sensitive = true end end end def handle_tray @buttons.each{|button| button.sensitive = false} Thread.new do if installed('eject') if @buttontext[2].text == _("Open tray") @instances['GtkMetadata'] = false @instances['ShortMessage'].open_tray(@settings['cdrom']) change_display(@instances['ShortMessage']) `eject #{@settings['cdrom']}` # spit the cd out @buttontext[2].text =_("Close tray") @buttonicons[2].stock = Gtk::Stock::GOTO_TOP @instances['ShortMessage'].ask_for_disc @buttons[0..2].each{|button| button.sensitive = true} ; @buttons[4].sensitive = true else @instances['ShortMessage'].close_tray(@settings['cdrom']) change_display(@instances['ShortMessage']) `eject --trayclose #{@settings['cdrom']}` # close the tray @buttontext[2].text = _("Open tray") @buttonicons[2].stock = Gtk::Stock::GOTO_BOTTOM scan_drive() end else @instances['ShortMessage'].no_eject_found change_display(@instances['ShortMessage']) @buttons[0..2].each{|button| button.sensitive = true} ; if @instances['GtkMetadata'] : @buttons[3].sensitive = true end ; @buttons[4].sensitive = true end end end def start_rip @buttons[0..3].each{|button| button.sensitive = false} @instances['GtkMetadata'].save_updates() if @settings['image'] @settings['tracksToRip'] = Array.new() @settings['tracksToRip'] << 0 else @settings['tracksToRip'] = @instances['GtkMetadata'].tracks_to_rip end @rubyripper = Rubyripper.new(@settings, self) # start a new instance, keep it out the Thread for later callbacks (yet_to_implement) Thread.new do if @rubyripper.settings_ok # configuration check do_rip() else @buttons[0..3].each{|button| button.sensitive = true} end end end def do_rip Thread.new do @buttons[0..3].each{|button| button.sensitive = false} if @instances['RipStatus'] == false : @instances['RipStatus'] = RipStatus.new() else @instances['RipStatus'].reset end change_display(@instances['RipStatus']) @rubyripper.start_rip # fire away the start shot end end def showSummary @buttons[0..3].each{|button| button.sensitive = true} @instances['Summary'] = Summary.new(@settings['editor'], @settings['filemanager'], @rubyripper.output_dirs[0], @rubyripper.gui.short_summary) change_display(@instances['Summary']) @instances['RipStatus'].reset() @rubyripper = false # some resetting of variables, I suspect some optimization of ruby otherwise would prevent refreshing end def update(modus, value=false) #Threading here is not really necessary, because none of these are cpu intensive. Thread.new do if modus == "error" @instances['ShortMessage'].show_message(value) change_display(@instances['ShortMessage']) sleep(5) change_display(@instances['GtkMetadata']) @buttons.each{|button| button.sensitive = true} elsif modus == "cddb_hit" && !value @instances['GtkMetadata'].update() if @current_instance != 'GtkMetadata' : change_display(@instances['GtkMetadata']) end elsif modus == "cddb_hit" && value @instances['MultipleFreedbHits'] = MultipleFreedbHits.new(value, @settings['cd'], self) change_display(@instances['MultipleFreedbHits']) elsif modus == "ripping_progress" progress = "%.3g" % (value * 100) @instances['RipStatus'].rip_bar.text = _("Ripping progress %s \%") % progress @instances['RipStatus'].rip_bar.fraction = value elsif modus == "encoding_progress" progress = "%.3g" % (value * 100) @instances['RipStatus'].enc_bar.text = _("Encoding progress %s \%") % [progress] @instances['RipStatus'].enc_bar.fraction = value elsif modus == "log_change" @instances['RipStatus'].textview.buffer.insert(@instances['RipStatus'].textview.buffer.end_iter, value) # First parameter is the last character + 1 in the log @instances['RipStatus'].textview.scroll_to_iter(@instances['RipStatus'].textview.buffer.end_iter, 0, true, 1, 1) elsif modus == "dir_exists" @instances['DirExists'] = DirExists.new(self, @rubyripper, value) change_display(@instances['DirExists']) elsif modus == "finished" showSummary() else puts _("Ehh.. There shouldn't be anything else. WTF?") puts _("Secret modus = %s") % [modus] end end end end class ShortMessage attr_reader :display, :no_disc_found, :open_tray, :close_tray, :ask_for_disc, :no_eject_found, :show_message def initialize(cdrom) @display = Gtk::Label.new(_("Welcome to rubyripper %s.\nScanning drive %s for an audio disc...") % [$rr_version, cdrom]) end def no_disc_found(cdrom) @display.text = _("No disc found in %s!\nPlease insert a disc and push 'Scan drive'.\n\nThe cdrom drive can be set in 'Preferences'.") % [cdrom] end def open_tray(cdrom) @display.text = _("Opening tray of drive %s") % [cdrom] end def close_tray(cdrom) @display.text = _("Closing tray of drive %s. \n\nThe drive will be scanned for an audio disc...") % [cdrom] end def ask_for_disc @display.text = _("Insert an audio-disc and press 'Close tray'.\nThe drive will automatically be scanned for a disc.\n\nIf the tray is already closed, press 'Scan drive'") end def no_eject_found @display.text = _("The eject utility is not found on your system!") end def show_message(message) message += _("\n\nThis display will automatically show\n the disc info within 5 seconds") @display.text = message end end class GtkMetadata attr_reader :update, :display, :save_updates, :tracks_to_rip def initialize(cdinfo) @cd = cdinfo @tracks_to_rip = Array.new discinfo_objects() #create all necessary objects for displaying the discinfo trackselection_objects() #create all necessary objects for displaying the trackselection update() pack_both() #pack them together so we can show this beauty to the world :) end def discinfo_objects #helpfunction for show_cdinfo @table10 = Gtk::Table.new(3,4,false) @table10.column_spacings = 5 @table10.row_spacings = 4 @table10.border_width = 7 #create objects @artist_label = Gtk::Label.new(_('Artist:')) ; @artist_label.set_alignment(0.0, 0.5) ; @artist_entry = Gtk::Entry.new @album_label = Gtk::Label.new(_('Album:')) ; @album_label.set_alignment(0.0, 0.5) ; @album_entry = Gtk::Entry.new @genre_label = Gtk::Label.new(_('Genre:')) ; @genre_label.set_alignment(0.0, 0.5) ; @genre_entry = Gtk::Entry.new ; @genre_entry.width_request = 100 @year_label = Gtk::Label.new(_('Year:')) ; @year_label.set_alignment(0.0, 0.5) ; @year_entry = Gtk::Entry.new ; @year_entry.width_request = 100 @var_checkbox = Gtk::CheckButton.new(_('Mark disc as various artist')) #add callback @var_checkbox.signal_connect("toggled") do if @var_checkbox.active? == true set_var_artist_in_table() else unset_var_artist_in_table() end end #pack objects in 2x4 table @table10.attach(@artist_label, 0,1,0,1, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column @table10.attach(@album_label,0,1,1,2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table10.attach(@artist_entry, 1,2,0,1, Gtk::FILL, Gtk::SHRINK, 0,0) #2nd column @table10.attach(@album_entry, 1, 2, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table10.attach(@genre_label, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #3rd column @table10.attach(@year_label, 2, 3, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table10.attach(@genre_entry, 3, 4, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #4th column @table10.attach(@year_entry, 3 , 4, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table10.attach(@var_checkbox, 0, 4, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) end def trackselection_objects #helpfunction for show_cdinfo @table20 = Gtk::Table.new(@cd.audiotracks + 1, 4, false) @table20.column_spacings = 5 @table20.row_spacings = 4 @table20.border_width = 7 #create objects and apply signals @all_tracks_button = Gtk::CheckButton.new(_('All')) ; @all_tracks_button.active = true #create checkbutton to select all/none tracks @check_track_array = Array.new ; @cd.audiotracks.times{|number| @check_track_array << Gtk::CheckButton.new((number + 1).to_s)} #create checkbutton for each track # Disable track selection buttons if we're ripping to a single file, it implies ripping the whole CD # if @settings['create_single_file'] == "true" # @check_track_array.each{|box| box.sensitive = false} # end @check_track_array.each{|tracknumber| tracknumber.active = true} #include all tracks by default @all_tracks_button.signal_connect("toggled") do @all_tracks_button.active? ? @check_track_array.each{|box| box.active = true} : @check_track_array.each{|box| box.active = false} #signal to toggle on/off all tracks end @trackname_label = Gtk::Label.new(_("Tracknames \(%s tracks\)") % [@cd.audiotracks]) @track_entry_array = Array.new ; @cd.audiotracks.times{@track_entry_array << Gtk::Entry.new} @length_label = Gtk::Label.new(_("Length \(%s\)") % [@cd.playtime]) @length_label_array = Array.new ; @cd.audiotracks.times{|number| @length_label_array << Gtk::Label.new(@cd.lengthText[number])} #pack objects in @cd.audiotracks + 1 by 3 table @table20.attach(@all_tracks_button, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 1st row @table20.attach(@trackname_label, 1, 3, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) #2nd + 3rd column (to later on allow various artist + trackname), 1st row @table20.attach(@length_label, 3, 4, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #4th column, 1st row @cd.audiotracks.times do |index| @table20.attach(@check_track_array[index], 0, 1, 1 + index, 2 + index, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 2nd row till end @table20.attach(@track_entry_array[index],1, 3, 1 + index, 2 + index, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) #2nd + 3rd column, 2nd row till end @table20.attach(@length_label_array[index],3, 4, 1 + index, 2 + index, Gtk::FILL, Gtk::SHRINK, 0, 0) #4th column, 2nd row till end end end def pack_both #create frame for discinfo objects @label10 = Gtk::Label.new ; @label10.set_markup(_("Disc info")) @frame10 = Gtk::Frame.new @frame10.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame10.label_widget = @label10 @frame10.border_width = 5 @frame10.add(@table10) #create scrolled window for trackselection_objects to allow for a lot of tracks @scrolled_window = Gtk::ScrolledWindow.new() @scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC) @scrolled_window.set_border_width(5) @scrolled_window.add_with_viewport(@table20) #create frame for trackselection_objects @label20 = Gtk::Label.new ; @label20.set_markup(_("Track selection")) @frame20 = Gtk::Frame.new() @frame20.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame20.label_widget = @label20 @frame20.border_width = 5 @frame20.add(@scrolled_window) #move both frames into a vbox @display = Gtk::VBox.new #One VBox to rule them all @display.pack_start(@frame10, false, false) @display.pack_start(@frame20, true, true) end def update() # Update gui with freedb info if not @cd.md.varArtists.empty? : @var_checkbox.active = true end @artist_entry.text = @cd.md.artist ; @album_entry.text = @cd.md.album @year_entry.text = @cd.md.year ; @genre_entry.text = @cd.md.genre @cd.audiotracks.times{|index| @track_entry_array[index].text = @cd.md.tracklist[index]} unless @cd.md.varArtists.empty? : set_var_artist_in_table() end end def set_var_artist_in_table @cd.audiotracks.times{|time| if @cd.md.varArtists[time] == nil: @cd.md.varArtists[time] = _('Unknown') end} #Fill with unknown if the artistfield is not there if @table20.children.include?(@var_artist_label) : @table20.remove(@var_artist_label) ; @var_artist_array.each{|object| @table20.remove(object)} end #remove the previous @var_artist_label = Gtk::Label.new(_('Artist')) @var_artist_array = Array.new ; @cd.audiotracks.times{|index| @var_artist_array << Gtk::Entry.new} @cd.audiotracks.times{|index| @var_artist_array[index].text = @cd.md.varArtists[index]} #remove current tracknames from array, as we're repacking them @table20.remove(@trackname_label) ; @track_entry_array.each{|object| @table20.remove(object)} #repack into @table20 @table20.attach(@var_artist_label, 1, 2, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #2nd column, 1st row @table20.attach(@trackname_label, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #3rd column, 1st row @cd.audiotracks.times do |index| @table20.attach(@var_artist_array[index], 1, 2, index + 1, index + 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table20.attach(@track_entry_array[index], 2, 3, index + 1, index + 2, Gtk::FILL, Gtk::SHRINK, 0, 0) end @table20.show_all() end def unset_var_artist_in_table @cd.md.undoVarArtist() #sets the names back if @table20.children.include?(@var_artist_label) @table20.remove(@var_artist_label) @var_artist_array.each{|object| @table20.remove(object)} end @table20.remove(@trackname_label) ; @track_entry_array.each{|object| @table20.remove(object)} @table20.attach(@trackname_label, 1, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #3rd column, 1st row @cd.audiotracks.times do |index| @table20.attach(@track_entry_array[index], 1, 3, index + 1, index + 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) end update() #get the updated info before displaying @table20.show_all() end def save_updates() # save all updated info from the user @cd.md.artist = @artist_entry.text @cd.md.album = @album_entry.text @cd.md.genre = @genre_entry.text @cd.md.year = @year_entry.text if @year_entry.text.to_i != 0 @cd.audiotracks.times do |index| @cd.md.tracklist[index] = @track_entry_array[index].text if @check_track_array[index].active? : @tracks_to_rip << index + 1 end end unless @cd.md.varArtists.empty? @cd.audiotracks.times{|index| @cd.varArtists[index] = @var_artist_array[index].text} end end end class Preferences attr_reader :display, :save def initialize(settings) @settings = settings @display = Gtk::Notebook.new # Create a notebook (multiple pages) ripobjects_frame1() ripobjects_frame2() ripobjects_frame3() codecobjects_frame1() codecobjects_frame2() codecobjects_frame3() freedbobjects_frame() otherobjects_frame1() otherobjects_frame2() otherobjects_frame3() pack_other_frames() load() end def load # load the settings #ripping settings @cdrom_entry.text = @settings['cdrom'] @cdrom_offset_spin.value = @settings['offset'].to_f @all_chunks_spin.value = @settings['req_matches_all'].to_f @err_chunks_spin.value = @settings['req_matches_errors'].to_f @max_spin.value = @settings['max_tries'].to_f @rip_entry.text = @settings['rippersettings'] @eject.active = @settings['eject'] @no_log.active = @settings['no_log'] @create_cue.active = @settings['create_cue'] @create_single_file.active = @settings['image'] #codec settings @flac.active = @settings['flac'] @vorbis.active = @settings['vorbis'] @mp3.active = @settings['mp3'] @wav.active = @settings['wav'] @other.active = @settings['other'] @flac_entry.text = @settings['flacsettings'] @vorbis_entry.text = @settings['vorbissettings'] @mp3_entry.text = @settings['mp3settings'] @other_entry.text = @settings['othersettings'] @playlist.active = @settings['playlist'] @maxThreads.value = @settings['maxThreads'].to_f @normalize.active = if @settings['normalize'] == false : 0 elsif @settings['normalize'] == "replaygain" : 1 else 2 end @modus.active = if @settings['gain'] == "album" : 0 else 1 end #freedb @enable_freedb.active = @settings['freedb'] @first_hit.active = @settings['first_hit'] @freedb_server_entry.text = @settings['site'] @freedb_username_entry.text = @settings['username'] @freedb_hostname_entry.text = @settings['hostname'] #other @basedir_entry.text = @settings['basedir'] @naming_normal_entry.text = @settings['naming_normal'] @naming_various_entry.text = @settings['naming_various'] @naming_image_entry.text = @settings['naming_image'] @verbose.active = @settings['verbose'] @debug.active = @settings['debug'] @editor_entry.text = @settings['editor'] @filemanager_entry.text = @settings['filemanager'] end def save # Update the settings hash from the preferences window #ripping settings @settings['cdrom'] = @cdrom_entry.text @settings['offset'] = @cdrom_offset_spin.value.to_i @settings['req_matches_all'] = @all_chunks_spin.value.to_i @settings['req_matches_errors'] = @err_chunks_spin.value.to_i @settings['max_tries'] = @max_spin.value.to_i @settings['rippersettings'] = @rip_entry.text @settings['eject'] = @eject.active? @settings['no_log'] = @no_log.active? @settings['create_cue'] = @create_cue.active? @settings['image'] = @create_single_file.active? #codec settings @settings['flac'] = @flac.active? @settings['vorbis'] = @vorbis.active? @settings['mp3'] = @mp3.active? @settings['wav'] = @wav.active? @settings['other'] = @other.active? @settings['flacsettings'] = @flac_entry.text @settings['vorbissettings'] = @vorbis_entry.text @settings['mp3settings'] = @mp3_entry.text @settings['othersettings'] = @other_entry.text @settings['playlist'] = @playlist.active? @settings['maxThreads'] = @maxThreads.value.to_i @settings['normalize'] = if @normalize.active == 0 : false elsif @normalize.active == 1 : "replaygain" else "normalize" end @settings['gain'] = if @modus.active ==0 : "album" else "track" end #freedb @settings['freedb'] = @enable_freedb.active? @settings['first_hit'] = @first_hit.active? @settings['site'] = @freedb_server_entry.text @settings['username'] = @freedb_username_entry.text @settings['hostname'] = @freedb_hostname_entry.text #other @settings['basedir'] = @basedir_entry.text @settings['naming_normal'] = @naming_normal_entry.text @settings['naming_various'] = @naming_various_entry.text @settings['naming_image'] = @naming_image_entry.text @settings['verbose'] = @verbose.active? @settings['debug'] = @debug.active? @settings['editor'] = @editor_entry.text @settings['filemanager'] = @filemanager_entry.text if @settings['debug'] : Thread.abort_on_exception = true end save_configfile() #also update the config file end def save_configfile if not File.directory?(dirname = File.join(ENV['HOME'], '.rubyripper')) : Dir.mkdir(dirname) end file = File.new(File.join(ENV['HOME'], '.rubyripper/settings'), 'w') @settings.each do |key, value| file.puts "#{key}=#{value}" end file.close() end #Today is a great day to start counting with 40 :) Actually I worked backwards and needed to make sure I had enough room in the beginning. def ripobjects_frame1 # Cdrom device frame @table40 = Gtk::Table.new(2,2,false) @table40.column_spacings = 5 @table40.row_spacings = 4 @table40.border_width = 7 #creating objects @cdrom_label = Gtk::Label.new(_("Cdrom device:")) ; @cdrom_label.set_alignment(0.0, 0.5) # Align to the left instead of center @cdrom_offset_label = Gtk::Label.new(_("Cdrom offset:")) ; @cdrom_offset_label.set_alignment(0.0, 0.5) @cdrom_entry = Gtk::Entry.new @cdrom_offset_spin = Gtk::SpinButton.new(-1500.0, 1500.0, 1.0) ; @cdrom_offset_spin.value = 0.0 #pack objects @table40.attach(@cdrom_label, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) @table40.attach(@cdrom_offset_label, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table40.attach(@cdrom_entry, 1, 2, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) @table40.attach(@cdrom_offset_spin, 1, 2, 1, 2, Gtk::FILL|Gtk::SHRINK, Gtk::SHRINK, 0, 0) #create frame @frame40 = Gtk::Frame.new(_('Cdrom device')) @frame40.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame40.border_width = 5 @frame40.add(@table40) end def ripobjects_frame2 # Ripping options frame @table50 = Gtk::Table.new(3,3,false) @table50.column_spacings = 5 @table50.row_spacings = 4 @table50.border_width = 7 #create objects @all_chunks = Gtk::Label.new(_("Match all chunks:")) ; @all_chunks.set_alignment(0.0, 0.5) @err_chunks = Gtk::Label.new(_("Match erroneous chunks:")) ; @err_chunks.set_alignment(0.0, 0.5) @max_label = Gtk::Label.new(_("Maximum trials (0 = unlimited):")) ; @max_label.set_alignment(0.0, 0.5) @all_chunks_spin = Gtk::SpinButton.new(2.0, 100.0, 1.0) @err_chunks_spin = Gtk::SpinButton.new(2.0, 100.0, 1.0) @max_spin = Gtk::SpinButton.new(0.0, 100.0, 1.0) @time1 = Gtk::Label.new(_("times")) @time2 = Gtk::Label.new(_("times")) @time3 = Gtk::Label.new(_("times")) #pack objects @table50.attach(@all_chunks, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column @table50.attach(@err_chunks, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table50.attach(@max_label, 0, 1, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) @table50.attach(@all_chunks_spin, 1, 2, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #2nd column @table50.attach(@err_chunks_spin, 1, 2, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table50.attach(@max_spin, 1, 2, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) @table50.attach(@time1, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #3rd column @table50.attach(@time2, 2, 3, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table50.attach(@time3, 2, 3, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) #connect a signal to @all_chunks to make sure @err_chunks get always at least the same amount of rips as @all_chunks @all_chunks_spin.signal_connect("value_changed") {if @err_chunks_spin.value < @all_chunks_spin.value : @err_chunks_spin.value = @all_chunks_spin.value end ; @err_chunks_spin.set_range(@all_chunks_spin.value,100.0)} #ensure all_chunks cannot be smaller that err_chunks. #create frame @frame50= Gtk::Frame.new(_('Ripping options')) @frame50.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame50.border_width = 5 @frame50.add(@table50) end def ripobjects_frame3 #Ripping related frame @table60 = Gtk::Table.new(4,3,false) @table60.column_spacings = 5 @table60.row_spacings = 4 @table60.border_width = 7 #create objects @rip_label = Gtk::Label.new(_("Pass cdparanoia options:")) ; @rip_label.set_alignment(0.0, 0.5) @eject= Gtk::CheckButton.new(_('Eject cd when finished')) @no_log = Gtk::CheckButton.new(_('Only keep logfile if correction is needed')) @create_cue = Gtk::CheckButton.new(_('Create cuesheet')) @create_single_file = Gtk::CheckButton.new(_('Rip CD to single file')) @rip_entry= Gtk::Entry.new #pack objects @table60.attach(@rip_label, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) @table60.attach(@eject, 0, 2, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table60.attach(@rip_entry, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) @table60.attach(@no_log, 0, 2, 2, 3, Gtk::FILL|Gtk::SHRINK, Gtk::SHRINK, 0, 0) @table60.attach(@create_cue, 0, 2, 3, 4, Gtk::FILL|Gtk::SHRINK, Gtk::SHRINK, 0, 0) @table60.attach(@create_single_file, 0, 2, 4, 5, Gtk::FILL|Gtk::SHRINK, Gtk::SHRINK, 0, 0) #create frame @frame60 = Gtk::Frame.new(_('Ripping related')) @frame60.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame60.border_width = 5 @frame60.add(@table60) #pack all frames into a single page @page1 = Gtk::VBox.new #One VBox to rule them all [@frame40, @frame50, @frame60].each{|frame| @page1.pack_start(frame,false,false)} @page1_label = Gtk::Label.new(_("Secure Ripping")) @display.append_page(@page1, @page1_label) end def codecobjects_frame1 # Select audio codecs frame @table70 = Gtk::Table.new(6,2,false) @table70.column_spacings = 5 @table70.row_spacings = 4 @table70.border_width = 7 #objects 1st column @flac = Gtk::CheckButton.new(_('Flac')) @vorbis = Gtk::CheckButton.new(_('Vorbis')) @mp3= Gtk::CheckButton.new(_('Lame Mp3')) @wav = Gtk::CheckButton.new(_('Wav')) @other = Gtk::CheckButton.new(_('Other')) @expander70 = Gtk::Expander.new(_('Show options for "Other"')) #objects 2nd column @flac_entry= Gtk::Entry.new() @vorbis_entry= Gtk::Entry.new() @mp3_entry= Gtk::Entry.new() @other_entry= Gtk::Entry.new() #fill expander @legend = Gtk::Label.new(_("%a=artist %g=genre %t=trackname %f=codec\n%b=album %y=year %n=track %va=various artist\n%o = outputfile %i = inputfile")) @expander70.add(@legend) #pack_objects @table70.attach(@flac, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 1st row @table70.attach(@vorbis, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 2nd row @table70.attach(@mp3, 0, 1, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 3rd row @table70.attach(@wav, 0, 2, 3, 4, Gtk::FILL, Gtk::SHRINK, 0, 0) #both columns, 4th row @table70.attach(@other, 0, 1, 4, 5, Gtk::FILL, Gtk::SHRINK, 0, 0) # 1st column, 5th row @table70.attach(@expander70, 0, 2, 5, 6, Gtk::FILL, Gtk::SHRINK, 0, 0) #both columns, 6th row @table70.attach(@flac_entry, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) #2nd column, 1st row @table70.attach(@vorbis_entry, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) #2nd column, 2nd row @table70.attach(@mp3_entry, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) # 2nd column, 3rd row @table70.attach(@other_entry, 1, 2, 4, 5, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK, 0, 0) # 2nd column, 5th row #create frame @frame70 = Gtk::Frame.new(_("Select audio codecs")) @frame70.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame70.border_width = 5 @frame70.add(@table70) # add the hbox in the frame end def codecobjects_frame2 #Encoding related frame @table80 = Gtk::Table.new(2,2,false) @table80.column_spacings = 5 @table80.row_spacings = 4 @table80.border_width = 7 #creating objects @playlist = Gtk::CheckButton.new(_("Create m3u playlist")) @maxThreads = Gtk::SpinButton.new(0.0, 10.0, 1.0) @maxThreadsLabel = Gtk::Label.new(_("Number of extra encoding threads")) #packing objects @table80.attach(@playlist, 0, 2, 0, 1, Gtk::FILL, Gtk::FILL, 0, 0) @table80.attach(@maxThreadsLabel, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL, 0, 0) @table80.attach(@maxThreads, 1, 2, 1, 2, Gtk::FILL, Gtk::FILL, 0, 0) #create frame @frame80 = Gtk::Frame.new(_("Codec related")) @frame80.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame80.border_width = 5 @frame80.add(@table80) end def codecobjects_frame3 #Normalize audio @table85 = Gtk::Table.new(2,1,false) @table85.column_spacings = 5 @table85.row_spacings = 4 @table85.border_width = 7 #creating objects @normalize = Gtk::ComboBox.new() @normalize.append_text(_("Don't standardize volume")) @normalize.append_text(_("Use replaygain on audio files")) @normalize.append_text(_("Use normalize on wav files")) @normalize.active=0 @modus = Gtk::ComboBox.new() @modus.append_text(_("Album / Audiophile modus")) @modus.append_text(_("Track modus")) @modus.active = 0 @modus.sensitive = false @normalize.signal_connect("changed") {if @normalize.active == 0 : @modus.sensitive = false else @modus.sensitive = true end} #packing objects @table85.attach(@normalize, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 0, 0) @table85.attach(@modus, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL, 0, 0) #create frame @frame85 = Gtk::Frame.new(_("Normalize to standard volume")) @frame85.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame85.border_width = 5 @frame85.add(@table85) #pack all frames into a single page @page2 = Gtk::VBox.new #One VBox to rule them all [@frame70, @frame80, @frame85].each{|frame| @page2.pack_start(frame,false,false)} @page2_label = Gtk::Label.new(_("Codecs")) @display.append_page(@page2, @page2_label) end def freedbobjects_frame #Freedb client configuration frame @table90 = Gtk::Table.new(5,2,false) @table90.column_spacings = 5 @table90.row_spacings = 4 @table90.border_width = 7 #creating objects @enable_freedb= Gtk::CheckButton.new(_("Enable freedb metadata fetching")) @first_hit= Gtk::CheckButton.new(_("Always use first freedb hit")) @freedb_server_label= Gtk::Label.new(_("Freedb server:")) ; @freedb_server_label.set_alignment(0.0, 0.5) @freedb_username_label= Gtk::Label.new(_("Username:")) ; @freedb_username_label.set_alignment(0.0, 0.5) @freedb_hostname_label= Gtk::Label.new(_("Hostname:")) ; @freedb_hostname_label.set_alignment(0.0, 0.5) @freedb_server_entry = Gtk::Entry.new @freedb_username_entry = Gtk::Entry.new @freedb_hostname_entry = Gtk::Entry.new #packing objects @table90.attach(@enable_freedb, 0, 2, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) #both columns, 1st row @table90.attach(@first_hit, 0, 2, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) #both columns, 2nd row @table90.attach(@freedb_server_label, 0, 1, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 3rd row @table90.attach(@freedb_username_label, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 4th row @table90.attach(@freedb_hostname_label, 0, 1, 4, 5, Gtk::FILL, Gtk::SHRINK, 0, 0) #1st column, 5th row @table90.attach(@freedb_server_entry, 1, 2 , 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) #2nd column, 3rd row @table90.attach(@freedb_username_entry, 1, 2, 3, 4, Gtk::FILL, Gtk::SHRINK, 0, 0) #2nd column, 4th row @table90.attach(@freedb_hostname_entry, 1, 2, 4, 5, Gtk::FILL, Gtk::SHRINK, 0, 0) #2nd column, 5th row #create frame @frame90 = Gtk::Frame.new(_("Freedb options")) # will contain the above @frame90.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame90.border_width = 5 @frame90.add(@table90) #pack frame @page3 = Gtk::VBox.new #One VBox to rule them all [@frame90].each{|frame| @page3.pack_start(frame,false,false)} @page3_label = Gtk::Label.new(_("Freedb")) @display.append_page(@page3, @page3_label) end def otherobjects_frame1 # Naming scheme frame @table100 = Gtk::Table.new(6,2,false) @table100.column_spacings = 5 @table100.row_spacings = 4 @table100.border_width = 7 #creating objects 1st column @basedir_label = Gtk::Label.new(_('Base directory:')) ; @basedir_label.set_alignment(0.0, 0.5) #set_alignment(xalign=0.0, yalign=0.5) @naming_normal_label = Gtk::Label.new(_('Standard:')) ; @naming_normal_label.set_alignment(0.0, 0.5) @naming_various_label = Gtk::Label.new(_('Various artists:')) ; @naming_various_label.set_alignment(0.0, 0.5) @naming_image_label = Gtk::Label.new(_('Single file image:')) ; @naming_image_label.set_alignment(0.0, 0.5) @example_label =Gtk::Label.new('') ; @example_label.set_alignment(0.0, 0.5) ; @example_label.wrap = true @expander100 = Gtk::Expander.new(_('Show options for "Filenaming scheme"')) #configure expander #@artist_label = Gtk::Label.new("%a = artist %b = album %f = codec %g = genre\n%va = various artists %n = track %t = trackname %y = year") @legend_label = Gtk::Label.new(_("%a=artist %g=genre %t=trackname %f=codec\n%b=album %y=year %n=track %va=various artist")) @expander100.add(@legend_label) #packing 1st column @table100.attach(@basedir_label, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@naming_normal_label, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@naming_various_label, 0, 1, 2, 3, Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@naming_image_label, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@example_label, 0, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0) #width = 2 columns, also maximise width @table100.attach(@expander100, 0, 2 , 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0) #creating objects 2nd column and connect signals to them @basedir_entry = Gtk::Entry.new @naming_normal_entry = Gtk::Entry.new @naming_various_entry = Gtk::Entry.new @naming_image_entry = Gtk::Entry.new @basedir_entry.signal_connect("key_release_event"){@example_label.text = get_example_filename_normal(@basedir_entry.text, @naming_normal_entry.text) ; false} @basedir_entry.signal_connect("button_release_event"){@example_label.text = get_example_filename_normal(@basedir_entry.text, @naming_normal_entry.text) ; false} @naming_normal_entry.signal_connect("key_release_event"){@example_label.text = get_example_filename_normal(@basedir_entry.text, @naming_normal_entry.text) ; false} @naming_normal_entry.signal_connect("button_release_event"){@example_label.text = get_example_filename_normal(@basedir_entry.text, @naming_normal_entry.text) ; false} @naming_various_entry.signal_connect("key_release_event"){@example_label.text = get_example_filename_various(@basedir_entry.text, @naming_various_entry.text) ; false} @naming_various_entry.signal_connect("button_release_event"){@example_label.text = get_example_filename_various(@basedir_entry.text, @naming_various_entry.text) ; false} @naming_image_entry.signal_connect("key_release_event"){@example_label.text = get_example_filename_various(@basedir_entry.text, @naming_image_entry.text) ; false} @naming_image_entry.signal_connect("button_release_event"){@example_label.text = get_example_filename_various(@basedir_entry.text, @naming_image_entry.text) ; false} #packing 2nd column @table100.attach(@basedir_entry, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@naming_normal_entry, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@naming_various_entry, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0) @table100.attach(@naming_image_entry, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK, 0, 0) #create frame @frame100 = Gtk::Frame.new(_("Filenaming scheme")) #will contain the above @frame100.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame100.border_width = 5 @frame100.add(@table100) end #Small table needed for setting programs #log file viewer | entry #file manager | entry def otherobjects_frame2 @table110 = Gtk::Table.new(2,2,false) @table110.column_spacings = 5 @table110.row_spacings = 4 @table110.border_width = 7 #creating objects @editor_label = Gtk::Label.new(_("Log file viewer: ")) ; @editor_label.set_alignment(0.0, 0.5) @filemanager_label = Gtk::Label.new(_("File manager: ")) ; @filemanager_label.set_alignment(0.0,0.5) @editor_entry = Gtk::Entry.new @filemanager_entry = Gtk::Entry.new #packing objects @table110.attach(@editor_label, 0,1,0,1,Gtk::FILL, Gtk::SHRINK, 0, 0) @table110.attach(@filemanager_label, 0,1,1,2,Gtk::FILL, Gtk::SHRINK, 0, 0) @table110.attach(@editor_entry, 1,2,0,1, Gtk::FILL, Gtk::SHRINK, 0, 0) @table110.attach(@filemanager_entry, 1,2,1,2, Gtk::FILL, Gtk::SHRINK, 0, 0) #create frame @frame110 = Gtk::Frame.new(_("Programs of choice")) @frame110.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame110.border_width = 5 @frame110.add(@table110) end #Small table for debugging #Verbose mode | debug mode def otherobjects_frame3 # Debug options frame @table120 = Gtk::Table.new(1,2,false) @table120.column_spacings = 5 @table120.row_spacings = 4 @table120.border_width = 7 #creating objects and packing them @verbose = Gtk::CheckButton.new(_('Verbose mode')) @debug = Gtk::CheckButton.new(_('Debug mode')) @table120.attach(@verbose, 0,1,0,1,Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK) @table120.attach(@debug, 1,2,0,1,Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK) #create frame @frame120 = Gtk::Frame.new(_("Debug options")) #will contain the above @frame120.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @frame120.border_width = 5 @frame120.add(@table120) end def pack_other_frames #pack all frames into a single page @page4 = Gtk::VBox.new() [@frame100, @frame110, @frame120].each{|frame| @page4.pack_start(frame,false,false)} @page4_label = Gtk::Label.new(_("Other")) @display.signal_connect("switch_page"){|a, b, page| if page == 3: @example_label.text = get_example_filename_normal(@basedir_entry.text, @naming_normal_entry.text) end} @display.append_page(@page4, @page4_label) end end class RipStatus attr_reader :textview, :rip_bar, :enc_bar, :display, :reset def initialize create_status_objects() pack_status_objects() reset() #reset to default text end def create_status_objects @textview = Gtk::TextView.new @textview.editable = false @textview.wrap_mode = Gtk::TextTag::WRAP_WORD @scrolled_window = Gtk::ScrolledWindow.new @scrolled_window.set_policy(Gtk::POLICY_NEVER,Gtk::POLICY_AUTOMATIC) @scrolled_window.border_width = 7 @scrolled_window.add(@textview) @enc_bar = Gtk::ProgressBar.new @rip_bar = Gtk::ProgressBar.new @enc_bar.pulse_step = 0.01 @rip_bar.pulse_step = 0.01 @hbox1 = Gtk::HBox.new(true,5) @vbox1 = Gtk::VBox.new(false,5) @vbox1.border_width = 5 @label1 = Gtk::Label.new @label1.set_markup(_("Ripping status")) @display = Gtk::Frame.new @display.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @display.label_widget = @label1 @display.border_width = 5 end def pack_status_objects @hbox1.pack_start(@rip_bar) @hbox1.pack_start(@enc_bar) @vbox1.pack_start(@scrolled_window) @vbox1.pack_start(@hbox1,false,false) @display.add(@vbox1) end def reset # load default values @enc_bar.text = _('Not yet started (0%)') @rip_bar.text = _('Not yet started (0%)') @enc_bar.fraction = 0.0 @rip_bar.fraction = 0.0 @textview.buffer.text = "" end end class DirExists attr_reader :display def initialize(gui, rubyripper, dirname) @label = Gtk::Label.new(_("The directory %s\nalready exist. What do you want rubyripper to do?") % [dirname]) @label.wrap = true @image = Gtk::Image.new(Gtk::Stock::DIALOG_QUESTION, Gtk::IconSize::DIALOG) @infobox = Gtk::HBox.new @infobox.add(@image) ; @infobox.add(@label) @separator = Gtk::HSeparator.new @buttons = [Gtk::Button.new, Gtk::Button.new, Gtk::Button.new] @labels = [Gtk::Label.new(_("Cancel rip")), Gtk::Label.new(_("Overwrite\ndirectory")), Gtk::Label.new(_("Auto rename\ndirectory"))] @images = [Gtk::Image.new(Gtk::Stock::CANCEL, Gtk::IconSize::LARGE_TOOLBAR), Gtk::Image.new(Gtk::Stock::CLEAR, Gtk::IconSize::LARGE_TOOLBAR), Gtk::Image.new(Gtk::Stock::OK, Gtk::IconSize::LARGE_TOOLBAR)] @hboxes = [Gtk::HBox.new, Gtk::HBox.new, Gtk::HBox.new] @buttonbox = Gtk::HBox.new 3.times do |index| @hboxes[index].pack_start(@images[index], false, false) #pack the image + label into a hbox @hboxes[index].pack_start(@labels[index], false, false) @buttons[index].add(@hboxes[index]) #put the hbox into the button @buttonbox.pack_start(@buttons[index], false, false, 10) #put the buttons into a hbox end @buttons[0].signal_connect("released") {gui.change_display(gui.instances['GtkMetadata'])} @buttons[1].signal_connect("released") {rubyripper.overwrite_dir() ; gui.do_rip() } @buttons[2].signal_connect("released") {rubyripper.postfix_dir() ; gui.do_rip() } @vbox = Gtk::VBox.new @vbox.border_width = 10 [@infobox, @separator, @buttonbox].each{|object| @vbox.pack_start(object,false,false,10)} @display = Gtk::Frame.new(_("Dir already exists...")) # will contain the above @display.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @display.border_width = 5 @display.add(@vbox) end end class MultipleFreedbHits attr_reader :display def initialize(value, cd, main_instance) @label1 = Gtk::Label.new(_("The freedb server reports multiple hits.\nWhich one would you prefer?")) @image1 = Gtk::Image.new(Gtk::Stock::DIALOG_QUESTION, Gtk::IconSize::DIALOG) @hbox1 = Gtk::HBox.new [@image1, @label1].each{|object| @hbox1.pack_start(object)} @combobox = Gtk::ComboBox.new(true) # text only value.each{|freedb_hit| @combobox.append_text(freedb_hit)} @separator1 = Gtk::HSeparator.new @hbox2 = Gtk::HBox.new @hbox2.pack_start(@combobox, false,false,5) @button1 = Gtk::Button.new @label2 = Gtk::Label.new(_("Ok")) @image2 = Gtk::Image.new(Gtk::Stock::OK, Gtk::IconSize::LARGE_TOOLBAR) @hbox3 = Gtk::HBox.new [@image2, @label2].each{|object| @hbox3.pack_start(object,false,false,15)} @button1.add(@hbox3) @hbox4 = Gtk::HBox.new @hbox4.pack_start(@button1,true,false) @vbox1 = Gtk::VBox.new @vbox1.border_width = 10 [@hbox1, @hbox2, @separator1, @hbox4].each{|object| @vbox1.pack_start(object,false,false,10)} @display = Gtk::Frame.new(_("Multiple hits found...")) # will contain the above @display.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @display.border_width = 5 @display.add(@vbox1) @button1.signal_connect("released") do Thread.new do main_instance.change_display(main_instance.instances['GtkMetadata']) if @combobox.active == -1 : cd.md.freedbChoice(0) else cd.md.freedbChoice(@combobox.active) end end end end end class Summary attr_reader :display def initialize(editor, filemanager, directory, summary) @label1 = Gtk::Label.new(_("Rubyripper is finished with ripping the cd.\nA short summary is shown below.")) @image1 = Gtk::Image.new(Gtk::Stock::DIALOG_INFO, Gtk::IconSize::DIALOG) @hbox1 = Gtk::HBox.new() [@image1, @label1].each{|object| @hbox1.pack_start(object)} @hbox1.border_width = 10 @separator1 = Gtk::HSeparator.new @textview = Gtk::TextView.new @textview.editable = false @scrolled_window = Gtk::ScrolledWindow.new @scrolled_window.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_NEVER) @scrolled_window.border_width = 7 @scrolled_window.add(@textview) @textview.buffer.insert(@textview.buffer.end_iter, summary) @button1 = Gtk::Button.new() @label2 = Gtk::Label.new(_("Open log file")) @image2 = Gtk::Image.new(Gtk::Stock::EXECUTE, Gtk::IconSize::LARGE_TOOLBAR) @hbox2 = Gtk::HBox.new() [@image2, @label2].each{|object| @hbox2.pack_start(object)} @button1.add(@hbox2) @button1.signal_connect("released"){Thread.new{if installed(editor.split()[0]) : `#{editor} "#{directory + '/ripping.log'}"` else puts _("%s is not found on your system!") % [editor.split()[0]] end}} @button2 = Gtk::Button.new() @label3 = Gtk::Label.new(_("Open directory")) @image3 = Gtk::Image.new(Gtk::Stock::OPEN, Gtk::IconSize::LARGE_TOOLBAR) @hbox3 = Gtk::HBox.new() [@image3, @label3].each{|object| @hbox3.pack_start(object)} @button2.add(@hbox3) @button2.signal_connect("released"){Thread.new{if installed(filemanager.split()[0]) : `#{filemanager} "#{directory}"` else puts _("%s is not found on your system!") % [filemanager.split()[0]] end}} @hbox4 = Gtk::HBox.new(true, 5) #put the two buttons in a box [@button1, @button2].each{|object| @hbox4.pack_start(object)} @vbox1 = Gtk::VBox.new(false,10) @vbox1.pack_start(@hbox1,false,false) @vbox1.pack_start(@separator1,false,false) @vbox1.pack_start(@scrolled_window,false,false) #maximize the space for displaying the tracks @vbox1.pack_start(@hbox4,false,false) @display = Gtk::Frame.new(_("Ripping and encoding is finished")) @display.set_shadow_type(Gtk::SHADOW_ETCHED_IN) @display.border_width = 5 @display.add(@vbox1) end end if __FILE__ == $0 Gtk.init Main.new() Gtk.main end