zik 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +222 -0
  3. data/INSTALL +34 -0
  4. data/Makefile.in +199 -0
  5. data/README +53 -0
  6. data/ZiK.desktop +11 -0
  7. data/ZiK.rb +377 -0
  8. data/configure +269 -0
  9. data/dependencies +142 -0
  10. data/doc/COPYING +340 -0
  11. data/doc/ChangeLog +222 -0
  12. data/doc/html/fr/index.html +128 -0
  13. data/doc/html/index.html +126 -0
  14. data/doc/html/pix/ZiK3.png +0 -0
  15. data/doc/html/pix/capture.png +0 -0
  16. data/doc/html/pix/capture_cd.png +0 -0
  17. data/doc/html/pix/capture_compact.png +0 -0
  18. data/doc/html/pix/capture_radio.png +0 -0
  19. data/doc/html/pix/icon.png +0 -0
  20. data/doc/html/pix/logo.png +0 -0
  21. data/doc/html/styles/main.css +47 -0
  22. data/doc/man/manpage.1 +43 -0
  23. data/gui/assistant.rb +133 -0
  24. data/gui/cdgui.rb +54 -0
  25. data/gui/common.rb +56 -0
  26. data/gui/config.rb +120 -0
  27. data/gui/edit.rb +413 -0
  28. data/gui/error.rb +124 -0
  29. data/gui/gui.rb +1383 -0
  30. data/gui/mod.rb +239 -0
  31. data/gui/preference.rb +496 -0
  32. data/gui/progress.rb +50 -0
  33. data/gui/radiogui.rb +404 -0
  34. data/gui/search.rb +249 -0
  35. data/gui/socket.rb +107 -0
  36. data/mod/brainz.rb +76 -0
  37. data/mod/brainz/dialogs.rb +132 -0
  38. data/mod/brainz/functions.rb +55 -0
  39. data/mod/brainz/ofa.rb +76 -0
  40. data/mod/brainz/song.rb +139 -0
  41. data/mod/brainz/widget.rb +34 -0
  42. data/mod/cover.rb +90 -0
  43. data/mod/cover/application-x-cd-image.svg +666 -0
  44. data/mod/cover/config.rb +79 -0
  45. data/mod/cover/configwidget.rb +35 -0
  46. data/mod/cover/widget.rb +147 -0
  47. data/mod/hotkeys.rb +137 -0
  48. data/mod/hotkeys/config.rb +84 -0
  49. data/mod/hotkeys/configwidget.rb +93 -0
  50. data/mod/interact.rb +131 -0
  51. data/mod/interact/configwidget.rb +107 -0
  52. data/mod/interact/interaction.rb +79 -0
  53. data/mod/notify.rb +128 -0
  54. data/mod/notify/config.rb +96 -0
  55. data/mod/notify/configwidget.rb +76 -0
  56. data/mod/notify/window.rb +56 -0
  57. data/mod/trayicon.rb +83 -0
  58. data/mod/trayicon/config.rb +79 -0
  59. data/mod/trayicon/configwidget.rb +35 -0
  60. data/mod/trayicon/icon.rb +99 -0
  61. data/pix/ZiK.svg +78 -0
  62. data/pix/ZiK3.png +0 -0
  63. data/pix/assistant/capture.png +0 -0
  64. data/pix/gtk-directory.svg +287 -0
  65. data/pix/media-cdrom.svg +292 -0
  66. data/pix/network-wireless.svg +429 -0
  67. data/pix/player_play.svg +286 -0
  68. data/pix/sound.svg +244 -0
  69. data/pix/sound_directory.svg +464 -0
  70. data/player/cdplayer.rb +108 -0
  71. data/player/player.rb +132 -0
  72. data/player/radioplayer.rb +124 -0
  73. data/playlist/cdlist.rb +140 -0
  74. data/playlist/common.rb +343 -0
  75. data/playlist/editlist.rb +50 -0
  76. data/playlist/export.rb +108 -0
  77. data/playlist/playlist.rb +143 -0
  78. data/playlist/radiolist.rb +148 -0
  79. data/playlist/song.rb +122 -0
  80. data/po/ZiK.pot +622 -0
  81. data/po/fr/ZiK.po +658 -0
  82. data/zik +2 -0
  83. metadata +265 -0
  84. metadata.gz.sig +0 -0
