]> git.netwichtig.de Git - user/henk/code/ruby/grux.git/blob - bin/grux.rb
On branch master
[user/henk/code/ruby/grux.git] / bin / grux.rb
1 #!/usr/bin/env ruby
2
3 #$: << File.expand_path(File.dirname(FILE) + “/../lib”))
4
5 #require 'libgruxclient'
6 require 'gtk2'
7 require 'xmmsclient'
8 require 'xmmsclient_glib'
9
10 class Grux
11 end
12
13 class Grux::ClientWin < Gtk::VBox
14   def initialize
15     super
16
17     @server                 = Xmms::Client.new( 'Grux' )
18
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
28
29     @cntrlbtns      = [
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)
37     ]
38     @statusLbls     = [
39       @stateLbl       = Gtk::Label.new,
40       @playbackLbl    = Gtk::Label.new,
41       @nextSongLbl    = Gtk::Label.new
42     ]
43
44     @cntrlbtns.each do |button|
45       @cntrlBtnBox.pack_start button
46     end
47     @cntrlBtnBox.layout_style = Gtk::ButtonBox::START
48     @statusLbls.each do |label|
49       @statusLblBox.pack_start label, false
50     end
51
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
57
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 )
64     end
65     @playlistViewWin.add @playlistView
66
67     self.pack_start @upperBox
68     self.pack_start @playlistViewWin
69     self.pack_end @statusBar, false
70     self.show_all
71
72     begin
73       @server.connect( ENV['XMMS_PATH'] )
74       @server.add_to_glib_mainloop
75     rescue
76       @statusBar.push( @statusBar.get_context_id( "connection" ), "Failed to connect to #{ENV['XMMS_PATH']}" )
77     end
78
79     @playBtn.signal_connect :clicked do
80       self.toggle_playback
81     end
82     @stopBtn.signal_connect :clicked do
83       self.stop_playback
84     end
85     @nextBtn.signal_connect :clicked do
86       self.step_in_playlist 1
87     end
88     @prevBtn.signal_connect :clicked do
89       self.step_in_playlist -1
90     end
91     @rptBtnClkdHndlr = @rptBtn.signal_connect :clicked do
92       self.toggle_repeat_all
93     end
94     @rpt1BtnClkdHndlr = @rpt1Btn.signal_connect :clicked do
95       self.toggle_repeat_one
96     end
97
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
101           true
102         end
103         true
104       end
105     end
106
107     @server.broadcast_coll_changed do
108     end
109     @server.broadcast_config_value_changed do |*foo|
110       p foo
111     end
112     @server.broadcast_mediainfo_reader_status do
113     end
114     @server.broadcast_medialib_entry_added do
115     end
116     @server.broadcast_medialib_entry_changed do
117     end
118     @server.broadcast_playback_current_id.notifier do |id|
119       self.handle_current_song id
120     end
121     @server.broadcast_playback_status.notifier do |playing|
122       self.handle_playback_status playing
123     end
124     @server.broadcast_playback_volume_changed do
125     end
126     @server.broadcast_playlist_changed do
127     end
128     @server.broadcast_playlist_current_pos.notifier do |pos|
129       self.handle_current_pos pos
130     end
131     @server.broadcast_playlist_loaded do
132     end
133     @server.broadcast_quit do
134     end
135
136     self.resync_state
137   end
138
139   def toggle_playback
140     if @playbackState == 1
141       @server.playback_pause.notifier do |res|
142         @statusBar.push( @statusBar.get_context_id( "playback" ), "Paused playback" )
143         true
144       end
145     elsif @playbackState == 0 || 2
146       @server.playback_start.notifier do |res|
147         @statusBar.push( @statusBar.get_context_id( "playback" ), "Started playback" )
148         true
149       end
150     else
151       warn "Playbackstate unknown"
152       @server.playback_start.notifier do |res|
153         @statusBar.push( @statusBar.get_context_id( "playback" ), "Started playback" )
154         true
155       end
156     end
157   end
158
159   def stop_playback
160     @server.playback_stop.notifier do |res|
161       @statusBar.push( @statusBar.get_context_id( "playback" ), "Stopped playback" )
162       true
163     end
164   end
165
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" : ''}" )
170         true
171       end
172     true
173     end
174   end
175
176   def handle_playback_status( status )
177     @playbackState = status
178     @stateLbl.text = case status
179       when 0 then "stopped"
180       when 1 then "playing"
181       when 2 then "paused"
182       else "unknown"
183     end
184     true
185   end
186
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|
192       infos = {}
193       @playbackLbl.text = ""
194       @infoBox.each { |child| @infoBox.remove child }
195       self.show_all
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})" )
200         end
201       end
202       [ :artist, :title, :album ].each do |key|
203         @infoBox.pack_start( Gtk::Frame.new( key.to_s ).add( Gtk::Label.new( infos.delete( key ) ) ) )
204       end
205       infos.each_pair do |key, value|
206         if key == :artist
207           @infoBox.pack_start( Gtk::Frame.new( key.to_s ).add( Gtk::Label.new( value ) ) )
208           next
209         end
210         @infoBox.pack_end( Gtk::Frame.new( key.to_s ).add( Gtk::Label.new( value ) ) )
211       end
212       @infoBox.show_all
213       true
214     end
215     true
216   end
217
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"
225     #      end
226     #    end
227     #    true
228     #  end
229     #  true
230     #end
231     true
232   end
233
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"
242         true
243       end
244     end
245     @playlistView.model = @playlistList
246     true
247   end
248
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
253     end
254   end
255
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
260     end
261   end
262
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 )
268           true
269         end
270         true
271       end
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 )
276           true
277         end
278         true
279       end
280     else
281       warn "Unknown state: #{@currentconfig[:"playlist.repeat_all"]}"
282     end
283     true
284   end
285
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 )
291           true
292         end
293         true
294       end
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 )
299           true
300         end
301         true
302       end
303     else
304       warn "Unknown state: #{@currentconfig[:"playlist.repeat_one"]}"
305     end
306     true
307   end
308
309   def resync_state
310     @server.playlist.entries.notifier do |playlist|
311       self.handle_playlist playlist
312       true
313     end
314
315     @server.playback_current_id.notifier do |id|
316       self.handle_current_song id
317     end
318
319     @server.config_list_values.notifier do |res|
320       @currentconfig = {}
321       res.each_pair do |key, value|
322         @currentconfig[key] = value
323       end
324
325       @rpt1Btn.signal_handler_block( @rpt1BtnClkdHndlr ) do
326         @rpt1Btn.active = if( @currentconfig[:"playlist.repeat_one"] == "1" )
327           true
328         else
329           false
330         end
331       end
332       @rptBtn.signal_handler_block( @rptBtnClkdHndlr ) do
333         @rptBtn.active = if @currentconfig[:"playlist.repeat_all"] == "1"
334           true
335         else
336           false
337         end
338       end
339       true
340     end
341     true
342   end
343 end
344
345 class Grux::MainWin < Gtk::Window
346   def initialize
347     super
348
349     @mainCont       = Gtk::VBox.new
350     @btnCont        = Gtk::HBox.new
351     @clntCont       = Gtk::Notebook.new
352
353     @cnnctBtn       = Gtk::Button.new "_Connect"
354     @quitBtn        = Gtk::Button.new "_Quit"
355
356     self.title      = "Grux"
357
358     @winDstryHndlr  = self.signal_connect :destroy do
359       Gtk.main_quit
360     end
361
362     @cnnctBtnHndlr  = @cnnctBtn.signal_connect :clicked do
363       @clntCont.append_page( Grux::ClientWin.new, Gtk::Label.new( "Client" ) )
364     end
365     @quitBtnHndlr   = @quitBtn.signal_connect :clicked do
366       Gtk.main_quit
367     end
368
369     @btnCont.pack_start @cnnctBtn
370     @btnCont.pack_end @quitBtn
371
372     @mainCont.pack_start @btnCont, false
373     @mainCont.pack_end @clntCont
374
375     self.add @mainCont
376     self.show_all
377   end
378 end
379
380 gruxWin = Grux::MainWin.new
381 Gtk.main
382