#!/usr/bin/ruby -w # $Id: euphoria,v 1.41 2006/09/07 13:38:26 tilman Exp $ require "ecore" require "ecore_x" require "ecore_evas" require "edje" require "esmart" require "esmart_draggies" require "esmart_container" require "xmmsclient" require "xmmsclient_ecore" require "singleton" require "yaml" require "find" require "fileutils" require "euphoria/playlist" require "euphoria/playlist_item" require "euphoria/slider" require "euphoria/volume_box" require "euphoria/playtime_updater" require "euphoria/playback_status_handler" require "euphoria/file_dialog" Config = Struct.new("Config", :ipc_path, :theme, :time_display_elapsed) # backwards compatibility w/ DrFeelgood and earlier unless Xmms.respond_to?(:userconfdir) def Xmms.userconfdir File.join(File.expand_path("~"), ".xmms2") end end class Euphoria DATA_DIR = "/usr/local/share/euphoria" DATA_DIR_PRIV = File.join(Xmms.userconfdir, "clients", "euphoria") include Singleton attr_reader :xmms, :ee, :edje def initialize @edje = nil @xmms = nil @volume_box = nil # settings unless File.directory?(DATA_DIR_PRIV) FileUtils.mkdir_p(DATA_DIR_PRIV) end @config_file = DATA_DIR_PRIV + "/config.yaml" load_config init_xmms init_gui blk = lambda { |item| ui_fill_track_info(item) } @playlist = Playlist.new(@xmms, blk) setup_callbacks @playtime_updater = PlaytimeUpdater.new(xmms) do |current_pos| ui_refresh_time(current_pos) # refresh the seeker if !@playlist.current_item.nil? d = @playlist.current_item.duration if d > 0 ui_refresh_seeker(current_pos / d.to_f) end end end PlaybackStatusHandler.new(xmms) do |state| @playback_state = state signal_playback_state @playtime_updater.enabled = (@playback_state == Xmms::Client::PLAY) end # is repeat enabled? s = @xmms.configval_get("playlist.repeat_all").wait.value @repeat = (s == "1") @edje.emit_signal("TOGGLE_REPEAT_MODE", "Euphoria") if @repeat @sliders = {} unless @edje.data("has_volume_slider").nil? @sliders["volume"] = VolumeSlider.new(@edje, @xmms, "player.slider.volume") end if @edje.part_exists?("vol_display_text") # FIXME Maybe rename the part to volume_box @volume_box = VolumeBox.new(@edje, @xmms, "player.volumeBox") end =begin unless @edje.data("has_eq_slider").nil? 1.upto(10) do |i| p = "player.slider.eq.band%02i" % i k = "equalizer.gain#{i - 1}" @sliders[k] = EqSlider.new(@edje, @xmms, p, k) end end =end handle_current_pos(@xmms.playlist_current_pos.wait) end def show if @edje.data("has_separate_playlist").nil? @playlist.show(@theme, false) end @ee.show end def save_config File.open(@config_file, "w") { |fo| YAML.dump(@config, fo) } end def show_file_dialog if @file_dialog_theme.nil? puts "file dialog edje not found" return end FileDialog.open(@file_dialog_theme) do |sel| if File.directory?(sel) files = [] Find.find(sel) { |f| files << f if File.file?(f) } files.sort.each do |f| @xmms.playlist_add("file://" + f).wait end elsif File.exists?(sel) @xmms.playlist_add("file://" + sel).wait end end end private def init_gui @ee = Ecore::Evas::SoftwareX11.new @ee.title = "Euphoria" @ee.name_class = ["Euphoria", "Euphoria"] @ee.borderless = true #@ee.evas.font_path_append("/usr/X11R6/lib/X11/fonts/TTF") #@ee.evas.font_path_append(ENV["HOME"] + "/.fonts") @ee.on_pre_render { Edje::thaw } @ee.on_post_render { Edje::freeze } @ee.on_resize do x, y, w, h = @ee.geometry @edje.resize(w, h) @dragger.resize(w, h) end @dragger = Esmart::Draggies.new(@ee) @dragger.name = "dragger" @dragger.button = 1 @dragger.show @theme = find_theme(@config.theme) raise "Cannot find theme - #{@config.theme}" if @theme.nil? if Edje.collections(@theme).include?("esmart.filedialog") @file_dialog_theme = @theme else @file_dialog_theme = find_theme("file_dialog") end @edje = Edje::Edje.new(@ee.evas) @edje.load(@theme, "euphoria") @edje.name = "edje" @edje.show w, h = @edje.get_size_max @ee.set_size_max(w, h) w, h = @edje.get_size_min @ee.set_size_min(w, h) @ee.resize(w, h) @ee.shaped = !@edje.data("shaped").nil? ui_refresh_seeker(0) end def init_xmms @xmms = Xmms::Client.new("Euphoria") @xmms.connect(ENV["XMMS_PATH"] || @config.ipc_path) @xmms.add_to_ecore_mainloop @xmms.on_disconnect do puts "daemon exited, shutting down" Ecore.main_loop_quit end end def setup_callbacks @edje.on_signal("quit") do Ecore::main_loop_quit end @edje.on_signal("close") do Ecore::main_loop_quit end @edje.on_signal("playback.play") do case @playback_state when Xmms::Client::PLAY @xmms.playback_stop.wait sleep(0.5) # evil hack, fix xmms2d instead @xmms.playback_start.wait else @xmms.playback_start.wait end end @edje.on_signal("playback.stop") do @xmms.playback_stop.wait end @edje.on_signal("playback.pause") do case @playback_state when Xmms::Client::PLAY @xmms.playback_pause.wait when Xmms::Client::PAUSE @xmms.playback_start.wait end end @edje.on_signal("playback.next") do @xmms.playlist_set_next_rel(1).wait @xmms.playback_tickle.wait if @playback_state != Xmms::Client::PLAY @xmms.playback_start.wait end end @edje.on_signal("playback.prev") do @xmms.playlist_set_next_rel(-1).wait @xmms.playback_tickle.wait if @playback_state != Xmms::Client::PLAY @xmms.playback_start.wait end end @edje.on_signal("TOGGLE_TIME_DISPLAY_MODE") do @config.time_display_elapsed = !@config.time_display_elapsed end @edje.on_signal("DEBUG") do |sig, source| puts source end @edje.on_signal("playlist.open") { @playlist.show(@theme, true) } @edje.on_signal("file_dialog.open") do show_file_dialog end @edje.on_signal("TOGGLE_REPEAT_MODE") do |sig, source| # don't react on our own emission next if source == "Euphoria" @repeat = !@repeat v = @repeat ? "1" : "0" @xmms.configval_set("playlist.repeat_all", v).wait end @xmms.broadcast_configval_changed.notifier do |res| k = res.value.keys.first v = res.value.values.first case k when "playlist.repeat_all" tmp = (v == "1") if tmp != @repeat @repeat = tmp @edje.emit_signal("TOGGLE_REPEAT_MODE", "Euphoria") end when /equalizer\.gain(\d+)/ @sliders[k].value = v.to_f end end @xmms.broadcast_playback_volume_changed.notifier do |res| if @edje.data("has_volume_slider") @sliders["volume"].value = res.value end if @edje.part_exists?("vol_display_text") @volume_box.value = res.value end end @xmms.broadcast_playlist_current_pos.notifier do |res| handle_current_pos(res) end end def handle_current_pos(res) begin pos = res.value rescue Xmms::Result::ValueError else ui_fill_track_info(@playlist[pos]) end end def ui_fill_track_info(item) unless item.nil? if item.channel.nil? msg = Edje::Message.new(0, item.artist, item.title, item.album) else msg = Edje::Message.new(0, "", item.title, "") end @edje.send_message(msg) end end def ui_refresh_time(time) return unless @edje.part_exists?("player.time") fmt = "%i:%02i" unless @config.time_display_elapsed time = @playlist.current_item.duration - time fmt = "-" + fmt end tmp = fmt % [time / 60, time % 60] @edje.part("player.time").text = tmp end def ui_refresh_seeker(pos) if @edje.part_exists?("seeker") @edje.part("seeker").set_drag_value(pos, 0.1) #@edje.thaw #@edje.evas.render end end def signal_playback_state sig = case @playback_state when Xmms::Client::PAUSE "PLAYBACK_STATE_PAUSED" when Xmms::Client::PLAY "PLAYBACK_STATE_PLAYING" else "PLAYBACK_STATE_STOPPED" end @edje.emit_signal(sig, "Euphoria") end def load_config @config = nil if File.exist?(@config_file) File.open(@config_file) { |fo| @config = YAML.load(fo) } end if @config.nil? || !@config.is_a?(Config) @config = Config.new @config.ipc_path = nil @config.theme = "winter" @config.time_display_elapsed = true end end def find_theme(name) dirs = [DATA_DIR_PRIV, DATA_DIR] dirs.each do |dir| tmp = File.join(dir, "themes/#{name}.edj") return tmp if File.exist?(tmp) end nil end end $x = Euphoria.instance Euphoria.instance.show Ecore::main_loop_begin Euphoria.instance.save_config