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("activate") do
41 Snett::Snett.instance.xmms.send(*args)
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 = Xmms::Client.new(PKG_NAME)
72 @xmms.connect(ENV["XMMS_PATH"])
73 @xmms.add_to_glib_mainloop
74 @xmms.on_disconnect { destroy }
78 self.set_title(PKG_NAME)
80 signal_connect("destroy") do
81 @broadcasts.each { |bc| bc.disconnect }
86 self.resizable = false
87 self.decorated = false
89 @icon = Gdk::Pixbuf.new(DATADIR + "logo#{SIZE}.png")
91 self.resize(@icon.width, @icon.height)
93 #self.colormap = self.screen.rgba_colormap
95 pixmap, mask = @icon.render_pixmap_and_mask(self.colormap, 255)
96 self.shape_combine_mask(mask, 0, 0)
98 # load icon and put it in an eventbox
99 event_box = Gtk::EventBox.new.add(Gtk::Image.new(@icon))
100 event_box.events = Gdk::Event::BUTTON_PRESS_MASK |
101 Gdk::Event::BUTTON_RELEASE_MASK
103 event_box.signal_connect("button_press_event") do |_, event|
105 x, y = Gdk::Display.default.pointer[1, 2]
106 self.begin_move_drag(event.button, x, y, event.time)
107 elsif event.button == 3
114 @broadcasts << @xmms.broadcast_playback_current_id
115 @broadcasts.last.notifier(&method(:on_playback_current_id))
117 @xmms.playback_current_id.
118 notifier(&method(:on_playback_current_id))
128 def on_playback_current_id(res)
129 return if res.value.zero?
131 @xmms.medialib_get_info(res.value).
132 notifier(&method(:on_mlib_get_info))
135 def on_mlib_get_info(res)
138 s = "%s - %s" % [info[:artist], info[:title]]
139 @tooltips.set_tip(self, s, nil)
143 class Menu < Gtk::Menu
148 [Gtk::Stock::MEDIA_PLAY, :playback_start],
149 [Gtk::Stock::MEDIA_PAUSE, :playback_pause],
150 [Gtk::Stock::MEDIA_STOP, :playback_stop]
151 ].each do |(stock, meth)|
152 item = Gtk::ImageMenuItem.new(stock)
153 item.set_callback(meth)
158 append(Gtk::SeparatorMenuItem.new)
161 [Gtk::Stock::MEDIA_NEXT, :playback_next],
162 [Gtk::Stock::MEDIA_PREVIOUS, :playback_prev]
163 ].each do |(stock, meth)|
164 item = Gtk::ImageMenuItem.new(stock)
165 item.set_callback(meth)
170 append(Gtk::SeparatorMenuItem.new)
173 [Gtk::Stock::OPEN, "Load playlist...", :load],
174 [Gtk::Stock::ADD, "Append playlist...", :append]
175 ].each do |(stock, text, sym)|
176 item = Gtk::ImageMenuItem.new(text)
177 item.image = Gtk::Image.new(stock, Gtk::IconSize::MENU)
179 item.signal_connect("activate") do
180 PlaylistDialog.new(sym).show_all
187 item = Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
188 item.set_callback(:playlist_clear)
192 append(Gtk::SeparatorMenuItem.new)
194 item = Gtk::ImageMenuItem.new(Gtk::Stock::ABOUT)
195 item.signal_connect("activate") do
198 "version" => VERSION,
199 "copyright" => "(c) 2006 Tilman Sauerbeck",
200 "logo" => Gdk::Pixbuf.new(DATADIR + "logo128.png")
203 Gtk::AboutDialog.show(Snett.instance, props)
209 item = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
210 item.signal_connect("activate") do
211 Snett.instance.signal_emit("destroy")
221 super(nil, nil, event.button, event.time)
225 class PlaylistDialog < Gtk::Dialog
227 super("Playlists", Snett.instance,
228 Gtk::Dialog::DESTROY_WITH_PARENT | Gtk::Dialog::MODAL,
229 [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT],
230 [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT])
234 signal_connect("response") do |_, id|
235 on_ok if id == Gtk::Dialog::RESPONSE_ACCEPT
239 @store = Gtk::ListStore.new(String)
241 @view = Gtk::TreeView.new(@store)
242 renderer = Gtk::CellRendererText.new
244 col = Gtk::TreeViewColumn.new("Name", renderer, :text => 0)
245 @view.append_column(col)
247 scrolled = Gtk::ScrolledWindow.new
248 scrolled.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
255 Snett.instance.xmms.medialib_playlists_list.
256 notifier(&method(:on_playlists_list))
260 def on_playlists_list(res)
261 res.value.sort.each do |list|
262 next if list[0, 1] == "_"
264 @store.append[0] = list
269 selection = @view.selection
270 iter = selection.selected
273 Snett.instance.xmms.playlist_clear if @mode == :load
274 Snett.instance.xmms.medialib_playlist_load(iter[0])
280 Snett::Snett.instance.show_all