@@ -0,0 +1,343 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright 2007-2011 Vincent Carmona
4
+ vinc4mai@gmail.com
5
+
6
+ This file is part of ZiK.
7
+
8
+ ZiK is free software; you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation; either version 2 of the License, or
11
+ (at your option) any later version.
12
+
13
+ ZiK is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with ZiK; if not, write to the Free Software
20
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ =end
22
+
23
+ module ListBase
24
+ #Commun methods for PlayList and EditList.
25
+ #Small differences on a method can be hanble with editlist? and playlist? function.
26
+
27
+ def editlist?
28
+ !self.playlist?
29
+ end
30
+
31
+ def empty?
32
+ @songs.empty?
33
+ end
34
+
35
+ def clear
36
+ @songs.clear
37
+ if self.playlist?
38
+ @current=0
39
+ @n=0
40
+ end
41
+ end
42
+
43
+ def add(file, extension='wav,flac,ogg,mp3,wma,xspf,m3u,pls')
44
+ ErrorInfo.new("Add #{file} to playlist.")
45
+ unless file =~ /^\//#absolute path
46
+ file=File.join(Dir.pwd,file)
47
+ end
48
+ if File.exist?(file)
49
+ ###########################Use mahoro?
50
+ case
51
+ when File.directory?(file)
52
+ add_directory(file, extension)
53
+ when file=~/.*\.xspf$/i
54
+ add_xspf(file)
55
+ when file=~/.*\.m3u$/i
56
+ add_m3u(file)
57
+ when file=~/.*\.pls$/i
58
+ add_pls(file)
59
+ else
60
+ add_file(file)
61
+ end
62
+ if self.playlist?
63
+ @order=@order[0..@n].concat(@order[@n+1...@order.length].sort_by{rand}) unless @order.empty?
64
+ end
65
+ else
66
+ ErrorError.new("#{file} not found.")
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def add_file(file, tag=nil, reraise=false)
73
+ begin
74
+ @songs.push(Song.new(file, @format, tag))
75
+ @order.push(@songs.length-1) if self.playlist?
76
+ rescue BadPath=>e
77
+ ErrorError.new("#{file} not found.")
78
+ raise e if reraise
79
+ end
80
+ end
81
+
82
+ def add_directory(file, extension)
83
+ ext=extension.gsub(',','|'); ext.chop! if ext=~/\|$/; rext=Regexp.new('.*\.('+ext+')', Regexp::IGNORECASE)
84
+ if @sort_by_track
85
+ files=Dir.glob(File.join(file.gsub(/(?=[{\[\]}*])/, '\\'), '*'), File::FNM_CASEFOLD).sort!
86
+ temp=[]
87
+ files.each{|f|
88
+ case
89
+ when File.directory?(f)
90
+ add_directory(f, extension)
91
+ when f=~rext
92
+ case
93
+ when f=~/.*\.m3u$/i
94
+ add_m3u(f)
95
+ when f=~/.*\.pls$/i
96
+ add_pls(f)
97
+ else
98
+ begin
99
+ temp.push(Song.new(f, @format))
100
+ rescue BadPath
101
+ ErrorError.new("#{f} not found.")
102
+ end
103
+ end
104
+ end
105
+ }
106
+ temp.sort_by{|s| s.track}.each{|s|
107
+ @order.push(@songs.length) if self.playlist?
108
+ @songs.push(s)
109
+ }
110
+ else
111
+ files=[]
112
+ Find.find(file){|f| files.push(f) if f=~rext}
113
+ files.sort!
114
+ files.each{|f| add_file(f)}
115
+ end
116
+ end
117
+
118
+ def add_xspf(file)
119
+ #Only support file:// protocol for uris
120
+ begin
121
+ dir=File.dirname(file)
122
+ f=File.new(file,'r')
123
+ base=[]
124
+ doc=REXML::Document.new(f)
125
+ base.push(doc.elements["/playlist"].attributes["xml:base"])
126
+ base.push(doc.elements["/playlist/trackList"].attributes["xml:base"])
127
+ list=doc.elements["/playlist/trackList"]
128
+ list.each_element("track"){|t|
129
+ base.push(t.attributes["xml:base"])
130
+ location=t.elements["location"]
131
+ begin
132
+ if location.nil?
133
+ base.pop
134
+ else
135
+ base.push(location.attributes["xml:base"])
136
+ n=0
137
+ base.each_with_index{|el, i|
138
+ begin
139
+ GLib.filename_from_uri(el)
140
+ n=i
141
+ rescue
142
+ #dummy
143
+ end
144
+ }
145
+ uri=base[n..-1].join('')+location.text
146
+ begin
147
+ path=GLib.filename_from_uri(uri)[0]
148
+ rescue
149
+ #GLib.filename_from_uri crash if uri is a relative path
150
+ path=GLib.filename_from_uri(File.join(GLib.filename_to_uri(dir), uri))[0]
151
+ end
152
+ add_file(path, nil, true)
153
+ 2.times{base.pop}
154
+ end
155
+ rescue BadPath
156
+ base.pop
157
+ location=location.next_element
158
+ retry
159
+ end
160
+ }
161
+ ensure
162
+ f.close if f
163
+ end
164
+ end
165
+
166
+ def add_m3u(file)
167
+ begin
168
+ dir=Pathname.new(file).dirname
169
+ f=File.open(file,'r')
170
+ while line=f.gets
171
+ unless line.nil? or line =~ /^\#/ #line begin with #
172
+ line.chomp!
173
+ path=Pathname.new(line)
174
+ path.relative? ? p=dir+path : p=path
175
+ add_file(p.to_s)
176
+ end
177
+ end
178
+ ensure
179
+ f.close if f
180
+ end
181
+ end
182
+
183
+ def add_pls(file)
184
+ begin
185
+ dir=Pathname.new(file).dirname
186
+ path=[]#Array to store the path of all audio files
187
+ f=File.open(file,'r')
188
+ line=f.gets
189
+ while line.nil? #Skip blank lines
190
+ line=file.gets
191
+ end
192
+ if line =~ /^\[/ #formated playlist
193
+ while line=file.gets
194
+ if line =~ /^file[0-9]*\=/i #Search for the path file (ignore case)
195
+ line.chomp!
196
+ path.push(line.split('=')[1])
197
+ end
198
+ end
199
+ else
200
+ path.push(line.chomp!) unless line.nil?
201
+ while line=file.gets
202
+ path.push(line.chomp!) unless line.nil? or line.empty?
203
+ end
204
+ end
205
+ path.each{|p|
206
+ pn=Pathname.new(p)
207
+ pn.relative? ? pa=dir+pn : pa=pn
208
+ add_file(pa.to_s)
209
+ }
210
+ ensure
211
+ f.close if f
212
+ end
213
+ end
214
+
215
+ public
216
+
217
+ def save_xspf(file, relative=false)
218
+ begin
219
+ dir=Pathname.new(file).dirname
220
+ f=File.open(file,'w')
221
+ doc=REXML::Document.new
222
+ doc << REXML::XMLDecl.new(1,"UTF-8")
223
+ doc.add_element("playlist", {"version"=>"1", "xmlns"=>"http://xspf.org/ns/0/"})
224
+ doc.root.add_element("creator").text="ZiK #{Version}"
225
+ doc.root.add_element("info").text="http://zik.rubyforge.org/"
226
+ list=doc.root.add_element("trackList")
227
+ @songs.each{|song|
228
+ t=REXML::Element.new("track")
229
+ if relative
230
+ uri=Pathname.new(GLib.filename_to_uri(song.path)[7..-1]).relative_path_from(Pathname.new(GLib.filename_to_uri(dir)[7..-1])).to_s
231
+ else
232
+ uri=GLib.filename_to_uri(song.path)
233
+ end
234
+ t.add_element("location").text=uri
235
+ t.add_element("title").text=song.title unless song.title.empty?
236
+ t.add_element("creator").text=song.artist unless song.artist.empty?
237
+ t.add_element("album").text=song.album unless song.album.empty?
238
+ t.add_element("trackNum").text=song.track if song.track>0
239
+ t.add_element("duration").text=song.duration*1000 if song.duration>0
240
+ list.add_element(t)
241
+ }
242
+ doc.write(f, 2, true)
243
+ ErrorInfo.new("#{file} saved.")
244
+ rescue
245
+ ErrorError.new(_("Unable to write #{file}."), true)
246
+ ensure
247
+ f.close if f
248
+ end
249
+ end
250
+
251
+ def save_m3u(file, relative=false)
252
+ begin
253
+ dir=Pathname.new(file).dirname
254
+ f=File.open(file, 'w')
255
+ f.puts '#EXTM3U'
256
+ @songs.each{|song|
257
+ f.puts '#EXTINF:'+song.duration.to_s+','+song.name
258
+ if relative
259
+ f.puts Pathname.new(song.path).relative_path_from(dir)
260
+ else
261
+ f.puts song.path
262
+ end
263
+ }
264
+ ErrorInfo.new("#{file} saved.")
265
+ rescue
266
+ ErrorError.new(_("Unable to write #{file}."), true)
267
+ ensure
268
+ f.close if file
269
+ end
270
+ end
271
+
272
+ end
273
+
274
+ module ListPlay
275
+ #Commun methods for PlayList and Cd::List.
276
+ def previous_song
277
+ if @n > 0
278
+ @n-=1
279
+ if @shuffle
280
+ @current=@order[@n]
281
+ else
282
+ @current=@n
283
+ end
284
+ true
285
+ else
286
+ if @repeat
287
+ @order=@order.sort_by{rand}
288
+ @n=@songs.length-1
289
+ @current=@n
290
+ true
291
+ else
292
+ false
293
+ end
294
+ end
295
+ end
296
+
297
+ def next_song
298
+ if @n < @songs.length-1
299
+ @n+=1
300
+ if @shuffle
301
+ @current=@order[@n]
302
+ else
303
+ @current=@n
304
+ end
305
+ true
306
+ else
307
+ if @repeat
308
+ @order=@order.sort_by{rand}
309
+ @n=0
310
+ @current=@n
311
+ true
312
+ else
313
+ false
314
+ end
315
+ end
316
+ end
317
+
318
+ def current=(n)
319
+ if @shuffle
320
+ @n=@order.index(n)
321
+ @current=n
322
+ else
323
+ @n=n
324
+ @current=@n
325
+ end
326
+ end
327
+
328
+ def repeat=(status)
329
+ @repeat=status
330
+ end
331
+
332
+ def shuffle=(status)
333
+ unless @shuffle==status
334
+ if @shuffle
335
+ @n=@current
336
+ else
337
+ @order=@order.sort_by{rand}
338
+ @n=@order.index(@current)
339
+ end
340
+ @shuffle=!@shuffle
341
+ end
342
+ end
343
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright 2007-2011 Vincent Carmona
4
+ vinc4mai@gmail.com
5
+
6
+ This file is part of ZiK.
7
+
8
+ ZiK is free software; you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation; either version 2 of the License, or
11
+ (at your option) any later version.
12
+
13
+ ZiK is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with ZiK; if not, write to the Free Software
20
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ =end
22
+
23
+ class Editlist
24
+ include ListBase
25
+
26
+ attr_reader :songs
27
+
28
+ def initialize(songs, format)
29
+ @songs=[]
30
+ @songs.concat(songs)
31
+ @format=format
32
+ end
33
+
34
+ def playlist?
35
+ false
36
+ end
37
+
38
+ def merge(list, position)
39
+ if position>=list.songs.length
40
+ @songs=list.songs+@songs
41
+ else
42
+ if position==0
43
+ @songs.concat(list.songs)
44
+ else
45
+ @songs=list.songs[0...position]+@songs+list.songs[position..-1]
46
+ end
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,108 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright 2007-2011 Vincent Carmona
4
+ vinc4mai@gmail.com
5
+
6
+ This file is part of ZiK.
7
+
8
+ ZiK is free software; you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation; either version 2 of the License, or
11
+ (at your option) any later version.
12
+
13
+ ZiK is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with ZiK; if not, write to the Free Software
20
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ =end
22
+
23
+ require 'ftools'
24
+
25
+ class ExportSong
26
+ attr_reader :old_path, :path, :duration, :name, :bitrate, :samplerate, :channels, :type,
27
+ :title, :artist, :album, :track, :genre
28
+
29
+ def initialize(song, dir, config_dir)
30
+ @type=song.type
31
+ @old_path=song.path
32
+ @path=resolve_path(dir, config_dir)
33
+ @name=song.name
34
+ @title=song.title; @artist=song.artist; @album=song.album; @track=song.track; @genre=song.genre
35
+ @duration=song.duration; @bitrate=song.bitrate; @samplerate=song.samplerate; @channels=song.channels
36
+ end
37
+
38
+ private
39
+
40
+ def resolve_path(dir, config_dir)
41
+ tmp=nil
42
+ #Use a tree under dir directory...
43
+ config_dir.split(',').each{|cdir|
44
+ l=cdir.length
45
+ tmp=@old_path[l..-1] if cdir==old_path[0...l]
46
+ break if tmp
47
+ } if config_dir
48
+ #...or directly under dir directory.
49
+ tmp||=File.basename(@old_path)
50
+ File.join(dir, tmp)
51
+ end
52
+ end
53
+
54
+ class ExportList
55
+ include ListBase
56
+
57
+ def initialize(songs, file, config_dir=nil)
58
+ @file=file; @songs=[]
59
+ dir=File.dirname(@file)
60
+ songs.each{|song| @songs.push(ExportSong.new(song, dir, config_dir))}
61
+ @nb=@songs.length
62
+ end
63
+
64
+ def nb
65
+ @nb
66
+ end
67
+
68
+ def write_plalist
69
+ case @file
70
+ when /.*\.xspf$/i
71
+ save_xspf(@file, true)
72
+ when /.*\.m3u$/i
73
+ save_m3u(@file, true)
74
+ else
75
+ save_m3u(@file+'.m3u', true)
76
+ end
77
+ end
78
+
79
+ def export(queue)
80
+ @thread=Thread.new{
81
+ Thread.current[:abort]=false
82
+ estock=ErrorsStock.new
83
+ @songs.each_with_index{|song, i|
84
+ break if Thread.current[:abort]
85
+ begin
86
+ if File.exist?(song.path)
87
+ estock.add(ErrorWARNING, _("#{song.path} allready exists."))
88
+ else
89
+ dir=File.dirname(song.path)
90
+ File.makedirs(dir) unless File.exist?(dir)
91
+ File.copy(song.old_path, song.path)
92
+ end
93
+ rescue Errno::ENOENT#Original file (song.old) was removed
94
+ estock.add(ErrorERROR, _("Cannot access #{song.old_path}"))
95
+ rescue => e
96
+ estock.add(ErrorERROR, e.to_s)
97
+ ensure
98
+ queue.push(i)
99
+ end
100
+ }
101
+ queue.push(estock)
102
+ }
103
+ end
104
+
105
+ def abort_export
106
+ @thread[:abort]=true
107
+ end
108
+ end