add option -d in order to indicate the path to configuration files
[zik.git] / data / gui.rb
blobd35482146f2529022c92af9641bd929e2bca320a
1 =begin
2 Copyright 2007-2008 Vincent Carmona
4 This file is part of ZiK.
6     ZiK is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
11     ZiK is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
16     You should have received a copy of the GNU General Public License
17     along with ZiK; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 =end
21 class Gui < Gtk::Window
22         include GetText
23         bindtextdomain('ZiK',{:path=>Ldir})
24         
25         include ReadPlaylist
26         
27         def initialize
28 ####################################
29 #-------Preferences-----------------
30 ####################################
31                 @pref=Preference.new
32                 
33                 @border_width=10
34                 @showlistn=1
35 ####################################
36 #-----------Gstreamer player--------
37 ####################################
38                 @list1=Playlist.new(self,true)
39                 @player=Player.new(@list1,@pref.player)
40                 @player.volume=@pref.player['volume']/100
41 ##################
42 #-------Gui-------
43 ##################
44                 @seeking=false
45 #*****************Explorer & list widgets****************
46                 ###---Browse--------
47                 @treestore=Tree.new(String,String,String)
48                 @path_explo=@treestore.refresh(@pref.dir,@pref.ext)
49                 
50                 @iadd2plist_tree=Gtk::Image.new(Gtk::Stock::GO_FORWARD,Gtk::IconSize::MENU)
51                 @badd2plist_tree=Gtk::ImageMenuItem.new(_('Add to playlist'))
52                 @badd2plist_tree.image=@iadd2plist_tree
53                 @badd2plist_tree.signal_connect("activate") {
54                         case @showlistn
55                         when 1
56                                 @list1.add(@tree_select)
57                                 @player.add
58                         when 2
59                                 @list2.add(@tree_select)
60                         end
61                 }
62                 @sep_tree=Gtk::SeparatorMenuItem.new
63                 @brefresh_tree=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
64                 @brefresh_tree.signal_connect("activate") {@path_explo=@treestore.refresh(@pref.dir,@pref.ext)}
65                 @badd_tree=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)#Optimiser le code. -> ne pas rafraichir mais ajouter les nouveaux élements.
66                 @badd_tree.signal_connect("activate") {
67                         dialog=Gtk::FileChooserDialog.new(_("Add a directory"), self,
68                                 Gtk::FileChooser::ACTION_SELECT_FOLDER, nil,
69                                 [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
70                         if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
71                                 @pref.dir.push(dialog.filename)
72                                 @path_explo=@treestore.refresh(@pref.dir,@pref.ext)
73                         end
74                         dialog.destroy
75                 }
76                 @brm_tree=Gtk::ImageMenuItem.new(Gtk::Stock::REMOVE)
77                 @brm_tree.signal_connect("activate") {
78                         rm=false; collect=[]
79                         @tree_select.selected_each{|model,path,iter|
80                                 if path.depth==1
81                                         collect.push(path.to_s.to_i)
82                                         rm=true
83                                 end
84                         }
85                         if rm
86                                 collect.sort!; a=0
87                                 collect.each{|i| @pref.dir.delete_at(i-a);a+=1}
88                                 @path_explo=@treestore.refresh(@pref.dir,@pref.ext)
89                         else
90                                 puts "Delete only root directories"
91                         end
92                 }
93                 @bclear_tree=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
94                 @bclear_tree.signal_connect("activate") {@pref.dir.clear; @treestore.clear}
95                 @bpref_tree=Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
96                 @bpref_tree.signal_connect("activate") {
97                         dialog=Option.new(self,@pref.dir,@pref.ext,@border_width)
98                         if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
99                                 @pref.dir=dialog.dir
100                                 @pref.ext=dialog.ext
101                                 @path_explo=@treestore.refresh(@pref.dir,@pref.ext)
102                         end  
103                         dialog.destroy
104                 }
105                 @popup_tree=Gtk::Menu.new
106                 @popup_tree.append(@badd2plist_tree)
107                 @popup_tree.append(@sep_tree)
108                 @popup_tree.append(@brefresh_tree)
109                 @popup_tree.append(@badd_tree)
110                 @popup_tree.append(@brm_tree)
111                 @popup_tree.append(@bclear_tree)
112                 @popup_tree.append(@bpref_tree)
113                 @popup_tree.show_all
114                 
115                 @treeview=Gtk::TreeView.new(@treestore)
116                 @tree_select=@treeview.selection
117                 @tree_select.mode = Gtk::SELECTION_MULTIPLE
118                 @renderer = Gtk::CellRendererText.new
119                 @col = Gtk::TreeViewColumn.new(_("Browse"), @renderer, :text => 0)
120                 @treeview.append_column(@col)
121                 
122                 @treeview.signal_connect("button_press_event"){|widget, event|
123                         if event.button == 3
124                                 @popup_tree.popup(nil, nil, event.button, event.time)
125                         end
126                 }
127                 
128                 @wtree=Gtk::ScrolledWindow.new
129                 @wtree.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
130                 @wtree.add(@treeview)
131                 ###---Buttons---------
132                 @badd=Gtk::Button.new
133                 @badd.add(Gtk::Image.new(Gtk::Stock::GO_FORWARD,Gtk::IconSize::BUTTON))
134                 @badd.signal_connect('clicked') {
135                 case @showlistn
136                 when 1
137                         @list1.add(@tree_select)
138                         @player.add
139                 when 2
140                         @list2.add(@tree_select)
141                 when 3
142                         add_radio
143                 end
144                 }
145                 @bdel=Gtk::Button.new
146                 @bdel.add(Gtk::Image.new(Gtk::Stock::GO_BACK,Gtk::IconSize::BUTTON))
147                 @bdel.signal_connect('clicked') {
148                 case @showlistn
149                 when 1
150                         sel=@list1.del(@list1_select)
151                         @player.del(sel)
152                         current_shuffle=@player.order[@player.current]
153                         name=@list1.name[current_shuffle]
154                         duration=(@list1.duration[current_shuffle].to_i)
155                         @stitle.set_markup("<b>#{name}</b>")
156                         if duration <= 0
157                                 show_duration=false
158                                 @lduration.text='--:--'
159                         else
160                                 show_duration=true
161                                 @barpos.set_range(0,duration)
162                                 duration_s=(Time.at(duration).strftime("%M:%S"))
163                                 @lduration.text=duration_s
164                         end
165                         @list1.store.each{|model,path,iter|
166                                 if iter[0]==name
167                                         iter[1]=true
168                                 else
169                                         iter[1]=false
170                                 end
171                         }
172                 when 2
173                         @list2.del(@list2_select)
174                 when 3
175                         rm_radio
176                 end
177                 }
178                 @bclear=Gtk::Button.new
179                 @bclear.add(Gtk::Image.new(Gtk::Stock::CLEAR,Gtk::IconSize::BUTTON))
180                 @bclear.signal_connect('clicked') {
181                 case @showlistn
182                 when 1
183                         @player.stop
184                         @player.del_all
185                         @list1.del_all
186                 when 2
187                         @list2.del_all
188                 when 3
189                         @player.stop
190                         @pref.radio.clear
191                         @radiostore.clear
192                 end
193                 }
194                 ###---Lists-------------
195                 #choose the list
196                 @combolist=Gtk::ComboBox.new
197                 @combolist.append_text(_('Listen to playlist'))
198                 @combolist.append_text(_('Manage a secondary list'))
199                 @combolist.append_text(_('Listen to radio'))
200                 #@combolist.append_text(_('Lire un cd'))
201                 @combolist.active=0
202                 @combolist.signal_connect('changed'){
203                 case @combolist.active
204                 when 0
205                         @wradio.hide;@wlist2.hide;@mbox.hide;@wcd.hide;@wlist1.show;@showlistn=1
206                 when 1
207                         @wradio.hide;@wlist1.hide;@wcd.hide;@wlist2.show;@mbox.show;@showlistn=2
208                 when 2
209                         @wlist1.hide;@wlist2.hide;@mbox.hide;@wcd.hide;@wradio.show;@showlistn=3
210                 when 3
211                         @wlist1.hide;@wlist2.hide;@mbox.hide;@wradio.hide;@wcd.show;@showlistn=4
212                 end
213                 }
214                 
215                 #List 1
216                 #@list1=Playlist.new(self,true)  Already done
217                 
218                 @irm_list1=Gtk::Image.new(Gtk::Stock::GO_BACK,Gtk::IconSize::MENU)
219                 @brm_list1=Gtk::ImageMenuItem.new(_('Delete'))
220                 @brm_list1.image=@irm_list1
221                 @brm_list1.signal_connect("activate") {
222                         sel=@list1.del(@list1_select)
223                         @player.del(sel)
224                 }
225                 @brefresh_list1=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
226                 @brefresh_list1.signal_connect("activate") {@list1.refresh}
227                 @bexport_list1=Gtk::ImageMenuItem.new(Gtk::Stock::SAVE)
228                 @bexport_list1.signal_connect("activate") {@list1.export(self)}
229                 @bimport_list1=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)
230                 @bimport_list1.signal_connect("activate") {@list1.import(self);@player.add}
231                 @bclear_list1=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
232                 @bclear_list1.signal_connect("activate") {
233                         @player.stop unless @player.radio?
234                         @player.del_all
235                         @list1.del_all
236                 }
237                 @bsearch_list1=Gtk::ImageMenuItem.new(Gtk::Stock::FIND)
238                 @bsearch_list1.signal_connect("activate"){
239                         @combolist.active=0
240                         @wsearch_plist=Search::List.new unless Search.plist?
241                         position=self.position+@boxlist.allocation.to_a
242                         @wsearch_plist.search(position,@list1,@listview1)
243                 }
244                 @sep_list1=Gtk::SeparatorMenuItem.new
245                 @bedit_list1=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
246                 @bedit_list1.signal_connect("activate") {EditTag.new(self,@list1_select,@list1,@border_width)}
247                 @popup_list1=Gtk::Menu.new
248                 @popup_list1.append(@brm_list1)
249                 @popup_list1.append(@brefresh_list1)
250                 @popup_list1.append(@bexport_list1)
251                 @popup_list1.append(@bimport_list1)     
252                 @popup_list1.append(@bclear_list1)
253                 @popup_list1.append(@bsearch_list1)
254                 @popup_list1.append(@sep_list1)
255                 @popup_list1.append(@bedit_list1)
256                 @popup_list1.show_all
257                 
258                 @listview1=Gtk::TreeView.new(@list1.store)
259                 @listview1.headers_visible=false
260                 @list1_select=@listview1.selection
261                 @list1_select.mode = Gtk::SELECTION_MULTIPLE
262                 @renderer=Gtk::CellRendererText.new
263                 #@renderer.weight=Pango::WEIGHT_BOLD
264                 #@col=Gtk::TreeViewColumn.new("Liste de lecture", @renderer, :text => 0, :weight_set => 1)
265                 @renderer.background='Pink'#cf:/etc/X11/rgb.txt
266                 @col=Gtk::TreeViewColumn.new("Liste de lecture", @renderer, :text => 0, :background_set => 1)
267                 @listview1.append_column(@col)
268                 
269                 @listview1.signal_connect("row-activated"){|view, path, column|
270                         @player.stop
271                         play(path.to_s.to_i)
272                         }
273                 @listview1.signal_connect("button_press_event"){|widget, event|
274                         if event.button == 3
275                                 @popup_list1.popup(nil, nil, event.button, event.time)
276                         end
277                 }
278                 
279                 @wlist1=Gtk::ScrolledWindow.new
280                 @wlist1.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
281                 @wlist1.add(@listview1)
282                 
283                 #List 2
284                 @list2=Playlist.new(self)
285                 
286                 @irm_list2=Gtk::Image.new(Gtk::Stock::GO_BACK,Gtk::IconSize::MENU)
287                 @brm_list2=Gtk::ImageMenuItem.new(_('Delete'))
288                 @brm_list2.image=@irm_list2
289                 @brm_list2.signal_connect("activate") {
290                         sel=@list2.del(@list2_select)
291                         @player.del(sel)
292                 }
293                 @brefresh_list2=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
294                 @brefresh_list2.signal_connect("activate") {@list2.refresh}
295                 @bexport_list2=Gtk::ImageMenuItem.new(Gtk::Stock::SAVE)
296                 @bexport_list2.signal_connect("activate") {@list2.export(self)}
297                 @bimport_list2=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)
298                 @bimport_list2.signal_connect("activate") {@list2.import(self);@player.add}
299                 @bclear_list2=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
300                 @bclear_list2.signal_connect("activate") {
301                         @player.stop unless @player.radio?
302                         @player.del_all
303                         @list2.del_all
304                 }
305                 @sep_list2=Gtk::SeparatorMenuItem.new
306                 @bedit_list2=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
307                 @bedit_list2.signal_connect("activate") {EditTag.new(self,@list2_select,@list2,@border_width)}
308                 @popup_list2=Gtk::Menu.new
309                 @popup_list2.append(@brm_list2)
310                 @popup_list2.append(@brefresh_list2)
311                 @popup_list2.append(@bexport_list2)
312                 @popup_list2.append(@bimport_list2)     
313                 @popup_list2.append(@bclear_list2)
314                 @popup_list2.append(@sep_list2)
315                 @popup_list2.append(@bedit_list2)
316                 @popup_list2.show_all
317         
318                 @listview2=Gtk::TreeView.new(@list2.store)
319                 @listview2.headers_visible=false
320                 @list2_select=@listview2.selection
321                 @list2_select.mode = Gtk::SELECTION_MULTIPLE
322                 @renderer = Gtk::CellRendererText.new
323                 @col=Gtk::TreeViewColumn.new("Gérer une liste", @renderer, :text => 0)
324                 @listview2.append_column(@col)
325                 
326                 @listview2.signal_connect("button_press_event"){|widget, event|
327                         if event.button == 3
328                                 @popup_list2.popup(nil, nil, event.button, event.time)
329                         end
330                 }
331                 
332                 @wlist2=Gtk::ScrolledWindow.new
333                 @wlist2.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
334                 @wlist2.add(@listview2)
335                 
336                 #Buttons
337                 @iup=Gtk::Image.new(Gtk::Stock::GO_UP,Gtk::IconSize::BUTTON)
338                 @bup=Gtk::Button.new
339                 @bup.image=@iup
340                 @bup.signal_connect('clicked') {@list2.up(@list2_select)}
341                 @idown=Gtk::Image.new(Gtk::Stock::GO_DOWN,Gtk::IconSize::BUTTON)
342                 @bdown=Gtk::Button.new
343                 @bdown.image=@idown
344                 @bdown.signal_connect('clicked') {@list2.down(@list2_select)}
345                 @iexplo2m=Gtk::Image.new(Gtk::Stock::ADD,Gtk::IconSize::BUTTON)
346                 @bexplo2m=Gtk::Button.new
347                 @bexplo2m.image=@iexplo2m
348                 @bexplo2m.signal_connect('clicked') {@list2.import(self)}
349                 @im2explo=Gtk::Image.new(Gtk::Stock::SAVE,Gtk::IconSize::BUTTON)
350                 @bm2explo=Gtk::Button.new
351                 @bm2explo.image=@im2explo
352                 @bm2explo.signal_connect('clicked') {@list2.export(self)}
353                 @iplist2m=Gtk::Image.new(Gtk::Stock::COPY,Gtk::IconSize::BUTTON)
354                 @bplist2m=Gtk::Button.new
355                 @bplist2m.image=@iplist2m
356                 @bplist2m.signal_connect('clicked') {@list2.copy(@list1)}
357                 @im2plist=Gtk::Image.new(Gtk::Stock::PASTE,Gtk::IconSize::BUTTON)
358                 @bm2plist=Gtk::Button.new
359                 @bm2plist.image=@im2plist
360                 @bm2plist.signal_connect('clicked') {
361                         @list1.copy(@list2)
362                         @player.add
363                 }
364                 
365                 
366                 @mbox=Gtk::HBox.new(false, 0)
367                 @mbox.pack_start(@bexplo2m, true, false)
368                 @mbox.pack_start(@bm2explo, true, false)
369                 @mbox.pack_start(@bup, true, false)
370                 @mbox.pack_start(@bdown, true, false)
371                 @mbox.pack_start(@bplist2m, true, false)
372                 @mbox.pack_start(@bm2plist, true, false)
373                 
374                 #Radio
375                 @radiostore=Gtk::ListStore.new(String,String)
376                 @pref.radio.each{|key,value|
377                         child=@radiostore.append
378                         child[0]=key
379                         child[1]=value
380                         }
381                 
382                 @iadd_radio=Gtk::Image.new(Gtk::Stock::GO_FORWARD,Gtk::IconSize::MENU)
383                 @badd_radio=Gtk::ImageMenuItem.new(_('Add a radio'))
384                 @badd_radio.image=@iadd_radio
385                 @badd_radio=Gtk::ImageMenuItem.new(Gtk::Stock::GO_FORWARD)
386                 @irm_radio=Gtk::Image.new(Gtk::Stock::GO_BACK,Gtk::IconSize::MENU)
387                 @brm_radio=Gtk::ImageMenuItem.new(_('Delete a radio'))
388                 @brm_radio.image=@irm_radio
389                 @badd_radio.signal_connect("activate") {rm_radio}
390                 @bclear_radio=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
391                 @bclear_radio.signal_connect("activate") {
392                         @player.stop if @player.radio?
393                         @pref.radio.clear
394                         @radiostore.clear
395                 }
396                 @sep_radio=Gtk::SeparatorMenuItem.new
397                 @bedit_radio=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)#Gtk::MenuItem.new('Éditer')
398                 @bedit_radio.signal_connect("activate") {edit_radio(@radio_select.selected)}
399                 @popup_radio=Gtk::Menu.new
400                 @popup_radio.append(@badd_radio)
401                 @popup_radio.append(@brm_radio)
402                 @popup_radio.append(@bclear_radio)
403                 @popup_radio.append(@sep_radio)
404                 @popup_radio.append(@bedit_radio)
405                 @popup_radio.show_all
406                 
407                 @radioview=Gtk::TreeView.new(@radiostore)
408                 @radioview.headers_visible=false
409                 @radio_select=@radioview.selection
410                 @radio_select.mode = Gtk::SELECTION_SINGLE
411                 @renderer = Gtk::CellRendererText.new
412                 @col=Gtk::TreeViewColumn.new("Écouter la radio", @renderer, :text => 0)
413                 @radioview.append_column(@col)
414                 
415                 @radioview.signal_connect("row-activated"){@player.stop;play_radio}     
416                 @radioview.signal_connect("button_press_event"){|widget, event|
417                         if event.button == 3
418                                 @popup_radio.popup(nil, nil, event.button, event.time)
419                         end
420                 }
421                 
422                 @wradio=Gtk::ScrolledWindow.new
423                 @wradio.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
424                 @wradio.add(@radioview)
425                 
426                 #Cd
427                 @cdstore=Gtk::ListStore.new(String)
428                 @cdview=Gtk::TreeView.new(@cdstore)
429                 @cdview.headers_visible=false
430                 @renderer = Gtk::CellRendererText.new
431                 @col=Gtk::TreeViewColumn.new("Lire un cd", @renderer, :text => 0)
432                 @cdview.append_column(@col)
433                 
434                 @wcd=Gtk::ScrolledWindow.new
435                 @wcd.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
436                 @wcd.add(@cdview)
437                 
438                 #Box
439                 @boxlist=Gtk::VBox.new(false, 0)
440                 @boxlist.pack_start(@combolist, false, false, 0)
441                 @boxlist.pack_start(@wlist1)
442                 @boxlist.pack_start(@wlist2)
443                 @boxlist.pack_start(@wradio)
444                 @boxlist.pack_start(@wcd)
445                 @boxlist.pack_start(@mbox,false, false, 0)
447                 ###---Containers--------
448                 @table=Gtk::Table.new(5,2)
449                 @table.column_spacings=(5)
450                 @table.attach(@wtree, 0, 1, 0, 5)
451                 @table.attach(@badd, 1, 2, 1, 2, Gtk::SHRINK, Gtk::SHRINK)
452                 @table.attach(@bdel, 1, 2, 2, 3, Gtk::SHRINK, Gtk::SHRINK)
453                 @table.attach(@bclear, 1, 2, 3, 4, Gtk::SHRINK, Gtk::SHRINK)
454                 
455                 @paned=Gtk::HPaned.new
456                 #@paned.border_width=@border_width
457                 @paned.position=@pref.gui['paned_position']
458                 @paned.add1(@table)
459                 @paned.add2(@boxlist)
460 #**************Player buttons*********************
461                 #hide/show explo
462                 @iexplo=Gtk::Image.new('gtk-directory',Gtk::IconSize::BUTTON)#Gtk::Stock::DIRECTORY is not (yet?) initialized.
463                 @bexplo=Gtk::Button.new
464                 @bexplo.image=@iexplo
465                 @bexplo.signal_connect('clicked') {
466                         if @pref.gui['showexplo']
467                                 @paned.child1.hide
468                                 unless @pref.gui['showlist']
469                                         @paned.hide;self.resize(400,100)
470                                 end
471                         else
472                                 if @pref.gui['showlist']
473                                         s=self.size
474                                         @pref.gui['width']=s[0];@pref.gui['height']=s[1]
475                                 end
476                                 @paned.child1.show;@paned.show;self.resize(@pref.gui['width'],@pref.gui['height'])
477                         end
478                         @pref.gui['showexplo']=!@pref.gui['showexplo']
479                         }
480                 #hide/show list
481                 @ilist=Gtk::Image.new(Gtk::Stock::INDEX,Gtk::IconSize::BUTTON)
482                 @blist=Gtk::Button.new
483                 @blist.image=@ilist
484                 @blist.signal_connect('clicked') {
485                         if @pref.gui['showlist']
486                                 @paned.child2.hide
487                                 unless @pref.gui['showexplo']
488                                         @paned.hide;self.resize(400,100)
489                                 end
490                         else
491                                 if @pref.gui['showexplo']
492                                         s=self.size
493                                         @pref.gui['width']=s[0];@pref.gui['height']=s[1]
494                                 end
495                                 @paned.child2.show;@paned.show;self.resize(@pref.gui['width'],@pref.gui['height'])
496                         end
497                         @pref.gui['showlist']=!@pref.gui['showlist']
498                         }
499                 #Song name
500                 @stitle=Gtk::Label.new()
501                 @stitle.wrap=true
502                 
503                 @vtitle=Gtk::Frame.new#('Titre en cours')
504                 @vtitle.add(@stitle)
505                 #Volume
506                 @barvol=Gtk::VScale.new(0,100,1)
507                 @barvol.digits=0
508                 @barvol.inverted=true
509                 @barvol.value=@pref.player['volume']
510                 @barvol.signal_connect('value-changed'){@player.volume=@barvol.value/100}
511                 @barvol.show
512                 
513                 @wvol=Gtk::Window.new
514                 @wvol.decorated=false
515                 @wvol.skip_taskbar_hint=true
516                 @wvol.skip_pager_hint=true
517                 @wvol.set_size_request(40,200)
518                 @wvol.resizable=false
519                 #@wvol.transient_for=(self)
520                 @wvol.add(@barvol)
521                 @wvol.signal_connect("focus-out-event"){@wvol.hide}
522                 
523                 @ivol=Gtk::Image.new(File.join(Pdir,'volume.xpm'))
524                 @bvol=Gtk::Button.new
525                 @bvol.image=@ivol
526                 @barvol.can_focus=true
527                 @bvol.signal_connect('clicked') {
528                         position=self.position+@bvol.allocation.to_a
529                         @wvol.move(position[0]+position[2]-40,position[1]+position[3])
530                         @barvol.value=@player.volume*100
531                         @wvol.show
532                         }
533                 #Containers
534                 @boxh=Gtk::HBox.new(false)
535                 #@boxh.border_width=@border_width
536                 @boxh.pack_start(@bexplo, false, false)
537                 @boxh.pack_start(@blist, false, false)
538                 @boxh.pack_start(@vtitle, true, true)
539                 @boxh.pack_start(@bvol, false, false)
540                 
541                 #player
542                 @iprev=Gtk::Image.new(Gtk::Stock::MEDIA_PREVIOUS,Gtk::IconSize::BUTTON)
543                 @bprev= Gtk::Button.new
544                 @bprev.image=@iprev
545                 @bprev.signal_connect('clicked'){prev unless @player.radio?}
546                 @istop=Gtk::Image.new(Gtk::Stock::MEDIA_STOP,Gtk::IconSize::BUTTON)
547                 @bstop= Gtk::Button.new
548                 @bstop.image=@istop
549                 @bstop.signal_connect('clicked'){@player.stop}
550                 @iplay=Gtk::Image.new(Gtk::Stock::MEDIA_PLAY,Gtk::IconSize::BUTTON)
551                 @bplay= Gtk::Button.new
552                 @bplay.image=@iplay
553                 @bplay.signal_connect('clicked'){
554                         if @showlistn==3
555                                 @player.stop
556                                 play_radio
557                         else
558                                 @player.stop if @player.radio?
559                                 play
560                         end
561                         }
562                 @ipause=Gtk::Image.new(Gtk::Stock::MEDIA_PAUSE,Gtk::IconSize::BUTTON)
563                 @bpause=Gtk::Button.new
564                 @bpause.image=@ipause
565                 @bpause.signal_connect('clicked'){@player.pause}
566                 @inext=Gtk::Image.new(Gtk::Stock::MEDIA_NEXT,Gtk::IconSize::BUTTON)
567                 @bnext= Gtk::Button.new
568                 @bnext.image=@inext
569                 @bnext.signal_connect('clicked'){next_s unless @player.radio?}
570                 
571                 #song
572                 @lposition=Gtk::Label.new('--:--')
573                 @barpos=Gtk::HScale.new
574                 @barpos.draw_value=false
575                 @lduration=Gtk::Label.new('--:--')
576                 @barpos.signal_connect('button_press_event'){@seeking=true;false}
577                 @barpos.signal_connect('button_release_event'){@player.position=@barpos.value.to_i;@seeking=false}
579                 @bplayer = Gtk::HBox.new(false)
580                 #@bplayer.border_width=@border_width
581                 @bplayer.pack_start(@bprev, false, false)
582                 @bplayer.pack_start(@bstop, false, false)
583                 @bplayer.pack_start(@bplay, false, false)
584                 @bplayer.pack_start(@bpause, false, false)
585                 @bplayer.pack_start(@bnext, false, false)
586                 @bplayer.pack_start(@lposition, false, false)
587                 @bplayer.pack_start(@barpos, true, true)
588                 @bplayer.pack_start(@lduration, false, false)
589 #*************Quit************************
590                 @bclose= Gtk::Button.new(Gtk::Stock::QUIT)
591                 @bclose.signal_connect('clicked') {quit}
592 #*************Menu******************
593                 ###----Musik menu-------
594                 @play_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_PLAY)
595                 @play_it.signal_connect('activate'){@player.play}
596                 @stop_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_STOP)
597                 @stop_it.signal_connect('activate'){@player.stop}
598                 @prev_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_PREVIOUS)
599                 @prev_it.signal_connect('activate'){prev}
600                 @next_it=Gtk::ImageMenuItem.new(Gtk::Stock::MEDIA_NEXT)
601                 @next_it.signal_connect('activate'){next_s}
602                 @sep=Gtk::SeparatorMenuItem.new
603                 @sep2=Gtk::SeparatorMenuItem.new
604                 @shuffle_it=Gtk::CheckMenuItem.new(_('Shuffle'));
605                 @shuffle_it.active=@pref.player['shuffle']
606                 @shuffle_it.signal_connect("toggled"){@pref.player['shuffle']=!@pref.player['shuffle'];@player.toggle_shuffle}
607                 @repeat_it=Gtk::CheckMenuItem.new(_('Repeat'));#repeat or loopback or????
608                 @repeat_it.active=@pref.player['repeat']
609                 @repeat_it.signal_connect("toggled"){
610                         @pref.player['repeat']=!@pref.player['repeat'];@player.repeat=@pref.player['repeat']
611                 }
612                 @playonstart_it=Gtk::CheckMenuItem.new(_('Play on start'))
613                 @playonstart_it.active=@pref.player['playonstart']
614                 @playonstart_it.signal_connect("toggled"){@pref.player['playonstart']=!@pref.player['playonstart']}
615                 @quit_it=Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
616                 @quit_it.signal_connect('activate'){quit}
617                 
618                 @menu_musiq=Gtk::Menu.new
619                 @menu_musiq.append(@play_it)
620                 @menu_musiq.append(@stop_it)
621                 @menu_musiq.append(@prev_it)
622                 @menu_musiq.append(@next_it)
623                 @menu_musiq.append(@sep)
624                 @menu_musiq.append(@shuffle_it)
625                 @menu_musiq.append(@repeat_it)
626                 @menu_musiq.append(@playonstart_it)
627                 @menu_musiq.append(@sep2)
628                 @menu_musiq.append(@quit_it)
629                 ###----Explorateur menu------
630                 @tree_refresh_it=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
631                 @tree_refresh_it.signal_connect("activate") {@path_explo=@treestore.refresh(@pref.dir,@pref.ext)}
632                 @moddir_it=Gtk::ImageMenuItem.new(Gtk::Stock::PREFERENCES)
633                 @moddir_it.signal_connect("activate") {
634                         dialog=Option.new(self,@pref.dir,@pref.ext,@border_width)
635                         if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
636                                 @pref.dir=dialog.dir
637                                 @pref.ext=dialog.ext
638                                 @path_explo=@treestore.refresh(@pref.dir,@pref.ext)
639                         end  
640                         dialog.destroy
641                 }
642                 @search_it=Gtk::ImageMenuItem.new(Gtk::Stock::FIND)
643                 @search_it.signal_connect("activate") {
644                         @wsearch_explo=Search::Explo.new(@player,@list1,@list2,@border_width) unless Search.explo?
645                         position=self.position+@wtree.allocation.to_a
646                         @wsearch_explo.search(position,@path_explo)
647                 }
648                 
649                 @menu_explo=Gtk::Menu.new
650                 @menu_explo.append(@tree_refresh_it)
651                 @menu_explo.append(@moddir_it)
652                 @menu_explo.append(@search_it)
653                 ###----Playlist menu------
654                 @list_refresh_it=Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH)
655                 @list_refresh_it.signal_connect("activate") {@list1.refresh}
656                 @import_it=Gtk::ImageMenuItem.new(Gtk::Stock::ADD)
657                 @import_it.signal_connect("activate") {@list1.import(self);@player.add}
658                 @export_it=Gtk::ImageMenuItem.new(Gtk::Stock::SAVE)
659                 @export_it.signal_connect("activate") {@list1.export(self)}
660                 @del_it=Gtk::ImageMenuItem.new(Gtk::Stock::CLEAR)
661                 @del_it.signal_connect("activate") {@player.stop;@player.del_all;@list1.del_all}
662                 @search_plit=Gtk::ImageMenuItem.new(Gtk::Stock::FIND)
663                 @search_plit.signal_connect("activate"){
664                         @combolist.active=0
665                         @wsearch_plist=Search::List.new unless Search.plist?
666                         position=self.position+@boxlist.allocation.to_a
667                         @wsearch_plist.search(position,@list1,@listview1)
668                 }
669                 @sep=Gtk::SeparatorMenuItem.new
670                 @list_edit_it=Gtk::ImageMenuItem.new(Gtk::Stock::EDIT)
671                 @list_edit_it.signal_connect("activate") {
672                         @list1_select.select_all
673                         EditTag.new(self,@list1_select,@list1,@border_width)
674                 }
675                 
676                 @menu_list=Gtk::Menu.new
677                 @menu_list.append(@list_refresh_it)
678                 @menu_list.append(@import_it)
679                 @menu_list.append(@export_it)
680                 @menu_list.append(@del_it)
681                 @menu_list.append(@search_plit)
682                 @menu_list.append(@sep)
683                 @menu_list.append(@list_edit_it)
684                 ###----Help menu
685 #Faire un fichier help_lc.rb par langue
686 #Utiliser GetText.locale afin de connaitre lc
687                 @help_it2=Gtk::ImageMenuItem.new(Gtk::Stock::HELP)
688                 @help_it2.signal_connect("activate"){Help.new(self)}
689                 @about_it=Gtk::ImageMenuItem.new(Gtk::Stock::ABOUT)
690                 f=File.open(File.join(Ddir,'COPYING'))
691                 text=''
692                 while line=f.gets
693                         text+=line
694                 end
695                 f.close 
696                 @about_it.signal_connect("activate") {
697                 Gtk::AboutDialog.show(self, {'name'=>'ZiK',
698                 'version'=>Version,
699                 'copyright'=>'Copyright 2007-2008 Vincent Carmona',
700                 'comments'=>_('Audio player'),
701                 'website'=>'http://zik.rubyforge.org/',
702                 'license'=>text,
703                 'authors'=>["Vincent Carmona <vinc-mai@caramail.com>"],
704                 'translator_credits'=>"Français: Vincent Carmona\n",
705                 'logo'=>Gdk::Pixbuf.new(File.join(Pdir,'ZiK3.png'))})
706 #name do not work -> Bug 496689?
707                 }
708                 
709                 @menu_help=Gtk::Menu.new
710                 @menu_help.append(@help_it2)
711                 @menu_help.append(@about_it)
712                 ###----Menu bar------------
713                 @musiq_it=Gtk::MenuItem.new(_('Music'))
714                 @musiq_it.set_submenu(@menu_musiq)
715                 @list_it=Gtk::MenuItem.new(_('Playlist'))
716                 @list_it.set_submenu(@menu_list)
717                 @config_it=Gtk::MenuItem.new(_('Browser'))
718                 @config_it.set_submenu(@menu_explo)
719                 @help_it=Gtk::MenuItem.new(_('Help'))
720                 @help_it.set_submenu(@menu_help)
721                 
722                 @menu_bar=Gtk::MenuBar.new
723                 @menu_bar.append(@musiq_it)
724                 @menu_bar.append(@config_it)
725                 @menu_bar.append(@list_it)
726                 @menu_bar.append(@help_it)
727 #****************Acceleration Keys*********************
728 #connect media key 0xa2(play/pause)
729                 @accel=Gtk::AccelGroup.new
730                 @accel.connect(Gdk::Keyval::GDK_p, nil,Gtk::ACCEL_VISIBLE){
731                         if @player.playing?
732                                 @player.pause
733                         else
734                                 if @player.radio?
735                                         play_radio
736                                 else
737                                         play
738                                 end
739                         end
740                         }
741                 @accel.connect(Gdk::Keyval::GDK_s, nil,Gtk::ACCEL_VISIBLE){@player.stop}
742                 @accel.connect(Gdk::Keyval::GDK_b, nil,Gtk::ACCEL_VISIBLE){prev}
743                 @accel.connect(Gdk::Keyval::GDK_n, nil,Gtk::ACCEL_VISIBLE){next_s}
744                 @accel.connect(Gdk::Keyval::GDK_Down, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){@player.vol_down}
745                 @accel.connect(Gdk::Keyval::GDK_Up, Gdk::Window::CONTROL_MASK,Gtk::ACCEL_VISIBLE){@player.vol_up}
746                 @accel.connect(Gdk::Keyval::GDK_f, Gdk::Window::CONTROL_MASK, Gtk::ACCEL_VISIBLE){
747                         @combolist.active=0
748                         @wsearch_plist=Search::List.new unless Search.plist?
749                         position=self.position+@boxlist.allocation.to_a
750                         @wsearch_plist.search(position,@list1,@listview1)
751                 }
752 #***************Main window********************
753                 ###---Container---
754                 @vbox=Gtk::VBox.new
755                 @vbox.pack_start( @menu_bar, false, false, 0)
756                 @vbox.pack_start(@paned)
757                 @vbox.pack_start(@boxh, false, false)
758                 @vbox.pack_start(@bplayer, false, false)
759                 @vbox.pack_start(@bclose, false, false)
760                 #Pre show the widgets
761                 @vbox.show_all
762                 @wlist2.hide;@mbox.hide;@wradio.hide;@wcd.hide
763                 if !@pref.gui['showexplo']
764                         @paned.child1.hide
765                 end
766                 if !@pref.gui['showlist']
767                         @paned.child2.hide
768                 end
769                 ###---Window-----
770                 super(Gtk::Window::TOPLEVEL)
771                 self.signal_connect("grab-focus"){|widget, event| puts 'grab';@wvol.hide}
772                 self.signal_connect("delete_event") {quit;true}
773                 self.add_accel_group(@accel)
774                 self.set_default_size(500,600)
775                 if  @pref.gui['showlist'] or @pref.gui['explo']
776                         self.resize(@pref.gui['width'],@pref.gui['height'])
777                 else
778                         self.resize(400,100)
779                 end
780                 self.move(@pref.gui['xposition'],@pref.gui['yposition'])
781                 self.title='ZiK'
782                 @icon_Z = Gdk::Pixbuf.new(File.join(Pdir,'ZiK.svg'))
783                 self.icon=(@icon_Z)
784                 self.add(@vbox)
785                 
786                 if @pref.gui['tray']
787                         @tray=SysTray.new(self,@player)
788                 end
789                 play if @pref.player['playonstart']
790         end
793 #************Refresh the datas when playing****************************
794         def play(song=nil)
795                 @player.play(song)
796                 @pref.player['current']=@player.current
797                 current_shuffle=@player.order[@player.current]
798                 unless current_shuffle.nil?
799                         name=@list1.name[current_shuffle]
800                         duration=(@list1.duration[current_shuffle].to_i)
801                         @stitle.set_markup("<b>#{name}</b>")
802                         if duration <= 0
803                                 show_duration=false
804                                 @lduration.text='--:--'
805                         else
806                                 show_duration=true
807                                 @barpos.set_range(0,duration)
808                                 duration_s=(Time.at(duration).strftime("%M:%S"))
809                                 @lduration.text=duration_s
810                         end
811                         @list1.store.each{|model,path,iter|
812                                 if iter[0]==name
813                                         iter[1]=true
814                                 else
815                                         iter[1]=false
816                                 end
817                         }
818                 end
819                 
820                         Gtk.timeout_add(400){
821                                 unless @pref.player['current']==@player.current
822                                         @pref.player['current']=@player.current
823                                         current_shuffle=@player.order[@player.current]
824                                         unless current_shuffle.nil?
825                                                 name=@list1.name[current_shuffle]
826                                                 @stitle.set_markup("<b>#{name}</b>")
827                                                 duration=(@list1.duration[current_shuffle].to_i)
828                                                 if duration <= 0
829                                                         show_duration=false
830                                                         @lduration.text='--:--'
831                                                 else
832                                                         show_duration=true
833                                                         @barpos.set_range(0,duration)
834                                                         duration_s=(Time.at(duration).strftime("%M:%S"))
835                                                         @lduration.text=duration_s
836                                                 end
837                                                 @list1.store.each{|model,path,iter|#In the playlist view, set the current song to bold
838                                                         if iter[0]==name
839                                                                 iter[1]=true
840                                                         else
841                                                                 iter[1]=false
842                                                         end
843                                                 }
844                                         end
845                                 end
846                                 position=@player.position
847                                 unless position.nil?
848                                         unless @seeking
849                                         @barpos.value=position
850                                         end
851                                         if position >= 0
852                                         @lposition.text=Time.at(position).strftime("%M:%S")
853                                         else
854                                                 @lposition.text='--:--'
855                                         end
856                                 end
857                                 @player.playing?
858                                 }
859         end
860         
861         def play_radio #Gérer les erreurs du type "Gst error" -> utiliser array[1..end] 
862                 unless @radio_select.selected.nil?
863                         url=@radio_select.selected[1]
864                         case url
865                         when /^http:\/\/.*\.m3u$/i
866                                 plist=fetch_playlist(url)
867                                 tmp=Tempfile.new('ZiKPlist')
868                                 tmp.puts plist
869                                 tmp.close; tmp.open
870                                 array=read_m3u(tmp)
871                                 tmp.close!
872                                 stream=array
873                         when /^http:\/\/.*\.pls$/i
874                                 plist=fetch_playlist(url)
875                                 tmp=Tempfile.new('ZiKPlist')
876                                 tmp.puts plist
877                                 tmp.close; tmp.open
878                                 array=read_pls(tmp)
879                                 tmp.close!
880                                 stream=array
881                         when /^http:\/\/.*\.asx$/i
882                                 plist=fetch_playlist(url)
883                                 tmp=Tempfile.new('ZiKPlist')
884                                 tmp.puts plist
885                                 tmp.close; tmp.open
886                                 array=read_asx(tmp)
887                                 tmp.close!
888                                 stream=array
889                         else
890                                 stream=[url]
891                         end
892                         radio_name=@radio_select.selected[0]
893                         @stitle.set_markup("<b>#{radio_name}</b>")
894                         @lduration.text='--:--'
895                         @barpos.value=0
896                         i=0;l=stream.length
897                         begin
898                                 @player.play_radio(stream[i])
899                         rescue GstError
900                                 i+=1
901                                 @player.play_radio(stream[i]) if i < l
902                         end
903                 end
904         end
905         
906         def next_s
907                 play unless @player.playing?
908                 @player.next_s
909         end
910         
911         def prev
912                 play unless @player.playing?
913                 @player.prev
914         end
915         
916         def add_radio
917                 entry=Gtk::Entry.new
918                 entry.text=_('Name')
919                 entry2=Gtk::Entry.new
920                 entry2.text=_('Url')
921                 dialog = Gtk::Dialog.new(_("Add a radio"),self,Gtk::Dialog::DESTROY_WITH_PARENT,[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], [Gtk::Stock::APPLY, Gtk::Dialog::RESPONSE_ACCEPT])
922                 dialog.vbox.add(entry)
923                 dialog.vbox.add(entry2)
924                 dialog.show_all
925                 if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
926                         @pref.radio[entry.text]=entry2.text
927                         child=@radiostore.append
928                         child[0]=entry.text;child[1]=entry2.text
929                 end
930                 dialog.destroy
931         end
932         
933         def rm_radio
934                 unless @radio_select.selected.nil?
935                         @pref.radio.delete_at(@radio_select.selected.path.to_str.to_i)
936                         @radiostore.remove(@radio_select.selected)
937                 end
938         end
939         
940         def edit_radio(selection)
941                 unless selection.nil?
942                         entry=Gtk::Entry.new
943                         entry.text=selection[0]
944                         entry2=Gtk::Entry.new
945                         entry2.text=selection[1]
946                         dialog = Gtk::Dialog.new(_("Edit a radio"),self,Gtk::Dialog::DESTROY_WITH_PARENT,[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], [Gtk::Stock::APPLY, Gtk::Dialog::RESPONSE_ACCEPT])
947                         dialog.vbox.add(entry)
948                         dialog.vbox.add(entry2)
949                         dialog.show_all
950                         if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
951                                 @pref.radio.delete(selection[0])
952                                 @pref.radio[entry.text]=entry2.text
953                                 selection[0]=entry.text;selection[1]=entry2.text
954                         end
955                         dialog.destroy
956                 end
957         end
958         
959         def quit
960                  @player.stop
961                  @list1.write
962                  @pref.player['volume']=(@player.volume*100)
963                  pos=self.position
964                  @pref.gui['xposition']=pos[0]
965                  @pref.gui['yposition']=pos[1]
966                  if  @pref.gui['showlist'] or @pref.gui['explo']
967                         s=self.size
968                         @pref.gui['width']=s[0]
969                         @pref.gui['height']=s[1]
970                  end
971                  @pref.gui['paned_position']=@paned.position
972                  @pref.write
973                  Gtk.main_quit
974                  puts "Bye!"
975         end