zik 0.16.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/ChangeLog +222 -0
- data/INSTALL +34 -0
- data/Makefile.in +199 -0
- data/README +53 -0
- data/ZiK.desktop +11 -0
- data/ZiK.rb +377 -0
- data/configure +269 -0
- data/dependencies +142 -0
- data/doc/COPYING +340 -0
- data/doc/ChangeLog +222 -0
- data/doc/html/fr/index.html +128 -0
- data/doc/html/index.html +126 -0
- data/doc/html/pix/ZiK3.png +0 -0
- data/doc/html/pix/capture.png +0 -0
- data/doc/html/pix/capture_cd.png +0 -0
- data/doc/html/pix/capture_compact.png +0 -0
- data/doc/html/pix/capture_radio.png +0 -0
- data/doc/html/pix/icon.png +0 -0
- data/doc/html/pix/logo.png +0 -0
- data/doc/html/styles/main.css +47 -0
- data/doc/man/manpage.1 +43 -0
- data/gui/assistant.rb +133 -0
- data/gui/cdgui.rb +54 -0
- data/gui/common.rb +56 -0
- data/gui/config.rb +120 -0
- data/gui/edit.rb +413 -0
- data/gui/error.rb +124 -0
- data/gui/gui.rb +1383 -0
- data/gui/mod.rb +239 -0
- data/gui/preference.rb +496 -0
- data/gui/progress.rb +50 -0
- data/gui/radiogui.rb +404 -0
- data/gui/search.rb +249 -0
- data/gui/socket.rb +107 -0
- data/mod/brainz.rb +76 -0
- data/mod/brainz/dialogs.rb +132 -0
- data/mod/brainz/functions.rb +55 -0
- data/mod/brainz/ofa.rb +76 -0
- data/mod/brainz/song.rb +139 -0
- data/mod/brainz/widget.rb +34 -0
- data/mod/cover.rb +90 -0
- data/mod/cover/application-x-cd-image.svg +666 -0
- data/mod/cover/config.rb +79 -0
- data/mod/cover/configwidget.rb +35 -0
- data/mod/cover/widget.rb +147 -0
- data/mod/hotkeys.rb +137 -0
- data/mod/hotkeys/config.rb +84 -0
- data/mod/hotkeys/configwidget.rb +93 -0
- data/mod/interact.rb +131 -0
- data/mod/interact/configwidget.rb +107 -0
- data/mod/interact/interaction.rb +79 -0
- data/mod/notify.rb +128 -0
- data/mod/notify/config.rb +96 -0
- data/mod/notify/configwidget.rb +76 -0
- data/mod/notify/window.rb +56 -0
- data/mod/trayicon.rb +83 -0
- data/mod/trayicon/config.rb +79 -0
- data/mod/trayicon/configwidget.rb +35 -0
- data/mod/trayicon/icon.rb +99 -0
- data/pix/ZiK.svg +78 -0
- data/pix/ZiK3.png +0 -0
- data/pix/assistant/capture.png +0 -0
- data/pix/gtk-directory.svg +287 -0
- data/pix/media-cdrom.svg +292 -0
- data/pix/network-wireless.svg +429 -0
- data/pix/player_play.svg +286 -0
- data/pix/sound.svg +244 -0
- data/pix/sound_directory.svg +464 -0
- data/player/cdplayer.rb +108 -0
- data/player/player.rb +132 -0
- data/player/radioplayer.rb +124 -0
- data/playlist/cdlist.rb +140 -0
- data/playlist/common.rb +343 -0
- data/playlist/editlist.rb +50 -0
- data/playlist/export.rb +108 -0
- data/playlist/playlist.rb +143 -0
- data/playlist/radiolist.rb +148 -0
- data/playlist/song.rb +122 -0
- data/po/ZiK.pot +622 -0
- data/po/fr/ZiK.po +658 -0
- data/zik +2 -0
- metadata +265 -0
- metadata.gz.sig +0 -0
data/gui/gui.rb
ADDED
@@ -0,0 +1,1383 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
Copyright 2007-2011 Vincent Carmona
|
4
|
+
|
5
|
+
This file is part of ZiK.
|
6
|
+
|
7
|
+
ZiK is free software; you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU General Public License as published by
|
9
|
+
the Free Software Foundation; either version 2 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
ZiK is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU General Public License
|
18
|
+
along with ZiK; if not, write to the Free Software
|
19
|
+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
=end
|
21
|
+
|
22
|
+
class Gui < Gtk::Window
|
23
|
+
include Pack
|
24
|
+
|
25
|
+
type_register#needded to implement new signals
|
26
|
+
attr_reader :renderer2
|
27
|
+
attr_reader :vbox, :selectview, :cm_list, :menu_bar#needded for modules, in gui/mod.rb
|
28
|
+
attr_reader :playlist, :config, :list_selection#needded for modules
|
29
|
+
|
30
|
+
signal_new('play', GLib::Signal::RUN_FIRST, nil, nil, Song)
|
31
|
+
def signal_do_play(song); end
|
32
|
+
signal_new('stop', GLib::Signal::RUN_FIRST, nil, nil)
|
33
|
+
def signal_do_stop; end
|
34
|
+
|
35
|
+
def initialize(player, playlist, config, cdplayer=nil, cdlist=nil, radioplayer=nil, radiolist=nil)
|
36
|
+
@player=player
|
37
|
+
@active_view='default'
|
38
|
+
@playlist=playlist
|
39
|
+
@config=config
|
40
|
+
if $cd
|
41
|
+
@cdplayer=cdplayer
|
42
|
+
@cdlist=cdlist
|
43
|
+
end
|
44
|
+
if $radio
|
45
|
+
@radiolist=radiolist
|
46
|
+
@radioplayer=radioplayer
|
47
|
+
end
|
48
|
+
|
49
|
+
@editing=false
|
50
|
+
@seeking=false
|
51
|
+
@nb_timeout=0
|
52
|
+
|
53
|
+
#*********************Menu zone*******************************
|
54
|
+
#Music menu
|
55
|
+
@play_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_PLAY)
|
56
|
+
@play_it.signal_connect('activate'){play}
|
57
|
+
@pause_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_PAUSE)
|
58
|
+
@pause_it.signal_connect('activate'){pause}
|
59
|
+
@stop_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_STOP)
|
60
|
+
@stop_it.signal_connect('activate'){stop}
|
61
|
+
@previous_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_PREVIOUS)
|
62
|
+
@previous_it.signal_connect('activate'){previous_song}
|
63
|
+
@next_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_NEXT)
|
64
|
+
@next_it.signal_connect('activate'){next_song}
|
65
|
+
@separator_it=Gtk::SeparatorMenuItem.new
|
66
|
+
@shuffle_it=Gtk::CheckMenuItem.new(_('Shuffle'))
|
67
|
+
@shuffle_it.active=@config['shuffle']
|
68
|
+
@shuffle_it.signal_connect('toggled'){self.shuffle=@shuffle_it.active?}
|
69
|
+
@repeat_it=Gtk::CheckMenuItem.new(_('Repeat'))
|
70
|
+
@repeat_it.active=@config['repeat']
|
71
|
+
@repeat_it.signal_connect('toggled'){self.repeat=@repeat_it.active?}
|
72
|
+
@separator_it2=Gtk::SeparatorMenuItem.new
|
73
|
+
@preference_it=Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
|
74
|
+
@preference_it.signal_connect('activate'){
|
75
|
+
if $cd
|
76
|
+
Preference_window.show(self, @playlist, @config, :player, @cdlist, @cdplayer, @wcd)
|
77
|
+
else
|
78
|
+
Preference_window.show(self, @playlist, @config, :player)
|
79
|
+
end
|
80
|
+
}
|
81
|
+
@quit_it=Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
|
82
|
+
@quit_it.signal_connect('activate'){quit}
|
83
|
+
|
84
|
+
@music_menu=Gtk::Menu.new
|
85
|
+
[@play_it, @pause_it, @stop_it,@previous_it, @next_it, @separator_it, @shuffle_it, @repeat_it, @separator_it2,
|
86
|
+
@preference_it, @quit_it].each{|it|
|
87
|
+
@music_menu.append(it)
|
88
|
+
}
|
89
|
+
|
90
|
+
#Browser menu
|
91
|
+
@refreshtree_it=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
|
92
|
+
@refreshtree_it.signal_connect('activate'){refresh_treestore(@config['directory'],@config['extension'])}
|
93
|
+
@find_it=Gtk::ImageMenuItem.new(Gtk::Stock::FIND)
|
94
|
+
@find_it.signal_connect('activate'){BrowseSearchWindow.show(self,@config)}
|
95
|
+
@preference_it2=Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
|
96
|
+
@preference_it2.signal_connect('activate'){
|
97
|
+
if $cd
|
98
|
+
Preference_window.show(self, @playlist, @config, :browse, @cdlist, @cdplayer, @wcd)
|
99
|
+
else
|
100
|
+
Preference_window.show(self, @playlist, @config, :browse)
|
101
|
+
end
|
102
|
+
}
|
103
|
+
|
104
|
+
@browse_menu=Gtk::Menu.new
|
105
|
+
[@refreshtree_it, @find_it, @preference_it2].each{|it| @browse_menu.append(it)}
|
106
|
+
|
107
|
+
#Playlist menu
|
108
|
+
@add_it=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)
|
109
|
+
@add_it.signal_connect('activate'){import_list}
|
110
|
+
@rm_it=Gtk::ImageMenuItem.new(Gtk::Stock::REMOVE)
|
111
|
+
@rm_it.signal_connect('activate'){list_rm(@list_selection)}
|
112
|
+
@clear_it=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
|
113
|
+
@clear_it.signal_connect('activate'){list_clear}
|
114
|
+
@find2_it=Gtk::ImageMenuItem.new(Gtk::Stock::FIND)
|
115
|
+
@find2_it.signal_connect('activate'){search}
|
116
|
+
@edit_it=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
|
117
|
+
@edit_it.signal_connect('activate'){list_edit}
|
118
|
+
@bsave=Gtk::ImageMenuItem.new(Gtk::Stock::SAVE)
|
119
|
+
@separator_it2=Gtk::SeparatorMenuItem.new
|
120
|
+
@bsave.signal_connect('activate'){list_save}
|
121
|
+
@separator_it3=Gtk::SeparatorMenuItem.new
|
122
|
+
@bexport=Gtk::MenuItem.new(_("Export songs"))
|
123
|
+
@bexport.tooltip_text=_("Copy songs to a directory and write the selected playlist file.")
|
124
|
+
@bexport.signal_connect('activate'){export_songs}
|
125
|
+
@preference_it3=Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
|
126
|
+
@preference_it3.signal_connect('activate'){
|
127
|
+
if $cd
|
128
|
+
Preference_window.show(self, @playlist, @config, :playlist, @cdlist, @cdplayer, @wcd)
|
129
|
+
else
|
130
|
+
Preference_window.show(self,@playlist,@config,:playlist)
|
131
|
+
end
|
132
|
+
}
|
133
|
+
|
134
|
+
@playlist_menu=Gtk::Menu.new
|
135
|
+
#Do not show @edit_it. See bug 28638
|
136
|
+
#Fixme
|
137
|
+
# [@add_it, @rm_it, @clear_it, @find2_it, @edit_it, @bsave, @separator_it2, @bexport,
|
138
|
+
[@add_it, @rm_it, @clear_it, @find2_it, @bsave, @separator_it2, @bexport,
|
139
|
+
@separator_it3, @preference_it3].each{|it| @playlist_menu.append(it)}
|
140
|
+
|
141
|
+
#Radio menu
|
142
|
+
if $radio
|
143
|
+
@add_rit=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)
|
144
|
+
@add_rit.signal_connect('activate'){@wradio.add_radio}
|
145
|
+
@rm_rit=Gtk::ImageMenuItem.new(Gtk::Stock::REMOVE)
|
146
|
+
@rm_rit.signal_connect('activate'){
|
147
|
+
current_removed=@wradio.rm
|
148
|
+
if @active_view=='radio'
|
149
|
+
@radioplayer.stop if current_removed
|
150
|
+
end
|
151
|
+
}
|
152
|
+
@clear_rit=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
|
153
|
+
@clear_rit.signal_connect('activate'){@radioplayer.stop; @wradio.clear}
|
154
|
+
@edit_rit=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
|
155
|
+
@edit_rit.signal_connect('activate'){radios_edit}
|
156
|
+
@import_rit=Gtk::ImageMenuItem.new(_('_Import'))
|
157
|
+
@import_rit.image=Gtk::Image.new(Gtk::Stock::ADD, Gtk::IconSize::MENU)
|
158
|
+
@import_rit.signal_connect('activate'){@wradio.import}
|
159
|
+
@radio_menu=Gtk::Menu.new
|
160
|
+
[@add_rit, @rm_rit, @clear_rit, @edit_rit, @import_rit].each{|it| @radio_menu.append(it)}
|
161
|
+
end
|
162
|
+
|
163
|
+
#Help menu
|
164
|
+
@help_it=Gtk::ImageMenuItem.new(Gtk::Stock::HELP)
|
165
|
+
@help_it.signal_connect('activate'){help}
|
166
|
+
@assistant_it=Gtk::MenuItem.new(_('Assistant'))
|
167
|
+
@assistant_it.signal_connect('activate'){
|
168
|
+
require File.join(Data_dir, 'gui/assistant')
|
169
|
+
Assistant.new(@config, self)
|
170
|
+
}
|
171
|
+
@bug_it=Gtk::MenuItem.new(_('Report a bug'))
|
172
|
+
@bug_it.signal_connect('activate'){
|
173
|
+
unless system('gnome-open http://rubyforge.org/tracker/?group_id=5494')
|
174
|
+
ErrorError.new('Cannot open http://rubyforge.org/tracker/?group_id=5494', true)
|
175
|
+
end
|
176
|
+
}
|
177
|
+
@about_it=Gtk::ImageMenuItem.new(Gtk::Stock::ABOUT)
|
178
|
+
@about_it.signal_connect('activate'){about}
|
179
|
+
|
180
|
+
@help_menu=Gtk::Menu.new
|
181
|
+
[@help_it, @assistant_it, @bug_it, @about_it].each{|it| @help_menu.append(it)}
|
182
|
+
|
183
|
+
#Menu bar
|
184
|
+
@music_it=Gtk::MenuItem.new(_('_Music'))
|
185
|
+
@music_it.set_submenu(@music_menu)
|
186
|
+
@broswe_it=Gtk::MenuItem.new(_('_Browser'))
|
187
|
+
@broswe_it.set_submenu(@browse_menu)
|
188
|
+
@playlist_it=Gtk::MenuItem.new(_('Play_list'))
|
189
|
+
@playlist_it.set_submenu(@playlist_menu)
|
190
|
+
if $radio
|
191
|
+
@radiolist_it=Gtk::MenuItem.new(_('_Radio'))
|
192
|
+
@radiolist_it.set_submenu(@radio_menu)
|
193
|
+
end
|
194
|
+
@help_it2=Gtk::MenuItem.new(_('_Help'))
|
195
|
+
@help_it2.set_submenu(@help_menu)
|
196
|
+
|
197
|
+
@menu_bar=Gtk::MenuBar.new
|
198
|
+
if $radio
|
199
|
+
[@music_it, @broswe_it, @playlist_it, @radiolist_it, @help_it2].each{|it| @menu_bar.append(it)}
|
200
|
+
else
|
201
|
+
[@music_it, @broswe_it, @playlist_it, @help_it2].each{|it| @menu_bar.append(it)}
|
202
|
+
end
|
203
|
+
#*********************Browser zone****************************
|
204
|
+
@treestore=Gtk::TreeStore.new(String,String)
|
205
|
+
GLib::Idle.add{
|
206
|
+
refresh_treestore(@config['directory'], @config['extension'], true)
|
207
|
+
false
|
208
|
+
}
|
209
|
+
|
210
|
+
@renderer=Gtk::CellRendererText.new
|
211
|
+
@col=Gtk::TreeViewColumn.new(_("Browser"), @renderer, :text => 0)
|
212
|
+
@treeview=Gtk::TreeView.new(@treestore)#See also Gtk::IconView.
|
213
|
+
@treeview.append_column(@col)
|
214
|
+
@treeview.signal_connect("row-activated"){|view, path, column|
|
215
|
+
if @editing
|
216
|
+
@edit_wrapper.add_song(@treestore.get_iter(path)[1])
|
217
|
+
else
|
218
|
+
@playlist.add(@treestore.get_iter(path)[1], @config['extension'])
|
219
|
+
refresh_liststore
|
220
|
+
end
|
221
|
+
}
|
222
|
+
@treeview.signal_connect("button_press_event"){|widget, event|
|
223
|
+
if event.button==3
|
224
|
+
@cm_browse.popup(nil, nil, event.button, event.time)
|
225
|
+
end
|
226
|
+
}
|
227
|
+
|
228
|
+
@tree_selection=@treeview.selection
|
229
|
+
@tree_selection.mode=Gtk::SELECTION_MULTIPLE
|
230
|
+
|
231
|
+
|
232
|
+
@wtree=Gtk::ScrolledWindow.new
|
233
|
+
@wtree.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
|
234
|
+
@wtree.add(@treeview)
|
235
|
+
|
236
|
+
#Drag&drop
|
237
|
+
@treeview.enable_model_drag_source(Gdk::Window::BUTTON1_MASK,
|
238
|
+
[['brower-selection', Gtk::Drag::TargetFlags::SAME_APP, DragType::BROWSER_SELECTION]],
|
239
|
+
Gdk::DragContext::ACTION_COPY)
|
240
|
+
#@treeview.signal_connect("drag-data-get"){|widget, context, data, info, time| data.set(Gdk::Selection::TYPE_STRING, 'toto')}
|
241
|
+
#data.uris=[uris1,uris2] crash!
|
242
|
+
@treeview.enable_model_drag_dest([['text/uri-list', Gtk::Drag::TargetFlags::OTHER_APP, DragType::URI_LIST]],
|
243
|
+
Gdk::DragContext::ACTION_COPY)
|
244
|
+
@treeview.signal_connect("drag-data-received"){|widget, context, x, y, data, info, time|
|
245
|
+
if info==DragType::URI_LIST
|
246
|
+
old=@config['directory']
|
247
|
+
data.uris.each{|uri|
|
248
|
+
path=GLib.filename_from_uri(uri)[0]
|
249
|
+
@config['directory']+=path+',' if File.directory?(path)
|
250
|
+
}
|
251
|
+
end
|
252
|
+
refresh_treestore(@config['directory'], @config['extension']) unless old==@config['directory']
|
253
|
+
}
|
254
|
+
|
255
|
+
#Context menu
|
256
|
+
@brefresh_browse=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
|
257
|
+
@brefresh_browse.signal_connect('activate'){refresh_treestore(@config['directory'],@config['extension'])}
|
258
|
+
@bfind_browse=Gtk::ImageMenuItem.new(Gtk::Stock::FIND)
|
259
|
+
@bfind_browse.signal_connect('activate'){BrowseSearchWindow.show(self,@config)}
|
260
|
+
@bpreference_browse=Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
|
261
|
+
@bpreference_browse.signal_connect('activate'){
|
262
|
+
if $cd
|
263
|
+
Preference_window.show(self, @playlist, @config, :browse, @cdlist, @cdplayer, @wcd)
|
264
|
+
else
|
265
|
+
Preference_window.show(self, @playlist, @config, :browse)
|
266
|
+
end
|
267
|
+
}
|
268
|
+
|
269
|
+
@cm_browse=Gtk::Menu.new
|
270
|
+
@cm_browse.append(@brefresh_browse)
|
271
|
+
@cm_browse.append(@bfind_browse)
|
272
|
+
@cm_browse.append(@bpreference_browse)
|
273
|
+
@cm_browse.show_all
|
274
|
+
|
275
|
+
#*********************Buttons zone*****************************
|
276
|
+
@badd=Gtk::Button.new
|
277
|
+
@badd.image=Gtk::Image.new(Gtk::Stock::ADD,Gtk::IconSize::BUTTON)
|
278
|
+
@badd.tooltip_text=_('Add selected files to playlist')
|
279
|
+
@badd.signal_connect('clicked') {
|
280
|
+
if @editing
|
281
|
+
@edit_wrapper.add_songs(@tree_selection)
|
282
|
+
else
|
283
|
+
list_add(@tree_selection, @config['extension'])
|
284
|
+
end
|
285
|
+
}
|
286
|
+
|
287
|
+
@brm=Gtk::Button.new
|
288
|
+
@brm.image=Gtk::Image.new(Gtk::Stock::REMOVE,Gtk::IconSize::BUTTON)
|
289
|
+
@brm.tooltip_text=_('Remove selected songs from playlist')
|
290
|
+
@brm.signal_connect('clicked') {@editing ? @edit_wrapper.rm_song : list_rm(@list_selection)}
|
291
|
+
|
292
|
+
@bclear=Gtk::Button.new
|
293
|
+
@bclear.image=Gtk::Image.new(Gtk::Stock::CLEAR,Gtk::IconSize::BUTTON)
|
294
|
+
@bclear.tooltip_text=_('Clear playlist')
|
295
|
+
@bclear.signal_connect('clicked') {@editing ? @edit_wrapper.clear : list_clear}
|
296
|
+
|
297
|
+
@bedit=Gtk::Button.new
|
298
|
+
@bedit.image=Gtk::Image.new(Gtk::Stock::EDIT,Gtk::IconSize::BUTTON)
|
299
|
+
@bedit.tooltip_text=_('Edit playlist')
|
300
|
+
@bedit.signal_connect('clicked'){list_edit}
|
301
|
+
|
302
|
+
@bfind=Gtk::Button.new
|
303
|
+
@bfind.image=Gtk::Image.new(Gtk::Stock::FIND, Gtk::IconSize::BUTTON)
|
304
|
+
@bfind.tooltip_text=_('Find in playlist')
|
305
|
+
@bfind.signal_connect('clicked'){@editing ? @edit_wrapper.search : search}
|
306
|
+
|
307
|
+
#*********************Playlist zone****************************
|
308
|
+
@list_store=Gtk::ListStore.new(String,TrueClass)
|
309
|
+
refresh_liststore
|
310
|
+
|
311
|
+
@renderer2=Gtk::CellRendererText.new
|
312
|
+
@renderer2.background=@config['playing_color']
|
313
|
+
@col2=Gtk::TreeViewColumn.new(_("Playlist"), @renderer2, :text => 0, :background_set => 1)
|
314
|
+
@list_view=Gtk::TreeView.new(@list_store)
|
315
|
+
#@list_view.headers_visible=false
|
316
|
+
@list_view.append_column(@col2)
|
317
|
+
@list_view.signal_connect("row-activated"){|view, path, column|
|
318
|
+
@playlist.current=path.to_s.to_i
|
319
|
+
stop
|
320
|
+
play
|
321
|
+
}
|
322
|
+
@list_view.signal_connect("button_press_event"){|widget, event|
|
323
|
+
if event.button==3
|
324
|
+
@cm_list.popup(nil, nil, event.button, event.time)
|
325
|
+
end
|
326
|
+
}
|
327
|
+
compact(@config['compact'])
|
328
|
+
|
329
|
+
@list_selection=@list_view.selection
|
330
|
+
@list_selection.mode=Gtk::SELECTION_MULTIPLE
|
331
|
+
|
332
|
+
@wlist=Gtk::ScrolledWindow.new
|
333
|
+
@wlist.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
|
334
|
+
@wlist.add(@list_view)
|
335
|
+
|
336
|
+
#Drag&drop
|
337
|
+
dragtable=[['brower-selection', Gtk::Drag::TargetFlags::SAME_APP, DragType::BROWSER_SELECTION],
|
338
|
+
['text/uri-list', Gtk::Drag::TargetFlags::OTHER_APP, DragType::URI_LIST]]
|
339
|
+
@list_view.enable_model_drag_dest(dragtable, Gdk::DragContext::ACTION_COPY)
|
340
|
+
@list_view.signal_connect("drag-data-received"){|widget, context, x, y, data, info, time|
|
341
|
+
case info
|
342
|
+
when DragType::BROWSER_SELECTION
|
343
|
+
r=@list_view.get_dest_row(x, y)
|
344
|
+
if r.nil?
|
345
|
+
list_add(@tree_selection, @config['extension'])
|
346
|
+
else
|
347
|
+
pos=r[0].to_s.to_i
|
348
|
+
case r[1]
|
349
|
+
when Gtk::TreeView::DROP_AFTER, Gtk::TreeView::DROP_INTO_OR_AFTER
|
350
|
+
pos+=1
|
351
|
+
end
|
352
|
+
list_add_at(@tree_selection, @config['extension'], pos)
|
353
|
+
end
|
354
|
+
when DragType::URI_LIST
|
355
|
+
r=@list_view.get_dest_row(x, y)
|
356
|
+
if r.nil?
|
357
|
+
list_add_uris(data.uris, @config['extension'])
|
358
|
+
else
|
359
|
+
pos=r[0].to_s.to_i
|
360
|
+
case r[1]
|
361
|
+
when Gtk::TreeView::DROP_AFTER, Gtk::TreeView::DROP_INTO_OR_AFTER
|
362
|
+
pos+=1
|
363
|
+
end
|
364
|
+
list_add_uris_at(data.uris, @config['extension'], pos)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
}
|
368
|
+
|
369
|
+
#Context menu
|
370
|
+
@badd_list=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)
|
371
|
+
@badd_list.signal_connect("activate"){import_list}
|
372
|
+
@brm_list=Gtk::ImageMenuItem.new(Gtk::Stock::REMOVE)
|
373
|
+
@bedit_list=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
|
374
|
+
@bedit_list.signal_connect("activate"){list_edit}
|
375
|
+
@bsave_list=Gtk::ImageMenuItem.new(Gtk::Stock::SAVE)
|
376
|
+
@bsave_list.signal_connect("activate"){list_save}
|
377
|
+
@brm_list.signal_connect("activate"){list_rm(@list_selection)}
|
378
|
+
sep=Gtk::SeparatorMenuItem.new
|
379
|
+
@bedit2_list=Gtk::ImageMenuItem.new(_('Edit tag'))
|
380
|
+
@bedit2_list.image=Gtk::Image.new(Gtk::Stock::EDIT, Gtk::IconSize::MENU)
|
381
|
+
@bedit2_list.signal_connect("activate"){
|
382
|
+
s=@list_selection.selected_rows
|
383
|
+
unless s.empty?
|
384
|
+
i=s[-1].to_s.to_i
|
385
|
+
EditSongWindow.new(@playlist.songs[i], self, @config['name_format'])
|
386
|
+
end
|
387
|
+
}
|
388
|
+
@bopen=Gtk::ImageMenuItem.new(Gtk::Stock::OPEN)
|
389
|
+
@bopen.signal_connect("activate"){
|
390
|
+
s=@list_selection.selected_rows
|
391
|
+
unless s.empty?
|
392
|
+
i=s[-1].to_s.to_i
|
393
|
+
dir=File.dirname(@playlist.songs[i].path)
|
394
|
+
dir.gsub!(/(?=[{\[\ \]}*])/, '\\')#gsub(/(?=[{\[\]}*])/, '\\') -> escape { [ ] } *
|
395
|
+
ErrorError.new("Cannot open #{dir}", true) unless system("gnome-open #{dir}")
|
396
|
+
end
|
397
|
+
}
|
398
|
+
|
399
|
+
@cm_list=Gtk::Menu.new
|
400
|
+
[@badd_list, @brm_list, @bedit_list, @bsave_list, sep, @bedit2_list, @bopen].each{|b| @cm_list.append(b)}
|
401
|
+
|
402
|
+
@cm_list.show_all
|
403
|
+
|
404
|
+
#*********************Cd zone**********************************
|
405
|
+
if $cd
|
406
|
+
@wcd=Cd::Window.new(@config, @cdlist)
|
407
|
+
@wcd.view.signal_connect("row-activated"){|view, path, column|
|
408
|
+
@cdlist.current=path.to_s.to_i
|
409
|
+
stop
|
410
|
+
play
|
411
|
+
}
|
412
|
+
|
413
|
+
@bcdrefresh=Gtk::Button.new
|
414
|
+
@bcdrefresh.image=Gtk::Image.new(Gtk::Stock::REFRESH, Gtk::IconSize::BUTTON)
|
415
|
+
@bcdrefresh.signal_connect('clicked'){@cdlist.refresh; @wcd.refresh_store}##{Thread.new($stdout){@list.refresh_on;refresh_store}}
|
416
|
+
@bcdpreference=Gtk::Button.new
|
417
|
+
@bcdpreference.image=Gtk::Image.new(Gtk::Stock::PREFERENCES, Gtk::IconSize::BUTTON)
|
418
|
+
@bcdpreference.signal_connect('clicked'){
|
419
|
+
Preference_window.show(self, @playlist, @config, :cd, @cdlist, @cdplayer, @wcd)
|
420
|
+
}
|
421
|
+
|
422
|
+
@cdtable=Gtk::Table.new(4,2)
|
423
|
+
@cdtable.column_spacings=($border)
|
424
|
+
@cdtable.attach(@bcdrefresh, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK)
|
425
|
+
@cdtable.attach(@bcdpreference, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK)
|
426
|
+
@cdtable.attach(@wcd, 1, 2, 0, 4)
|
427
|
+
end
|
428
|
+
|
429
|
+
#*********************Radio zone*******************************
|
430
|
+
if $radio
|
431
|
+
@wradio=Radio::Window.new(self, @radiolist)
|
432
|
+
@wradio.view.signal_connect("row-activated"){|view, path, column|
|
433
|
+
@radiolist.current=path.to_s.to_i
|
434
|
+
stop
|
435
|
+
play
|
436
|
+
}
|
437
|
+
|
438
|
+
@bradioadd=Gtk::Button.new
|
439
|
+
@bradioadd.image=Gtk::Image.new(Gtk::Stock::ADD, Gtk::IconSize::BUTTON)
|
440
|
+
@bradioadd.tooltip_text=_('Add a radio')
|
441
|
+
@bradioadd.signal_connect('clicked'){@wradio.add_radio}
|
442
|
+
@bradiorm=Gtk::Button.new
|
443
|
+
@bradiorm.image=Gtk::Image.new(Gtk::Stock::REMOVE, Gtk::IconSize::BUTTON)
|
444
|
+
@bradiorm.tooltip_text=_('Remove selection')
|
445
|
+
@bradiorm.signal_connect('clicked'){
|
446
|
+
current_removed=@wradio.rm
|
447
|
+
if @active_view=='radio'
|
448
|
+
@radioplayer.stop if current_removed
|
449
|
+
end
|
450
|
+
}
|
451
|
+
@bradioclear=Gtk::Button.new
|
452
|
+
@bradioclear.image=Gtk::Image.new(Gtk::Stock::CLEAR, Gtk::IconSize::BUTTON)
|
453
|
+
@bradioclear.tooltip_text=_('Clear radios list')
|
454
|
+
@bradioclear.signal_connect('clicked'){
|
455
|
+
@radioplayer.stop
|
456
|
+
@wradio.clear
|
457
|
+
}
|
458
|
+
|
459
|
+
@bradioedit=Gtk::Button.new
|
460
|
+
@bradioedit.image=Gtk::Image.new(Gtk::Stock::EDIT, Gtk::IconSize::BUTTON)
|
461
|
+
@bradioedit.tooltip_text=_('Edit a radio')
|
462
|
+
@bradioedit.signal_connect('clicked'){radios_edit}
|
463
|
+
|
464
|
+
@radiotable=Gtk::Table.new(6,2)
|
465
|
+
@radiotable.column_spacings=($border)
|
466
|
+
@radiotable.attach(@bradioadd, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK)
|
467
|
+
@radiotable.attach(@bradiorm, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK)
|
468
|
+
@radiotable.attach(@bradioclear, 0, 1, 3, 4, Gtk::SHRINK, Gtk::SHRINK)
|
469
|
+
@radiotable.attach(@bradioedit, 0, 1, 4, 5, Gtk::SHRINK, Gtk::SHRINK)
|
470
|
+
@radiotable.attach(@wradio, 1, 2, 0, 6)
|
471
|
+
end
|
472
|
+
|
473
|
+
#*********************Player zone******************************
|
474
|
+
#View selection
|
475
|
+
#@icon_theme=Gtk::IconTheme.default
|
476
|
+
#@idir=@icon_theme.load_icon('gtk-directory', Gtk::IconSize::BUTTON, Gtk::IconTheme::LOOKUP_FORCE_SVG)
|
477
|
+
@viewstore=Gtk::ListStore.new(Gdk::Pixbuf)
|
478
|
+
['sound_directory.svg','sound.svg','gtk-directory.svg','player_play.svg'].each{|image|
|
479
|
+
child=@viewstore.append
|
480
|
+
child[0]=Gdk::Pixbuf.new(File.join(Pix_dir, image), 24, 24)
|
481
|
+
}
|
482
|
+
if $cd
|
483
|
+
child=@viewstore.append
|
484
|
+
child[0]=Gdk::Pixbuf.new(File.join(Pix_dir, 'media-cdrom.svg'), 24, 24)
|
485
|
+
end
|
486
|
+
if $radio
|
487
|
+
child=@viewstore.append
|
488
|
+
child[0]=Gdk::Pixbuf.new(File.join(Pix_dir, 'network-wireless.svg'), 24, 24)
|
489
|
+
end
|
490
|
+
@renderer3=Gtk::CellRendererPixbuf.new
|
491
|
+
@selectview=Gtk::ComboBox.new(false)
|
492
|
+
@selectview.model=@viewstore
|
493
|
+
@selectview.pack_start(@renderer3,false)
|
494
|
+
@selectview.set_attributes(@renderer3, :pixbuf => 0)
|
495
|
+
|
496
|
+
case @config['view']
|
497
|
+
when 'playlist' then @selectview.active=View::PLAYLIST
|
498
|
+
when 'browser' then @selectview.active=View::BROWSER
|
499
|
+
when 'player' then @selectview.active=View::COMPACT
|
500
|
+
when 'cd' then @selectview.active=View::CD
|
501
|
+
when 'radio' then @selectview.active=View::RADIO
|
502
|
+
else @selectview.active=View::ALL
|
503
|
+
end
|
504
|
+
@selectview.signal_connect('changed'){change_view}
|
505
|
+
#Song title
|
506
|
+
@song_title=Gtk::Label.new
|
507
|
+
@song_title.wrap=true
|
508
|
+
@song_title.attributes=Pango::AttrList.new.insert(Pango::AttrWeight.new(Pango::WEIGHT_BOLD))
|
509
|
+
@fsong_title=Gtk::Frame.new
|
510
|
+
@fsong_title.add(@song_title)
|
511
|
+
#volume
|
512
|
+
@bvolume=Gtk::VolumeButton.new
|
513
|
+
@bvolume.value=@player.volume
|
514
|
+
@bvolume.signal_connect('value-changed'){
|
515
|
+
@player.volume=@bvolume.value
|
516
|
+
@cdplayer.volume=@bvolume.value if $cd
|
517
|
+
@radioplayer.volume=@bvolume.value if $radio
|
518
|
+
}
|
519
|
+
|
520
|
+
#buttons
|
521
|
+
@iprev=Gtk::Image.new(Gtk::Stock::MEDIA_PREVIOUS,Gtk::IconSize::BUTTON)
|
522
|
+
@bprev= Gtk::Button.new;@bprev.image=@iprev
|
523
|
+
@bprev.signal_connect('clicked'){previous_song}
|
524
|
+
@istop=Gtk::Image.new(Gtk::Stock::MEDIA_STOP,Gtk::IconSize::BUTTON)
|
525
|
+
@bstop=Gtk::Button.new;@bstop.image=@istop
|
526
|
+
@bstop.signal_connect('clicked'){stop}
|
527
|
+
@iplay=Gtk::Image.new(Gtk::Stock::MEDIA_PLAY,Gtk::IconSize::BUTTON)
|
528
|
+
@bplay= Gtk::Button.new;@bplay.image=@iplay
|
529
|
+
@bplay.signal_connect('clicked'){play}
|
530
|
+
@ipause=Gtk::Image.new(Gtk::Stock::MEDIA_PAUSE,Gtk::IconSize::BUTTON)
|
531
|
+
@bpause=Gtk::Button.new;@bpause.image=@ipause
|
532
|
+
@bpause.signal_connect('clicked'){pause}
|
533
|
+
@inext=Gtk::Image.new(Gtk::Stock::MEDIA_NEXT,Gtk::IconSize::BUTTON)
|
534
|
+
@bnext= Gtk::Button.new;@bnext.image=@inext
|
535
|
+
@bnext.signal_connect('clicked'){next_song}
|
536
|
+
#time
|
537
|
+
@lposition=Gtk::Label.new('--:--')
|
538
|
+
@lposbox=Gtk::EventBox.new
|
539
|
+
@lposbox.events=Gdk::Event::BUTTON_PRESS_MASK
|
540
|
+
@lposbox.add(@lposition)
|
541
|
+
@lposbox.signal_connect('button_press_event'){|widget, event|
|
542
|
+
if event.button==1
|
543
|
+
@config['remaining_time']=!@config['remaining_time']
|
544
|
+
end
|
545
|
+
}
|
546
|
+
@sposition=Gtk::HScale.new
|
547
|
+
@sposition.draw_value=false
|
548
|
+
@sposition.signal_connect('button_press_event'){@seeking=true;false}
|
549
|
+
@sposition.signal_connect('button_release_event'){
|
550
|
+
case active_player
|
551
|
+
when 'default'
|
552
|
+
player=@player
|
553
|
+
when 'cd'
|
554
|
+
player=@cdplayer
|
555
|
+
when 'radio'
|
556
|
+
player=nil
|
557
|
+
end
|
558
|
+
player.position=@sposition.value.to_i if player
|
559
|
+
@seeking=false
|
560
|
+
}
|
561
|
+
@lduration=Gtk::Label.new('--:--')
|
562
|
+
#containers
|
563
|
+
@title_container=Gtk::HBox.new(false)
|
564
|
+
@title_container.pack_start(@selectview, false, false)
|
565
|
+
@title_container.pack_start(@fsong_title, true, true)
|
566
|
+
@title_container.pack_start(@bvolume, false, false)
|
567
|
+
|
568
|
+
@button_container=Gtk::HBox.new(false)
|
569
|
+
@button_container.pack_start(@bprev, false, false)
|
570
|
+
@button_container.pack_start(@bstop, false, false)
|
571
|
+
@button_container.pack_start(@bplay, false, false)
|
572
|
+
@button_container.pack_start(@bpause, false, false)
|
573
|
+
@button_container.pack_start(@bnext, false, false)
|
574
|
+
@button_container.pack_start(@lposbox, false, false)
|
575
|
+
@button_container.pack_start(@sposition, true, true)
|
576
|
+
@button_container.pack_start(@lduration, false, false)
|
577
|
+
|
578
|
+
#**********************Key bindings***************************
|
579
|
+
@accel=Gtk::AccelGroup.new
|
580
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_p, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){playpause}
|
581
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_s, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){stop}
|
582
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_b, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){previous_song}
|
583
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_n, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){next_song}
|
584
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_Down, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){volume_down}
|
585
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_Up, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){volume_up}
|
586
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_f, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){
|
587
|
+
@editing ? @edit_wrapper.search : search
|
588
|
+
}
|
589
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_d, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){focus_to_current}
|
590
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_F1, nil, Gtk::ACCEL_VISIBLE){help}
|
591
|
+
@accel.connect(Gdk::Keyval::GDK_KEY_Delete, nil, Gtk::ACCEL_VISIBLE){
|
592
|
+
list_rm(@list_selection) if @list_view.has_focus?
|
593
|
+
if @edit_wrapper
|
594
|
+
@edit_wrapper.rm_song if @edit_wrapper.has_focus?
|
595
|
+
end
|
596
|
+
}
|
597
|
+
|
598
|
+
#*********************Main window******************************
|
599
|
+
@table=Gtk::Table.new(8, 2)
|
600
|
+
@table.column_spacings=($border)
|
601
|
+
@table.attach(@badd, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK)
|
602
|
+
@table.attach(@brm, 0, 1, 3, 4, Gtk::SHRINK, Gtk::SHRINK)
|
603
|
+
@table.attach(@bclear, 0, 1, 4, 5, Gtk::SHRINK, Gtk::SHRINK)
|
604
|
+
@table.attach(@bedit, 0, 1, 5, 6, Gtk::SHRINK, Gtk::SHRINK)
|
605
|
+
@table.attach(@bfind, 0, 1, 6, 7, Gtk::SHRINK, Gtk::SHRINK)
|
606
|
+
@table.attach(@wlist, 1, 2, 1, 8)
|
607
|
+
|
608
|
+
@paned=Gtk::HPaned.new
|
609
|
+
@paned.position=@config['paned_position']
|
610
|
+
@paned.add1(@wtree)
|
611
|
+
@paned.add2(@table)
|
612
|
+
|
613
|
+
@vbox=Gtk::VBox.new
|
614
|
+
@vbox.pack_start(@menu_bar, false, false, 0)
|
615
|
+
@vbox.pack_start(@paned)
|
616
|
+
@vbox.pack_start(@cdtable) if $cd
|
617
|
+
@vbox.pack_start(@radiotable) if $radio
|
618
|
+
@vbox.pack_start(@title_container, false, false)
|
619
|
+
@vbox.pack_start(@button_container, false, false)
|
620
|
+
|
621
|
+
super()
|
622
|
+
self.signal_connect("delete_event") {quit; false}
|
623
|
+
self.title=$name
|
624
|
+
@icon_Z=Gdk::Pixbuf.new(File.join(Pix_dir,'ZiK.svg'))
|
625
|
+
self.icon=(@icon_Z)
|
626
|
+
self.add_accel_group(@accel)
|
627
|
+
|
628
|
+
self.resize(@config['width'],@config['height'])
|
629
|
+
self.move(@config['x'],@config['y'])
|
630
|
+
|
631
|
+
self.add(@vbox)
|
632
|
+
|
633
|
+
@vbox.show_all
|
634
|
+
change_view
|
635
|
+
self.show
|
636
|
+
end
|
637
|
+
|
638
|
+
private
|
639
|
+
|
640
|
+
def change_view
|
641
|
+
case @selectview.active
|
642
|
+
when View::ALL
|
643
|
+
@paned.show; @paned.child1.show; @paned.child2.show
|
644
|
+
@badd.sensitive=true
|
645
|
+
@playlist_it.show; @broswe_it.show
|
646
|
+
@cdtable.hide if $cd
|
647
|
+
@radiotable.hide if $radio
|
648
|
+
@radiolist_it.hide if $radio
|
649
|
+
self.resize(self.size[0],@config['height']) if @config['view']=='player'
|
650
|
+
@config['view']='all'
|
651
|
+
@active_view='default'
|
652
|
+
when View::PLAYLIST
|
653
|
+
@paned.show; @paned.child1.hide; @paned.child2.show
|
654
|
+
@badd.sensitive=false
|
655
|
+
@playlist_it.show; @broswe_it.hide
|
656
|
+
@cdtable.hide if $cd
|
657
|
+
@radiotable.hide if $radio
|
658
|
+
@radiolist_it.hide if $radio
|
659
|
+
self.resize(self.size[0],@config['height']) if @config['view']=='player'
|
660
|
+
@config['view']='playlist'
|
661
|
+
@active_view='default'
|
662
|
+
when View::BROWSER
|
663
|
+
@paned.show; @paned.child1.show; @paned.child2.hide
|
664
|
+
@playlist_it.hide; @broswe_it.show
|
665
|
+
@cdtable.hide if $cd
|
666
|
+
@radiotable.hide if $radio
|
667
|
+
@radiolist_it.hide if $radio
|
668
|
+
self.resize(self.size[0],@config['height']) if @config['view']=='player'
|
669
|
+
@config['view']='browser'
|
670
|
+
@active_view='default'
|
671
|
+
when View::COMPACT
|
672
|
+
@paned.hide
|
673
|
+
@playlist_it.hide; @broswe_it.hide
|
674
|
+
@cdtable.hide if $cd
|
675
|
+
@radiotable.hide if $radio
|
676
|
+
@radiolist_it.hide if $radio
|
677
|
+
s=self.size; self.resize(s[0],1)
|
678
|
+
@config['height']=s[1]
|
679
|
+
@config['view']='player'
|
680
|
+
when View::CD
|
681
|
+
@paned.hide; @cdtable.show
|
682
|
+
@playlist_it.hide; @broswe_it.hide
|
683
|
+
@radiotable.hide if $radio
|
684
|
+
@radiolist_it.hide if $radio
|
685
|
+
self.resize(self.size[0],@config['height']) if @config['view']=='player'
|
686
|
+
@config['view']='cd'
|
687
|
+
@active_view='cd'
|
688
|
+
when View::RADIO
|
689
|
+
@paned.hide
|
690
|
+
@playlist_it.hide; @broswe_it.hide
|
691
|
+
@radiotable.show
|
692
|
+
@radiolist_it.show
|
693
|
+
@cdtable.hide if $cd
|
694
|
+
self.resize(self.size[0],@config['height']) if @config['view']=='player'
|
695
|
+
@config['view']='radio'
|
696
|
+
@active_view='radio'
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
public
|
701
|
+
|
702
|
+
def quit
|
703
|
+
pos=self.position;@config['x']=pos[0];@config['y']=pos[1]
|
704
|
+
s=self.size;@config['width']=s[0];@config['height']=s[1] unless @selectview.active==View::COMPACT
|
705
|
+
@config['paned_position']=@paned.position
|
706
|
+
|
707
|
+
Gtk.main_quit
|
708
|
+
end
|
709
|
+
|
710
|
+
def play(player_wanted=@active_view)
|
711
|
+
case player_wanted
|
712
|
+
when 'default'
|
713
|
+
if $cd
|
714
|
+
@cdplayer.stop if @cdplayer.playing?
|
715
|
+
end
|
716
|
+
if $radio
|
717
|
+
@radioplayer.stop if @radioplayer.playing?
|
718
|
+
end
|
719
|
+
playlist=@playlist
|
720
|
+
song=@playlist.songs[@playlist.current]
|
721
|
+
player=@player
|
722
|
+
store=@list_store
|
723
|
+
when 'cd'
|
724
|
+
@player.stop if @player.playing?
|
725
|
+
if $radio
|
726
|
+
@radioplayer.stop if @radioplayer.playing?
|
727
|
+
end
|
728
|
+
playlist=@cdlist
|
729
|
+
song=@cdlist.songs[@cdlist.current]
|
730
|
+
player=@cdplayer
|
731
|
+
store=@wcd.store
|
732
|
+
when 'radio'
|
733
|
+
@player.stop if @player.playing?
|
734
|
+
if $cd
|
735
|
+
@cdplayer.stop if @cdplayer.playing?
|
736
|
+
end
|
737
|
+
playlist=@radiolist
|
738
|
+
song=@radiolist.radios[@radiolist.current]
|
739
|
+
player=@radioplayer
|
740
|
+
store=@wradio.store
|
741
|
+
end
|
742
|
+
|
743
|
+
if song.nil?
|
744
|
+
ErrorError.new("Song n°#{playlist.current} do not exists.")
|
745
|
+
else
|
746
|
+
player.play(song)
|
747
|
+
self.signal_emit('play', song)
|
748
|
+
@song_title.text="#{song.name}"
|
749
|
+
duration=song.duration
|
750
|
+
if duration <= 0
|
751
|
+
@lduration.text='--:--'
|
752
|
+
@sposition.set_range(0,1200)#Use 20 minutes if song's duration is not known.
|
753
|
+
GLib::Timeout.add(600){get_gst_duration(player, song)}#if taglib cannot give the track duration, let's try GStreamer
|
754
|
+
elsif duration < 3600
|
755
|
+
@lduration.text=Time.at(duration).strftime("%M:%S")
|
756
|
+
@sposition.set_range(0,duration)
|
757
|
+
else
|
758
|
+
@lduration.text=(duration.to_i/3600).to_s+":"+Time.at(duration).strftime("%M:%S")
|
759
|
+
@sposition.set_range(0,duration)
|
760
|
+
end
|
761
|
+
store.each{|model, path, iter|
|
762
|
+
if path.to_s.to_i==playlist.current
|
763
|
+
iter[1]=true
|
764
|
+
else
|
765
|
+
iter[1]=false
|
766
|
+
end
|
767
|
+
}
|
768
|
+
nb_timeout=@nb_timeout+=1
|
769
|
+
GLib::Timeout.add(400){
|
770
|
+
position=player.position
|
771
|
+
if position <= 0
|
772
|
+
@lposition.text="--:--"
|
773
|
+
else
|
774
|
+
duration=song.duration#get an uptodate duration
|
775
|
+
if duration <= 0
|
776
|
+
@lposition.text=Time.at(position).strftime("%M:%S")
|
777
|
+
elsif duration < 3600
|
778
|
+
if @config['remaining_time']
|
779
|
+
t=duration-position; format="-%M:%S"
|
780
|
+
else
|
781
|
+
t=position; format="%M:%S"
|
782
|
+
end
|
783
|
+
@lposition.text=Time.at(t).strftime(format)
|
784
|
+
else
|
785
|
+
if @config['remaining_time']
|
786
|
+
t=duration-position
|
787
|
+
format="-"
|
788
|
+
else
|
789
|
+
t=position
|
790
|
+
format=""
|
791
|
+
end
|
792
|
+
@lposition.text=format+(t.to_i/3600).to_s+":"+Time.at(t).strftime("%M:%S")
|
793
|
+
end
|
794
|
+
end
|
795
|
+
@sposition.value=position unless @seeking
|
796
|
+
player.playing? && @nb_timeout==nb_timeout
|
797
|
+
}
|
798
|
+
if player_wanted=='radio'
|
799
|
+
@bprev.sensitive=false
|
800
|
+
@bnext.sensitive=false
|
801
|
+
else
|
802
|
+
@bprev.sensitive=true
|
803
|
+
@bnext.sensitive=true
|
804
|
+
end
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
private
|
809
|
+
|
810
|
+
def get_gst_duration(player, song, tryagain=true)
|
811
|
+
duration=player.duration
|
812
|
+
if duration>0
|
813
|
+
song.duration=duration
|
814
|
+
if duration < 3600
|
815
|
+
@lduration.text=Time.at(duration).strftime("%M:%S")
|
816
|
+
else
|
817
|
+
@lduration.text=(duration.to_i/3600).to_s+":"+Time.at(duration).strftime("%M:%S")
|
818
|
+
end
|
819
|
+
@sposition.set_range(0,duration)
|
820
|
+
else
|
821
|
+
GLib::Timeout.add(4000){get_gst_duration(player, song, false)} if tryagain
|
822
|
+
end
|
823
|
+
false
|
824
|
+
end
|
825
|
+
|
826
|
+
public
|
827
|
+
|
828
|
+
def stop
|
829
|
+
@player.stop
|
830
|
+
@cdplayer.stop if $cd
|
831
|
+
@radioplayer.stop if $radio
|
832
|
+
self.signal_emit('stop')
|
833
|
+
end
|
834
|
+
|
835
|
+
def pause
|
836
|
+
@player.pause
|
837
|
+
if $cd
|
838
|
+
@cdplayer.pause
|
839
|
+
end
|
840
|
+
if $radio
|
841
|
+
@radioplayer.pause
|
842
|
+
end
|
843
|
+
end
|
844
|
+
|
845
|
+
def active_player
|
846
|
+
active_player=nil
|
847
|
+
active_player='default' if @player.playing?
|
848
|
+
active_player='cd' if $cd&&@cdplayer.playing?
|
849
|
+
active_player='radio' if $radio&&@radioplayer.playing?
|
850
|
+
active_player=@active_view unless active_player
|
851
|
+
active_player
|
852
|
+
end
|
853
|
+
|
854
|
+
def playing?
|
855
|
+
return true if @player.playing?
|
856
|
+
return true if $cd&&@cdplayer.playing?
|
857
|
+
return true if $radio&&@radioplayer.playing?
|
858
|
+
false
|
859
|
+
end
|
860
|
+
|
861
|
+
def playpause
|
862
|
+
playing? ? pause : play
|
863
|
+
end
|
864
|
+
|
865
|
+
def previous_song
|
866
|
+
player=active_player
|
867
|
+
case player
|
868
|
+
when 'default'
|
869
|
+
playlist=@playlist
|
870
|
+
when 'cd'
|
871
|
+
playlist=@cdlist
|
872
|
+
when 'radio'
|
873
|
+
return
|
874
|
+
end
|
875
|
+
if playlist.previous_song
|
876
|
+
stop
|
877
|
+
play(player)
|
878
|
+
else
|
879
|
+
ErrorInfo.new("Begining of the playlist.")
|
880
|
+
end
|
881
|
+
end
|
882
|
+
|
883
|
+
def next_song
|
884
|
+
player=active_player
|
885
|
+
case player
|
886
|
+
when 'default'
|
887
|
+
playlist=@playlist
|
888
|
+
when 'cd'
|
889
|
+
playlist=@cdlist
|
890
|
+
when 'radio'
|
891
|
+
return
|
892
|
+
end
|
893
|
+
if playlist.next_song
|
894
|
+
stop
|
895
|
+
play(player)
|
896
|
+
else
|
897
|
+
ErrorInfo.new("End of the playlist.")
|
898
|
+
end
|
899
|
+
end
|
900
|
+
|
901
|
+
def next_song_on_error
|
902
|
+
unless @first_song_error
|
903
|
+
@first_song_error=@playlist.current
|
904
|
+
next_song
|
905
|
+
else
|
906
|
+
if @playlist.current==@first_song_error
|
907
|
+
ErrorError.new("All tracks seems to be inaccessible.")
|
908
|
+
else
|
909
|
+
next_song
|
910
|
+
end
|
911
|
+
end
|
912
|
+
end
|
913
|
+
|
914
|
+
def update_gst_registry
|
915
|
+
label=Gtk::Label.new(_("Loading new plugins. Please wait..."))
|
916
|
+
window=Gtk::Window.new
|
917
|
+
window.modal=true
|
918
|
+
window.transient_for=self
|
919
|
+
window.signal_connect("delete_event") {true}
|
920
|
+
window.add(label)
|
921
|
+
window.show_all
|
922
|
+
stop
|
923
|
+
Gst::Registry.update
|
924
|
+
window.destroy
|
925
|
+
play
|
926
|
+
end
|
927
|
+
|
928
|
+
def volume_up
|
929
|
+
inc=@bvolume.adjustment.page_increment
|
930
|
+
if @bvolume.value>1-inc
|
931
|
+
@bvolume.value=1
|
932
|
+
else
|
933
|
+
@bvolume.value+=inc
|
934
|
+
end
|
935
|
+
end
|
936
|
+
|
937
|
+
def volume_down
|
938
|
+
inc=@bvolume.adjustment.page_increment
|
939
|
+
if @bvolume.value<inc
|
940
|
+
@bvolume.value=0
|
941
|
+
else
|
942
|
+
@bvolume.value-=inc
|
943
|
+
end
|
944
|
+
end
|
945
|
+
|
946
|
+
def shuffle=(tf)
|
947
|
+
@config['shuffle']=tf
|
948
|
+
@shuffle_it.active=tf
|
949
|
+
@playlist.shuffle=tf
|
950
|
+
@cdlist.shuffle=tf if $cd
|
951
|
+
end
|
952
|
+
|
953
|
+
def repeat=(tf)
|
954
|
+
@config['repeat']=tf
|
955
|
+
@repeat_it.active=tf
|
956
|
+
@playlist.repeat=tf
|
957
|
+
@cdlist.repeat=tf if $cd
|
958
|
+
end
|
959
|
+
|
960
|
+
def refresh_treestore(directories, extension, start=false)
|
961
|
+
ErrorInfo.new('Refreshing tree view...')
|
962
|
+
self.cursor=Gdk::Cursor::WATCH
|
963
|
+
|
964
|
+
backup=File.join(User_dir,'tree')
|
965
|
+
unless File.exist?(backup)
|
966
|
+
Dir.mkdir(backup) if $saveconfig
|
967
|
+
end
|
968
|
+
BrowseSearchWindow.refresh
|
969
|
+
@treestore.clear
|
970
|
+
|
971
|
+
rexp=Regexp.new('.*\.('+extension.gsub(',','|')+')$', Regexp::IGNORECASE)
|
972
|
+
directories.split(',').each_with_index{|directory, nb|
|
973
|
+
if File.directory?(directory)
|
974
|
+
|
975
|
+
fback=File.join(backup, nb.to_s)
|
976
|
+
if (not @config['refresh_on_start'] and File.readable?(fback) and start)
|
977
|
+
#Read the list of files
|
978
|
+
f=File.open(fback,'r')
|
979
|
+
files=f.readlines
|
980
|
+
f.close
|
981
|
+
else
|
982
|
+
#List all music files
|
983
|
+
files=[]
|
984
|
+
Find.find(directory){|f| files.push(f) if f=~rexp}
|
985
|
+
@config['sort_case_sensitive'] ? files.sort! : files=files.sort_by{|f| f.downcase}
|
986
|
+
if $saveconfig
|
987
|
+
if @config['refresh_on_start']
|
988
|
+
#Delete list
|
989
|
+
ff=Dir.glob(File.join(backup,'*'))
|
990
|
+
File.delete(*ff)
|
991
|
+
else
|
992
|
+
#Save the list
|
993
|
+
f=File.open(fback,'w')
|
994
|
+
f.puts files
|
995
|
+
f.close
|
996
|
+
end
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
#Add root directory
|
1001
|
+
root=@treestore.append(nil)
|
1002
|
+
root[0]=directory;root[1]=directory
|
1003
|
+
hiter={directory=>root}
|
1004
|
+
|
1005
|
+
if @config['sort_directories_first']
|
1006
|
+
files.each{|file|
|
1007
|
+
dirname=File.dirname(file)
|
1008
|
+
refresh_treestore_dirs(hiter, dirname)
|
1009
|
+
}
|
1010
|
+
files.each{|file|
|
1011
|
+
ext=File.extname(file);name=File.basename(file,ext);dirname=File.dirname(file)
|
1012
|
+
refresh_treestore_file(file, name, hiter[dirname])
|
1013
|
+
}
|
1014
|
+
else
|
1015
|
+
files.each{|file|
|
1016
|
+
ext=File.extname(file);name=File.basename(file,ext);dirname=File.dirname(file)
|
1017
|
+
refresh_treestore_dirs(hiter, dirname)#Create directories from root directory to file
|
1018
|
+
refresh_treestore_file(file, name, hiter[dirname])#Add file
|
1019
|
+
}
|
1020
|
+
end
|
1021
|
+
else
|
1022
|
+
printf("#{directory} is not a directory...")
|
1023
|
+
end
|
1024
|
+
}
|
1025
|
+
self.cursor=Gdk::Cursor::ARROW
|
1026
|
+
ErrorInfo.new('Refreshing done.')
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
private
|
1030
|
+
|
1031
|
+
def refresh_treestore_dirs(hiter, dir)
|
1032
|
+
dirs=[]
|
1033
|
+
until ancestor=hiter[dir]
|
1034
|
+
dirs.push(dir)
|
1035
|
+
dir=File.expand_path(File.join(dir,'..'))
|
1036
|
+
end
|
1037
|
+
dirs.reverse!.each{|dir|
|
1038
|
+
child=@treestore.append(hiter[File.expand_path(File.join(dir,'..'))])
|
1039
|
+
child[0]=File.basename(dir);child[1]=dir
|
1040
|
+
hiter[dir]=child
|
1041
|
+
}
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
def refresh_treestore_file(file, name, iter)
|
1045
|
+
child=@treestore.append(iter)
|
1046
|
+
child[0]=name;child[1]=file
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
public
|
1050
|
+
|
1051
|
+
def compact(tf, scale_factor=0.7)
|
1052
|
+
#Must be called at initialization time (to set @hcompact)
|
1053
|
+
@hcompact={:weight=>@renderer2.weight, :ypad=>@renderer2.ypad,
|
1054
|
+
:spacing=>@col2.spacing} unless @hcompact
|
1055
|
+
if tf
|
1056
|
+
@renderer2.scale=scale_factor
|
1057
|
+
@renderer2.weight=@hcompact[:weight]/(scale_factor**0.5)
|
1058
|
+
@renderer2.ypad=0
|
1059
|
+
@col2.spacing=0
|
1060
|
+
else
|
1061
|
+
@renderer2.scale=1
|
1062
|
+
@renderer2.weight=@hcompact[:weight]
|
1063
|
+
@renderer2.ypad=@hcompact[:ypad]
|
1064
|
+
@col2.spacing=@hcompact[:spacing]
|
1065
|
+
end
|
1066
|
+
@col2.queue_resize
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
def refresh_liststore
|
1070
|
+
@list_store.clear
|
1071
|
+
i=0
|
1072
|
+
@playlist.songs.each{|song|
|
1073
|
+
child=@list_store.append
|
1074
|
+
child[0]=song.name
|
1075
|
+
@playlist.current==i ? child[1]=true : child[1]=false
|
1076
|
+
i+=1
|
1077
|
+
}
|
1078
|
+
if active_player=='default'&&!@song_title.nil?#@song_title is not defined when Gui object is created
|
1079
|
+
song=@playlist.songs[@playlist.current]
|
1080
|
+
@song_title.text="#{song.name}" unless song.nil?
|
1081
|
+
end
|
1082
|
+
end
|
1083
|
+
|
1084
|
+
def focus_to_current
|
1085
|
+
@list_view.scroll_to_cell(Gtk::TreePath.new(@playlist.current.to_s), nil, true, 0.5, 0.5)
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
def search(songs=@playlist.songs, selection=@list_selection, view=@list_view)
|
1089
|
+
proc=Proc.new{
|
1090
|
+
@wsearch=ListSearchWidget.new(songs, selection, view)
|
1091
|
+
if @editing
|
1092
|
+
@table.attach(@wsearch, 2, 8, 0, 1, Gtk::FILL, Gtk::SHRINK)
|
1093
|
+
else
|
1094
|
+
@table.attach(@wsearch, 1, 2, 0, 1, Gtk::FILL, Gtk::SHRINK)
|
1095
|
+
end
|
1096
|
+
}
|
1097
|
+
unless @wsearch
|
1098
|
+
proc.call
|
1099
|
+
else
|
1100
|
+
proc.call if @wsearch.destroyed?
|
1101
|
+
end
|
1102
|
+
@wsearch.focus
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
def refresh_playlist(new,force=false)
|
1106
|
+
unless new.songs==@playlist.songs
|
1107
|
+
if new.empty?
|
1108
|
+
@playlist.clear
|
1109
|
+
else
|
1110
|
+
@playlist.change_to(new)
|
1111
|
+
force=true
|
1112
|
+
end
|
1113
|
+
end
|
1114
|
+
refresh_liststore if force
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
def import_list
|
1118
|
+
dialog=Gtk::FileChooserDialog.new(_("Import a file"), self,
|
1119
|
+
Gtk::FileChooser::ACTION_OPEN, nil,
|
1120
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
|
1121
|
+
dialog.select_multiple=true
|
1122
|
+
dialog.show_hidden=false
|
1123
|
+
filter=Gtk::FileFilter.new
|
1124
|
+
filter.add_pattern('*.xspf');filter.add_pattern('*.m3u');filter.add_pattern('*.pls')
|
1125
|
+
filter.add_mime_type('audio/*')
|
1126
|
+
dialog.filter=filter
|
1127
|
+
if dialog.run==Gtk::Dialog::RESPONSE_ACCEPT
|
1128
|
+
dialog.filenames.each{|file| @playlist.add(file, @config['extension'])}
|
1129
|
+
refresh_liststore
|
1130
|
+
end
|
1131
|
+
dialog.destroy
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
def list_save
|
1135
|
+
dialog=Gtk::FileChooserDialog.new(_("Save playlist"), self,
|
1136
|
+
Gtk::FileChooser::ACTION_SAVE, nil,
|
1137
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
|
1138
|
+
dialog.do_overwrite_confirmation=true
|
1139
|
+
dialog.filter=Gtk::FileFilter.new.add_pattern('*.m3u').add_pattern('*.xspf')
|
1140
|
+
dialog.show_hidden=false
|
1141
|
+
if dialog.run==Gtk::Dialog::RESPONSE_ACCEPT
|
1142
|
+
f=dialog.filename
|
1143
|
+
case
|
1144
|
+
when f=~/.*\.xspf$/i
|
1145
|
+
@playlist.save_xspf(f, @config['relative_playlist'])
|
1146
|
+
when f=~/.*\.m3u$/i
|
1147
|
+
@playlist.save_m3u(f, @config['relative_playlist'])
|
1148
|
+
else
|
1149
|
+
@playlist.save_m3u(f+'.m3u', @config['relative_playlist'])
|
1150
|
+
end
|
1151
|
+
end
|
1152
|
+
dialog.destroy
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
def export_songs
|
1156
|
+
dialog=Gtk::FileChooserDialog.new(_("Export songs"), self,
|
1157
|
+
Gtk::FileChooser::ACTION_SAVE, nil,
|
1158
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
1159
|
+
[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
|
1160
|
+
dialog.do_overwrite_confirmation=true
|
1161
|
+
dialog.filter=Gtk::FileFilter.new.add_pattern('*.m3u').add_pattern('*.xspf')
|
1162
|
+
b=Gtk::RadioButton.new(_("Export all songs in this directory.")).show
|
1163
|
+
Gtk::RadioButton.new(b, _("Recreate songs tree under the destination directory.")).show
|
1164
|
+
dialog.extra_widget=hpack(b.group)
|
1165
|
+
if dialog.run==Gtk::Dialog::RESPONSE_ACCEPT
|
1166
|
+
f=dialog.filename
|
1167
|
+
if b.active?
|
1168
|
+
@exportlist=ExportList.new(@playlist.songs, f)
|
1169
|
+
else
|
1170
|
+
@exportlist=ExportList.new(@playlist.songs, f, @config['directory'])
|
1171
|
+
end
|
1172
|
+
@exportlist.write_plalist
|
1173
|
+
ErrorInfo.new('Copying audio files...')
|
1174
|
+
nb=@exportlist.nb.to_f
|
1175
|
+
wprogress=ProgressWindow.new(_("Copying audio files..."), self)
|
1176
|
+
wprogress.text="0/"+"#{nb.to_i}"
|
1177
|
+
require 'thread'; queue=Queue.new
|
1178
|
+
@exportlist.export(queue)
|
1179
|
+
GLib::Timeout.add_seconds(1){
|
1180
|
+
li=nil; error=nil
|
1181
|
+
until queue.empty?
|
1182
|
+
case o=queue.pop
|
1183
|
+
when Fixnum
|
1184
|
+
li=o
|
1185
|
+
else
|
1186
|
+
error=o
|
1187
|
+
break
|
1188
|
+
end
|
1189
|
+
end
|
1190
|
+
if li
|
1191
|
+
wprogress.fraction=(li+1)/nb
|
1192
|
+
wprogress.text="#{(li+1)}"+"/"+"#{nb.to_i}"
|
1193
|
+
end
|
1194
|
+
if error
|
1195
|
+
wprogress.destroy
|
1196
|
+
if error.kind_of?(ErrorsStock)
|
1197
|
+
o.show_all(n_("An error occured while exporting songs.\n",
|
1198
|
+
"Some errors occured while exporting songs.\n", o.nb))
|
1199
|
+
else
|
1200
|
+
ErrorError.new(
|
1201
|
+
_("An error occured while exporting songs.\nUnknown queued object type (#{o.class})."), true)
|
1202
|
+
end
|
1203
|
+
false
|
1204
|
+
else
|
1205
|
+
true
|
1206
|
+
end
|
1207
|
+
}
|
1208
|
+
end
|
1209
|
+
dialog.destroy
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
def abort_export_songs
|
1213
|
+
@exportlist.abort_export
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
def list_add(selection, extension)
|
1217
|
+
selection.selected_each{|model, path, iter| @playlist.add(iter[1], extension)}
|
1218
|
+
refresh_liststore
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
def list_add_at(selection, extension, position)
|
1222
|
+
elist=Editlist.new([], @config['name_format'])
|
1223
|
+
selection.selected_each{|model, path, iter| elist.add(iter[1], extension)}
|
1224
|
+
elist.merge(@playlist, position)
|
1225
|
+
@playlist.change_to(elist)
|
1226
|
+
refresh_liststore
|
1227
|
+
end
|
1228
|
+
|
1229
|
+
def list_add_uris(uris, extension)
|
1230
|
+
uris.each{|uri| @playlist.add(GLib.filename_from_uri(uri)[0], extension)}
|
1231
|
+
refresh_liststore
|
1232
|
+
end
|
1233
|
+
|
1234
|
+
def list_add_uris_at(uris, extension, position)
|
1235
|
+
elist=Editlist.new([], @config['name_format'])
|
1236
|
+
uris.each{|uri| elist.add(GLib.filename_from_uri(uri)[0], extension)}
|
1237
|
+
elist.merge(@playlist, position)
|
1238
|
+
@playlist.change_to(elist)
|
1239
|
+
refresh_liststore
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
def list_rm(selection)
|
1243
|
+
i=[]
|
1244
|
+
selection.selected_each{|model, path, iter| i.push(path.to_s.to_i)}
|
1245
|
+
i=i.sort {|x,y| y<=> x}
|
1246
|
+
i.each{|num|
|
1247
|
+
current_removed=@playlist.rm(num)
|
1248
|
+
@player.stop if current_removed
|
1249
|
+
}
|
1250
|
+
refresh_liststore
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
def list_clear
|
1254
|
+
@player.stop
|
1255
|
+
@playlist.clear
|
1256
|
+
refresh_liststore
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
def list_edit
|
1260
|
+
@editing=true
|
1261
|
+
begin; @wsearch.destroy; rescue; end
|
1262
|
+
elist=Editlist.new(@playlist.songs, @config['name_format'])
|
1263
|
+
@edit_wrapper=EditListWrapper.new(self, elist, @config)
|
1264
|
+
bcancel=Gtk::Button.new(Gtk::Stock::CANCEL)
|
1265
|
+
bok=Gtk::Button.new(Gtk::Stock::OK)
|
1266
|
+
pquit=Proc.new{
|
1267
|
+
@bedit.sensitive=true
|
1268
|
+
@wlist.show
|
1269
|
+
@edit_wrapper.destroy
|
1270
|
+
bcancel.destroy
|
1271
|
+
bok.destroy
|
1272
|
+
begin; @wsearch.destroy; rescue; end
|
1273
|
+
@playlist_it.set_submenu(@playlist_menu)
|
1274
|
+
@table.resize(8, 2)
|
1275
|
+
@editing=false
|
1276
|
+
}
|
1277
|
+
pcancel=Proc.new{
|
1278
|
+
if @edit_wrapper.force_refresh_parent
|
1279
|
+
@edit_wrapper.refresh_list
|
1280
|
+
refresh_liststore
|
1281
|
+
end
|
1282
|
+
}
|
1283
|
+
pok=Proc.new{
|
1284
|
+
@edit_wrapper.refresh_list
|
1285
|
+
refresh_playlist(@edit_wrapper.list, @edit_wrapper.force_refresh_parent)
|
1286
|
+
}
|
1287
|
+
bcancel.signal_connect('clicked'){
|
1288
|
+
pcancel.call
|
1289
|
+
pquit.call
|
1290
|
+
}
|
1291
|
+
bcancel.show
|
1292
|
+
bok.signal_connect('clicked'){
|
1293
|
+
pok.call
|
1294
|
+
pquit.call
|
1295
|
+
}
|
1296
|
+
bok.show
|
1297
|
+
cancel_it=Gtk::ImageMenuItem.new(Gtk::Stock::CANCEL)
|
1298
|
+
cancel_it.signal_connect('activate'){pcancel.call; pquit.call}
|
1299
|
+
ok_it=Gtk::ImageMenuItem.new(Gtk::Stock::OK)
|
1300
|
+
ok_it.signal_connect('activate'){pok.call; pquit.call}
|
1301
|
+
playlist_menu=Gtk::Menu.new
|
1302
|
+
playlist_menu.append(cancel_it)
|
1303
|
+
playlist_menu.append(ok_it)
|
1304
|
+
playlist_menu.show_all
|
1305
|
+
@playlist_it.set_submenu(playlist_menu)
|
1306
|
+
@table.attach(@edit_wrapper.table, 2, 8, 1, 8)
|
1307
|
+
@table.attach(@edit_wrapper.badd, 3, 4, 8, 9, Gtk::SHRINK, Gtk::SHRINK)
|
1308
|
+
@table.attach(@edit_wrapper.bsave, 4, 5, 8, 9, Gtk::SHRINK, Gtk::SHRINK)
|
1309
|
+
@table.attach(bcancel, 6, 7, 8, 9, Gtk::SHRINK, Gtk::SHRINK)
|
1310
|
+
@table.attach(bok, 7, 8, 8, 9, Gtk::SHRINK, Gtk::SHRINK)
|
1311
|
+
@bedit.sensitive=false
|
1312
|
+
@wlist.hide
|
1313
|
+
dialog=Gtk::MessageDialog.new(self, Gtk::Dialog::MODAL, Gtk::MessageDialog::INFO,
|
1314
|
+
Gtk::MessageDialog::BUTTONS_CLOSE,
|
1315
|
+
_("Do not forget to validate your changes after editing the playlist."))
|
1316
|
+
dialog.run; dialog.destroy
|
1317
|
+
end
|
1318
|
+
|
1319
|
+
if $radio
|
1320
|
+
def radios_edit
|
1321
|
+
elist=Radio::EditList.new(@radiolist.radios)
|
1322
|
+
Radio::Edit.new(self, elist, @wradio)
|
1323
|
+
end
|
1324
|
+
|
1325
|
+
def refresh_radiolist(new, force)
|
1326
|
+
unless new.radios==@radiolist.radios
|
1327
|
+
if new.radios.empty?
|
1328
|
+
@radiolist.clear
|
1329
|
+
else
|
1330
|
+
@radiolist.change_to(new)
|
1331
|
+
force=true
|
1332
|
+
end
|
1333
|
+
end
|
1334
|
+
@wradio.refresh_store if force
|
1335
|
+
end
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
def cursor=(c)
|
1339
|
+
self.window.cursor=Gdk::Cursor.new(c)
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
def help
|
1343
|
+
case ENV['LANG']
|
1344
|
+
when /^fr/i then index='html/fr/index.html'
|
1345
|
+
else index='html/index.html'
|
1346
|
+
end
|
1347
|
+
unless system("gnome-open #{File.join(Doc_dir,index)}")
|
1348
|
+
ErrorError.new(_("Cannot open #{File.join(Doc_dir,index)}"), true)
|
1349
|
+
unless index=='html/index.html'
|
1350
|
+
unless system("gnome-open #{File.join(Doc_dir,'html/index.html')}")
|
1351
|
+
ErrorError.new(_("Cannot open #{File.join(Doc_dir,'html/index.html')}"), true)
|
1352
|
+
end
|
1353
|
+
end
|
1354
|
+
end
|
1355
|
+
end
|
1356
|
+
|
1357
|
+
def about
|
1358
|
+
begin
|
1359
|
+
f=File.open(File.join(Doc_dir,'COPYING'))
|
1360
|
+
copying=''
|
1361
|
+
while line=f.gets
|
1362
|
+
copying+=line
|
1363
|
+
end
|
1364
|
+
rescue
|
1365
|
+
copying="Error: license file was not found.\n
|
1366
|
+
The GNU General Public License, version 2 can be found at:\nhttp://www.gnu.org/licenses/gpl-2.0.html"
|
1367
|
+
ensure
|
1368
|
+
f.close unless f.nil?
|
1369
|
+
end
|
1370
|
+
authors=["Vincent Carmona <vinc4mai@gmail.com>"]
|
1371
|
+
if $module
|
1372
|
+
3.times{authors.push("")}; authors.push("Modules"); authors.push("")
|
1373
|
+
Mod.all.each{|mod| authors.push(" "+mod.title+": "+mod.author)}
|
1374
|
+
end
|
1375
|
+
Gtk::AboutDialog.show(self, {:name=>$name, :version=>Version, :program_name=>$name,
|
1376
|
+
:copyright=>'Copyright 2007-2010 Vincent Carmona', :comments=>_('Audio player'),
|
1377
|
+
:website=>'http://zik.rubyforge.org/', :license=>copying,
|
1378
|
+
:authors=>authors,
|
1379
|
+
:artists=>["Jakub Steiner", "Lapo Calamandrei", "Andreas Nilsson", "Rodney Dawes", "Vincent Carmona"],
|
1380
|
+
:translator_credits=>"Français: Vincent Carmona\n",
|
1381
|
+
:logo=>Gdk::Pixbuf.new(File.join(Pix_dir,'ZiK3.png'))})
|
1382
|
+
end
|
1383
|
+
end
|