3 #$: << File.expand_path(File.dirname(FILE) + “/../lib”))
5 #require 'libgruxclient'
8 require 'xmmsclient_glib'
13 class Grux::ClientWin < Gtk::VBox
17 @server = Xmms::Client.new( 'Grux' )
19 @infoBoxWin = Gtk::ScrolledWindow.new
20 @upperBox = Gtk::HBox.new
21 @leftUpperBox = Gtk::VBox.new
22 @infoBox = Gtk::VBox.new
23 @cntrlBtnBox = Gtk::VButtonBox.new
24 @statusLblBoxWin = Gtk::ScrolledWindow.new
25 @statusLblBox = Gtk::VBox.new
26 @playlistViewWin = Gtk::ScrolledWindow.new
27 @statusBar = Gtk::Statusbar.new
30 @playBtn = Gtk::Button.new('_Play/Pause'),
31 @stopBtn = Gtk::Button.new('_Stop'),
32 @nextBtn = Gtk::Button.new('_Next'),
33 @prevBtn = Gtk::Button.new('Pre_vious'),
34 @rndmBtn = Gtk::Button.new('_Random'),
35 @rptBtn = Gtk::ToggleButton.new('Repeat _All', true),
36 @rpt1Btn = Gtk::ToggleButton.new('Repeat _One', true)
39 @stateLbl = Gtk::Label.new,
40 @playbackLbl = Gtk::Label.new,
41 @nextSongLbl = Gtk::Label.new
44 @cntrlbtns.each do |button|
45 @cntrlBtnBox.pack_start button
47 @cntrlBtnBox.layout_style = Gtk::ButtonBox::START
48 @statusLbls.each do |label|
49 @statusLblBox.pack_start label, false
52 @infoBoxWin.add_with_viewport @infoBox
53 @statusLblBoxWin.add_with_viewport @statusLblBox
54 @upperBox.pack_start @cntrlBtnBox, false
55 @upperBox.pack_start @infoBoxWin
56 @upperBox.pack_start @statusLblBoxWin
58 @playlistTextRenderer = Gtk::CellRendererText.new
59 @playlistView = Gtk::TreeView.new
60 @playlistList = Gtk::ListStore.new( String, String, String )
61 @playlistColumns = [ 'id', 'artist', 'title' ]
62 @playlistColumns.each_with_index do |tag, index|
63 @playlistView.append_column Gtk::TreeViewColumn.new( tag, @playlistTextRenderer, :text => index )
65 @playlistViewWin.add @playlistView
67 self.pack_start @upperBox
68 self.pack_start @playlistViewWin
69 self.pack_end @statusBar, false
73 @server.connect( ENV['XMMS_PATH'] )
74 @server.add_to_glib_mainloop
76 @statusBar.push( @statusBar.get_context_id( "connection" ), "Failed to connect to #{ENV['XMMS_PATH']}" )
79 @playBtn.signal_connect :clicked do
82 @stopBtn.signal_connect :clicked do
85 @nextBtn.signal_connect :clicked do
86 self.step_in_playlist 1
88 @prevBtn.signal_connect :clicked do
89 self.step_in_playlist -1
91 @rptBtnClkdHndlr = @rptBtn.signal_connect :clicked do
92 self.toggle_repeat_all
94 @rpt1BtnClkdHndlr = @rpt1Btn.signal_connect :clicked do
95 self.toggle_repeat_one
98 @playlistView.signal_connect :row_activated do |view, path, column|
99 @server.playlist_set_next( path.to_str.to_i ).notifier do
100 @server.playback_tickle.notifier do
107 @server.broadcast_coll_changed do
109 @server.broadcast_config_value_changed do |*foo|
112 @server.broadcast_mediainfo_reader_status do
114 @server.broadcast_medialib_entry_added do
116 @server.broadcast_medialib_entry_changed do
118 @server.broadcast_playback_current_id.notifier do |id|
119 self.handle_current_song id
121 @server.broadcast_playback_status.notifier do |playing|
122 self.handle_playback_status playing
124 @server.broadcast_playback_volume_changed do
126 @server.broadcast_playlist_changed do
128 @server.broadcast_playlist_current_pos.notifier do |pos|
129 self.handle_current_pos pos
131 @server.broadcast_playlist_loaded do
133 @server.broadcast_quit do
140 if @playbackState == 1
141 @server.playback_pause.notifier do |res|
142 @statusBar.push( @statusBar.get_context_id( "playback" ), "Paused playback" )
145 elsif @playbackState == 0 || 2
146 @server.playback_start.notifier do |res|
147 @statusBar.push( @statusBar.get_context_id( "playback" ), "Started playback" )
151 warn "Playbackstate unknown"
152 @server.playback_start.notifier do |res|
153 @statusBar.push( @statusBar.get_context_id( "playback" ), "Started playback" )
160 @server.playback_stop.notifier do |res|
161 @statusBar.push( @statusBar.get_context_id( "playback" ), "Stopped playback" )
166 def step_in_playlist( offset = 1 )
167 @server.playlist_set_next_rel( offset ).notifier do
168 @server.playback_tickle.notifier do |res|
169 @statusBar.push( @statusBar.get_context_id( "playback" ), "Skipped playback by #{offset} song#{offset.abs >= 1 ? "s" : ''}" )
176 def handle_playback_status( status )
177 @playbackState = status
178 @stateLbl.text = case status
179 when 0 then "stopped"
180 when 1 then "playing"
187 def handle_current_song( id )
188 songpath = Gtk::TreePath.new( @currentPlaylist.index id )
189 @playlistView.scroll_to_cell( songpath, nil, true, 0.5, 0.5 )
190 @playlistView.set_cursor( songpath, nil, false )
191 @server.medialib_get_info( id ).notifier do |songinfo|
193 @playbackLbl.text = ""
194 @infoBox.each { |child| @infoBox.remove child }
196 songinfo.each_key do |key|
197 songinfo[key].each_pair do |src,value|
198 @playbackLbl.text += "[#{src}] #{key} = #{value}\n"
199 infos[key] = ( ( infos[key] ? infos[key] + "\n" : "" ) + "#{value} (#{src})" )
202 [ :artist, :title, :album ].each do |key|
203 @infoBox.pack_start( Gtk::Frame.new( key.to_s ).add( Gtk::Label.new( infos.delete( key ) ) ) )
205 infos.each_pair do |key, value|
207 @infoBox.pack_start( Gtk::Frame.new( key.to_s ).add( Gtk::Label.new( value ) ) )
210 @infoBox.pack_end( Gtk::Frame.new( key.to_s ).add( Gtk::Label.new( value ) ) )
218 def handle_current_pos( pos )
219 #@server.playlist.entries.notifier do |playlist|
220 # @server.medialib_get_info( playlist[pos[:position]] ).notifier do |songinfo|
221 # @nextSongLbl.text = ""
222 # songinfo.each_pair do |key, info|
223 # info.each_pair do |src, value|
224 # @nextSongLbl.text += "[#{src}] #{key} = #{value}\n"
234 def handle_playlist( playlist )
235 @currentPlaylist = playlist
236 playlist.each_with_index do |id, index|
237 current_row = @playlistList.append
238 current_row[0] = index.to_s
239 @server.medialib_get_info( id ).notifier do |songinfo|
240 current_row[1] = songinfo[:artist] ? songinfo[:artist].first[1] : "NONE"
241 current_row[2] = songinfo[:title] ? songinfo[:title].first[1] : "NONE"
245 @playlistView.model = @playlistList
249 def handle_repeat_all_state( state )
250 @currentconfig[:"playlist.repeat_all"] = ( state ? "1" : "0" )
251 @rptBtn.signal_handler_block( @rptBtnClkdHndlr ) do
252 @rptBtn.active = state
256 def handle_repeat_one_state( state )
257 @currentconfig[:"playlist.repeat_one"] = ( state ? "1" : "0" )
258 @rpt1Btn.signal_handler_block( @rpt1BtnClkdHndlr ) do
259 @rpt1Btn.active = state
263 def toggle_repeat_all
264 if @currentconfig[:"playlist.repeat_all"] == "1"
265 @server.config_set_value( "playlist.repeat_all", "0" ).notifier do |res|
266 @server.config_get_value( "playlist.repeat_all" ).notifier do |value|
267 self.handle_repeat_all_state( value == "1" ? true : false )
272 elsif @currentconfig[:"playlist.repeat_all"] == "0"
273 @server.config_set_value( "playlist.repeat_all", "1" ).notifier do |res|
274 @server.config_get_value( "playlist.repeat_all" ).notifier do |value|
275 self.handle_repeat_all_state( value == "1" ? true : false )
281 warn "Unknown state: #{@currentconfig[:"playlist.repeat_all"]}"
286 def toggle_repeat_one
287 if @currentconfig[:"playlist.repeat_one"] == "1"
288 @server.config_set_value( "playlist.repeat_one", "0" ).notifier do |res|
289 @server.config_get_value( "playlist.repeat_one" ).notifier do |value|
290 self.handle_repeat_one_state( value == "1" ? true : false )
295 elsif @currentconfig[:"playlist.repeat_one"] == "0"
296 @server.config_set_value( "playlist.repeat_one", "1" ).notifier do |res|
297 @server.config_get_value( "playlist.repeat_one" ).notifier do |value|
298 self.handle_repeat_one_state( value == "1" ? true : false )
304 warn "Unknown state: #{@currentconfig[:"playlist.repeat_one"]}"
310 @server.playlist.entries.notifier do |playlist|
311 self.handle_playlist playlist
315 @server.playback_current_id.notifier do |id|
316 self.handle_current_song id
319 @server.config_list_values.notifier do |res|
321 res.each_pair do |key, value|
322 @currentconfig[key] = value
325 @rpt1Btn.signal_handler_block( @rpt1BtnClkdHndlr ) do
326 @rpt1Btn.active = if( @currentconfig[:"playlist.repeat_one"] == "1" )
332 @rptBtn.signal_handler_block( @rptBtnClkdHndlr ) do
333 @rptBtn.active = if @currentconfig[:"playlist.repeat_all"] == "1"
345 class Grux::MainWin < Gtk::Window
349 @mainCont = Gtk::VBox.new
350 @btnCont = Gtk::HBox.new
351 @clntCont = Gtk::Notebook.new
353 @cnnctBtn = Gtk::Button.new "_Connect"
354 @quitBtn = Gtk::Button.new "_Quit"
358 @winDstryHndlr = self.signal_connect :destroy do
362 @cnnctBtnHndlr = @cnnctBtn.signal_connect :clicked do
363 @clntCont.append_page( Grux::ClientWin.new, Gtk::Label.new( "Client" ) )
365 @quitBtnHndlr = @quitBtn.signal_connect :clicked do
369 @btnCont.pack_start @cnnctBtn
370 @btnCont.pack_end @quitBtn
372 @mainCont.pack_start @btnCont, false
373 @mainCont.pack_end @clntCont
380 gruxWin = Grux::MainWin.new