5 # Copyright (c) 2006 Tilman Sauerbeck (tilman at code-monkey de)
7 # Permission is hereby granted, free of charge, to any person obtaining
8 # a copy of this software and associated documentation files (the
9 # "Software"), to deal in the Software without restriction, including
10 # without limitation the rights to use, copy, modify, merge, publish,
11 # distribute, sublicense, and/or sell copies of the Software, and to
12 # permit persons to whom the Software is furnished to do so, subject to
13 # the following conditions:
15 # The above copyright notice and this permission notice shall be
16 # included in all copies or substantial portions of the Software.
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 require "xmmsclient_glib"
33 DATADIR = "/usr/local/share/#{PKG_NAME}/"
37 def set_callback(meth, args = [])
40 signal_connect("button_release_event") do
41 Snett::Snett.instance.xmms.send(*args)
47 class XmmsClient::XmmsClient
49 playlist_set_next_rel(1).notifier { playback_tickle }
53 playlist_set_next_rel(-1).notifier { playback_tickle }
60 class Snett < Gtk::Window
61 attr_reader :icon, :xmms
66 super(Gtk::Window::TOPLEVEL)
69 @tooltips = Gtk::Tooltips.new
71 @xmms = XmmsClient::XmmsClient.new(PKG_NAME)
72 @xmms.connect(ENV["XMMS_PATH"])
73 @xmms.add_to_glib_mainloop
77 self.set_title(PKG_NAME)
79 signal_connect("destroy") do
80 @broadcasts.each { |bc| bc.disconnect }
85 self.resizable = false
86 self.decorated = false
88 @icon = Gdk::Pixbuf.new(DATADIR + "logo#{SIZE}.png")
90 self.resize(@icon.width, @icon.height)
92 #self.colormap = self.screen.rgba_colormap
94 pixmap, mask = @icon.render_pixmap_and_mask(self.colormap, 255)
95 self.shape_combine_mask(mask, 0, 0)
97 # load icon and put it in an eventbox
98 event_box = Gtk::EventBox.new.add(Gtk::Image.new(@icon))
99 event_box.events = Gdk::Event::BUTTON_PRESS_MASK |
100 Gdk::Event::BUTTON_RELEASE_MASK
102 event_box.signal_connect("button_release_event") do |_, event|
103 menu.popup(event) if event.button == 3
107 event_box.signal_connect("button_press_event") do |_, event|
109 x, y = Gdk::Display.default.pointer[1, 2]
110 self.begin_move_drag(event.button, x, y, event.time)
116 @broadcasts << @xmms.broadcast_playback_current_id
117 @broadcasts.last.notifier(&method(:on_playback_current_id))
119 @xmms.playback_current_id.
120 notifier(&method(:on_playback_current_id))
130 def on_playback_current_id(res)
131 return if res.value.zero?
133 @xmms.medialib_get_info(res.value).
134 notifier(&method(:on_mlib_get_info))
137 def on_mlib_get_info(res)
138 info = res.value[:server]
140 s = "%s - %s" % [info[:artist], info[:title]]
141 @tooltips.set_tip(self, s, nil)
145 class Menu < Gtk::Menu
150 [Gtk::Stock::MEDIA_PLAY, :playback_start],
151 [Gtk::Stock::MEDIA_PAUSE, :playback_pause],
152 [Gtk::Stock::MEDIA_STOP, :playback_stop]
153 ].each do |(stock, meth)|
154 item = Gtk::ImageMenuItem.new(stock)
155 item.set_callback(meth)
160 append(Gtk::SeparatorMenuItem.new)
163 [Gtk::Stock::MEDIA_NEXT, :playback_next],
164 [Gtk::Stock::MEDIA_PREVIOUS, :playback_prev]
165 ].each do |(stock, meth)|
166 item = Gtk::ImageMenuItem.new(stock)
167 item.set_callback(meth)
172 append(Gtk::SeparatorMenuItem.new)
175 [Gtk::Stock::OPEN, "Load playlist...", :load],
176 [Gtk::Stock::ADD, "Append playlist...", :append]
177 ].each do |(stock, text, sym)|
178 item = Gtk::ImageMenuItem.new(text)
179 item.image = Gtk::Image.new(stock, Gtk::IconSize::MENU)
181 item.signal_connect("button_release_event") do
182 PlaylistDialog.new(sym).show_all
189 item = Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
190 item.set_callback(:playlist_clear)
194 append(Gtk::SeparatorMenuItem.new)
196 item = Gtk::ImageMenuItem.new(Gtk::Stock::ABOUT)
197 item.signal_connect("button_release_event") do
200 "version" => VERSION,
201 "copyright" => "(c) 2006 Tilman Sauerbeck",
202 "logo" => Gdk::Pixbuf.new(DATADIR + "logo128.png")
205 Gtk::AboutDialog.show(Snett.instance, props)
211 item = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
212 item.signal_connect("button_release_event") do
213 Snett.instance.signal_emit("destroy")
223 super(nil, nil, event.button, event.time)
227 class PlaylistDialog < Gtk::Dialog
229 super("Playlists", Snett.instance,
230 Gtk::Dialog::DESTROY_WITH_PARENT | Gtk::Dialog::MODAL,
231 [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT],
232 [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT])
236 signal_connect("response") do |_, id|
237 on_ok if id == Gtk::Dialog::RESPONSE_ACCEPT
241 @store = Gtk::ListStore.new(String)
243 @view = Gtk::TreeView.new(@store)
244 renderer = Gtk::CellRendererText.new
246 col = Gtk::TreeViewColumn.new("Name", renderer, :text => 0)
247 @view.append_column(col)
251 Snett.instance.xmms.medialib_playlists_list.
252 notifier(&method(:on_playlists_list))
256 def on_playlists_list(res)
257 res.value.sort.each do |list|
258 next if list[0, 1] == "_"
260 @store.append[0] = list
265 selection = @view.selection
266 iter = selection.selected
269 Snett.instance.xmms.playlist_clear if @mode == :load
270 Snett.instance.xmms.medialib_playlist_load(iter[0])
276 Snett::Snett.instance.show_all