zik 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
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