shroom 0.0.10 → 0.0.11

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.
data/README CHANGED
@@ -1,38 +1,31 @@
1
- Shroom
2
- ======
1
+ == Shroom
3
2
 
4
- Dependencies
5
- ------------
3
+ === Dependencies
6
4
 
7
- 'rake'
8
- 'libwxgtk2.8-0'
9
- 'libgnome2-ruby'
10
- 'libglade2-ruby'
11
- 'libgtkhtml2-ruby'
12
- 'libsqlite3-ruby'
13
- 'ruby-dev'
14
- 'libopenssl-ruby'
15
- 'libmp3lame-dev'
16
- 'libvorbis-dev'
17
- 'build-essential'
5
+ * rake
6
+ * libwxgtk2.8-0
7
+ * libgnome2-ruby
8
+ * libglade2-ruby
9
+ * libsqlite3-ruby
10
+ * ruby-dev
11
+ * libopenssl-ruby
12
+ * libmp3lame-dev
13
+ * libvorbis-dev
14
+ * build-essential
18
15
 
19
- Gem dependencies
20
- ----------------
16
+ === Gem dependencies
21
17
 
22
- ('ruby-mp3info', '>= 0.6.13')
23
- ('MP4Info', '>= 0.3.3')
24
- ('ruby-ogginfo', '>= 0.3.2')
25
- ('flacinfo-rb', '>= 0.4')
26
- ('earworm', '>= 0.0.2')
27
- ('sequel', '>= 3.2.0')
28
- ('wxruby', '>= 2.0.0')
29
- ('rbrainz', '>= 0.5.0')
30
- ('scrobbler', '>= 0.2.3')
31
- ('shared-mime-info', '>= 0.1')
18
+ * ruby-mp3info (>= 0.6.13)
19
+ * MP4Info (>= 0.3.3)
20
+ * ruby-ogginfo (>= 0.3.2)
21
+ * flacinfo-rb (>= 0.4)
22
+ * earworm (>= 0.0.2)
23
+ * sequel (>= 3.2.0)
24
+ * wxruby (>= 2.0.0)
25
+ * rbrainz (>= 0.5.0)
26
+ * scrobbler (>= 0.2.3)
32
27
 
33
- Repository
34
- ----------
35
-
36
- The latest source code should be available at:
37
- http://bitbucket.org/dismal_denizen/shroom/
28
+ === Repository
38
29
 
30
+ The latest source code should be available at
31
+ http://bitbucket.org/dismal_denizen/shroom
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'rake/testtask'
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = 'shroom'
10
- s.version = '0.0.10'
10
+ s.version = '0.0.11'
11
11
  s.has_rdoc = true
12
12
  s.extra_rdoc_files = ['README', 'LICENSE']
13
13
  s.summary = 'Shroom is a music player and organizer'
@@ -25,16 +25,14 @@ spec = Gem::Specification.new do |s|
25
25
  s.add_dependency('wxruby', '>= 2.0.0')
26
26
  s.add_dependency('rbrainz', '>= 0.5.0')
27
27
  s.add_dependency('scrobbler', '>= 0.2.3')
28
- s.add_dependency('shared-mime-info', '>= 0.1')
29
28
  s.requirements << 'rake'
30
29
  s.requirements << 'libwxgtk2.8-0'
31
30
  s.requirements << 'libgnome2-ruby'
32
31
  s.requirements << 'libglade2-ruby'
33
- s.requirements << 'libgtkhtml2-ruby'
34
32
  s.requirements << 'libsqlite3-ruby'
33
+ s.requirements << 'libopenssl-ruby'
35
34
  # Requirements for icanhasaudio
36
35
  s.requirements << 'ruby-dev'
37
- s.requirements << 'libopenssl-ruby'
38
36
  s.requirements << 'libmp3lame-dev'
39
37
  s.requirements << 'libvorbis-dev'
40
38
  s.requirements << 'build-essential'
@@ -51,25 +51,28 @@ module Sh
51
51
  end
52
52
  end
53
53
  action[:stock_image] = Stock::ADD
54
-
54
+
55
55
  action = Actions.new 'Reread tags', :song do |song|
56
56
  browse = Sh::Browse.instance
57
57
  browse.remove_song song if browse
58
- song.read_tags!(true)
59
- $db.save_song song
58
+ path = song.path
59
+ song.delete
60
+ song = Database.add_song path
60
61
  browse.insert_song song if browse
61
62
  end
62
63
  action[:stock_image] = Stock::HARDDISK
63
-
64
- action = Actions.new 'Lookup metadata automatically', :song do |song|
65
- if song.lookup!
66
- browse = Sh::Browse.instance
67
- browse.remove_song song if browse
68
- $db.save_song song
69
- browse.insert_song song if browse
64
+
65
+ if try_require 'earworm' and try_require 'rbrainz'
66
+ action = Actions.new 'Lookup metadata automatically', :song do |song|
67
+ if song.lookup!
68
+ browse = Sh::Browse.instance
69
+ browse.remove_song song if browse
70
+ song.save
71
+ browse.insert_song song if browse
72
+ end
70
73
  end
71
- end
72
- action[:stock_image] = Stock::FIND
74
+ action[:stock_image] = Stock::FIND
75
+ end
73
76
 
74
77
  action = Actions.new 'Add to playlist', :song, :playlist do |song, playlist|
75
78
  playlist << song
@@ -87,17 +90,19 @@ module Sh
87
90
  glade = Global::GLADE['dlg_song']
88
91
  dlg_song = glade['dlg_song']
89
92
  txt_title = glade['txt_title']
90
- txt_title.text = song.title
93
+ txt_title.text = song.title || File.basename(song.path)
94
+ spn_track_num = glade['spn_track_num']
95
+ spn_track_num.value = song.track_num || 0
91
96
 
92
97
  # Artists combo box
93
98
  sto_artists = ListStore.new(String, Artist)
94
99
  cmb_artist = glade['cmb_artist']
95
100
  sel = 0
96
- $db.artists.sort_by{|a| (a.name || '')}.each_with_index do |artist, i|
101
+ Artist.order(:name).each_with_index do |artist, i|
97
102
  iter = sto_artists.append
98
103
  iter[0] = artist.name
99
104
  iter[1] = artist
100
- sel = i if song.artist && artist.db_id == song.artist.db_id
105
+ sel = i if song.artist && artist.id == song.artist.id
101
106
  end
102
107
  cmb_artist.model = sto_artists
103
108
  cmb_artist.active = sel
@@ -106,11 +111,11 @@ module Sh
106
111
  sto_albums = ListStore.new(String, Album)
107
112
  cmb_album = glade['cmb_album']
108
113
  sel = 0
109
- $db.albums.sort_by{|a| (a.title || '')}.each_with_index do |album, i|
114
+ Album.order(:title).each_with_index do |album, i|
110
115
  iter = sto_albums.append
111
116
  iter[0] = album.title
112
117
  iter[1] = album
113
- sel = i if song.album && album.db_id == song.album.db_id
118
+ sel = i if song.album && album.id == song.album.id
114
119
  end
115
120
  cmb_album.model = sto_albums
116
121
  cmb_album.active = sel
@@ -125,12 +130,13 @@ module Sh
125
130
  end
126
131
  btn_ok = glade['btn_ok']
127
132
  ok_handle = btn_ok.signal_connect('clicked') do
128
- browse = Sh::Browse.instance
133
+ browse = Browse.instance
129
134
  song.title = txt_title.text
135
+ song.track_num = spn_track_num.value
130
136
  song.artist = cmb_artist.active_iter[1]
131
137
  song.album = cmb_album.active_iter[1]
132
138
  browse.remove_song song if browse
133
- $db.save_song song
139
+ song.save
134
140
  browse.insert_song song if browse
135
141
  dlg_song.hide
136
142
  end
@@ -15,9 +15,9 @@ module Sh
15
15
  data = iter[0]
16
16
  if data.is_a? Sh::Song
17
17
  if data.title
18
- cell.text = sprintf("%.2d\t%s", data.track_num, data.title)
18
+ cell.text = "%.2d\t%s" % [data.track_num, data.title]
19
19
  else
20
- cell.text = data.path.split('/').last
20
+ cell.text = File.basename(data.path)
21
21
  end
22
22
  else
23
23
  cell.text = data.to_s
@@ -26,13 +26,12 @@ module Sh
26
26
  @tree.append_column col_artist
27
27
 
28
28
  @model = TreeStore.new(Object, Array)
29
- # TODO: use this
30
- # @model.set_default_sort_func do |a, b|
31
- # oa, ob = a[0], b[0]
32
- # oa.to_s <=> ob.to_s
33
- # end
34
- # @model.set_sort_column_id(TreeSortable::DEFAULT_SORT_COLUMN_ID,
35
- # Gtk::SORT_ASCENDING)
29
+ @model.set_default_sort_func do |a, b|
30
+ oa, ob = a[0], b[0]
31
+ oa.to_s <=> ob.to_s
32
+ end
33
+ @model.set_sort_column_id(TreeSortable::DEFAULT_SORT_COLUMN_ID,
34
+ Gtk::SORT_ASCENDING)
36
35
  @tree.model = @model
37
36
 
38
37
  GLib::Timeout.add(1000) do
@@ -100,8 +99,7 @@ module Sh
100
99
  @tree.signal_connect('row_activated') do |widget, path, col|
101
100
  iter = @tree.model.get_iter(path)
102
101
  parent = iter.parent
103
- song = iter[0]
104
- if song.is_a? Sh::Song
102
+ if iter[0].is_a? Song
105
103
  view.stop
106
104
  queue = []
107
105
  while iter.parent == parent
@@ -118,7 +116,7 @@ module Sh
118
116
  view.queue = queue
119
117
  view.queue_pos = prev.size
120
118
  view.play
121
- else
119
+ elsif not iter[1].empty?
122
120
  view.stop
123
121
  view.queue = iter[1].dup
124
122
  view.play
@@ -131,7 +129,11 @@ module Sh
131
129
  end
132
130
 
133
131
  def self.instance
134
- return @@instance
132
+ return @@instance
133
+ end
134
+
135
+ def widget
136
+ return @scroll
135
137
  end
136
138
 
137
139
  def remove_song song
@@ -158,74 +160,102 @@ module Sh
158
160
  end
159
161
 
160
162
  def insert_song song
161
- artist_node = album_node = prev_song_node = nil
162
- @model.each do |model, path, iter|
163
- data = iter[0]
163
+ artist_node = album_node = nil
164
164
 
165
- if data.is_a? Artist
166
- artist_node = iter if data.db_id == song.artist.db_id
167
- elsif artist_node and data.is_a? Album
168
- album_node = iter if iter.parent == artist_node and data.db_id == song.album.db_id
169
- end
165
+ if song.album.special_case?
166
+ artist_node = @artist_nodes[song.artist.id]
167
+ else
168
+ artist_node = @artist_nodes[song.album.artist.id]
169
+ end
170
170
 
171
- if album_node and iter.parent == album_node and data.is_a? Song
172
- if data.track_num < song.track_num
173
- prev_song_node = iter
171
+ if artist_node and artist_node.has_child?
172
+ iter = artist_node.first_child
173
+ loop do
174
+ if iter[0].id == song.album.id
175
+ album_node = iter
176
+ break
177
+ else
178
+ break unless iter.next!
174
179
  end
175
180
  end
176
181
  end
182
+
177
183
  # Artist node
178
184
  unless artist_node
179
- artist_node = @model.append nil
180
- artist_node[0] = song.artist
181
- artist_node[1] = []
185
+ artist_node = create_artist_node song.artist
182
186
  end
183
- artist_node[1] << song
187
+
184
188
  # Album node
185
189
  unless album_node
186
- album_node = @model.append artist_node
187
- album_node[0] = song.album
188
- album_node[1] = []
190
+ album_node = create_album_node artist_node, song.album, []
189
191
  end
192
+
193
+ artist_node[1] << song
194
+ artist_node[1] = artist_node[1].sort_by{|s| s.to_s}
190
195
  album_node[1] << song
196
+ album_node[1] = album_node[1].sort_by{|s| s.to_s}
197
+
191
198
  # Song node
192
- song_node = @model.insert_after(album_node, prev_song_node)
199
+ song_node = @model.append album_node
193
200
  song_node[0] = song
194
201
  song_node[1] = [song]
195
202
  end
196
203
 
197
204
  def fill_model
198
- @model.clear
199
- artist_node = album_node = track_node = nil
200
- $db.songs.sort_by {|a| (a.to_s || '')}.each do |song|
201
- artist = song.artist
202
- if not artist_node or artist_node[0].db_id != artist.db_id
203
- artist_node = @model.append nil
204
- artist_node[0] = artist
205
- # Required for proper handling of multiple artists with on album
206
- album_node = nil
205
+ @artist_nodes = {}
206
+ @model.clear
207
+
208
+ Artist.each do |artist|
209
+ artist_node = create_artist_node artist
210
+
211
+ unknown_album_songs = []
212
+ non_album_songs = []
213
+ artist.songs.each do |song|
214
+ if song.album.id == Album::UNKNOWN
215
+ unknown_album_songs << song
216
+ elsif song.album.id == Album::NON_ALBUM
217
+ non_album_songs << song
218
+ end
207
219
  end
208
- artist_node[1] ||= []
209
- artist_node[1] << song
210
220
 
211
- album = song.album
212
- if not album_node or album_node[0].db_id != album.db_id
213
- album_node = @model.append artist_node
214
- album_node[0] = album
221
+ unless unknown_album_songs.empty?
222
+ create_album_node artist_node, Album[Album::UNKNOWN], unknown_album_songs
223
+ end
224
+ unless non_album_songs.empty?
225
+ create_album_node artist_node, Album[Album::NON_ALBUM], non_album_songs
215
226
  end
216
- album_node[1] ||= []
217
- album_node[1] << song
218
227
 
219
- track_node = @model.append album_node
220
- track_node[0] = song
221
- track_node[1] = [song]
228
+ artist.albums.each do |album|
229
+ create_album_node artist_node, album, album.songs
230
+ end
231
+
232
+ artist_node[1] = artist_node[1].sort_by {|s| s.to_s}
222
233
 
223
234
  Kelp.process_events
224
235
  end
225
236
  end
226
237
 
227
- def widget
228
- return @scroll
238
+ private
239
+ def create_artist_node artist
240
+ artist_node = @model.append nil
241
+ @artist_nodes[artist.id] = artist_node
242
+ artist_node[0] = artist
243
+ artist_node[1] = []
244
+ return artist_node
245
+ end
246
+
247
+ def create_album_node artist_node, album, songs
248
+ songs = songs.sort_by {|s| s.to_s}
249
+ album_node = @model.append artist_node
250
+ album_node[0] = album
251
+ album_node[1] = songs
252
+ songs.each do |song|
253
+ song_node = @model.append album_node
254
+ song_node[0] = song
255
+ song_node[1] = [song]
256
+ artist_node[1] << song
257
+ end
258
+ return album_node
229
259
  end
230
260
  end
231
261
  end
@@ -7,17 +7,15 @@ module Sh
7
7
  if artist and album
8
8
  @lastfm_rest ||= Rest::Get.new("http://ws.audioscrobbler.com/2.0",
9
9
  :api_key => Sh::KEYS[:lastfm], :method => "album.getInfo")
10
- path = "#{$cover_dir}/#{artist.to_md5}_#{album.to_md5}"
10
+ path = "#{Global::PATHS[:cover_dir]}/#{artist.to_md5}_#{album.to_md5}"
11
11
  if File.exists? path and File.size?(path) > 0
12
12
  return path
13
- elsif Ping.pingecho("audioscrobbler.com", 5)
13
+ else
14
14
  doc = REXML::Document.new(@lastfm_rest[:artist => artist, :album => album])
15
15
  img_url = REXML::XPath.first(doc, '//image[@size="extralarge"]').text
16
16
  if img_url
17
17
  open(path, 'w') do |output|
18
- open(img_url) do |input|
19
- output << input.read
20
- end
18
+ output << open(img_url).read
21
19
  end
22
20
  end
23
21
  end
@@ -26,4 +24,3 @@ module Sh
26
24
  end
27
25
  end
28
26
  end
29
-
@@ -5,7 +5,12 @@ module Sh
5
5
  def initialize view
6
6
  @model = ListStore.new(Gdk::Pixbuf, Object)
7
7
  @model.set_default_sort_func do |a, b|
8
- a[COL_ALBUM].title <=> b[COL_ALBUM].title
8
+ album_a, album_b = a[COL_ALBUM], b[COL_ALBUM]
9
+ comparison = album_a.artist.name <=> album_b.artist.name
10
+ if comparison == 0
11
+ comparison = album_a.title <=> album_b.title
12
+ end
13
+ comparison
9
14
  end
10
15
  @model.set_sort_column_id(TreeSortable::DEFAULT_SORT_COLUMN_ID,
11
16
  Gtk::SORT_ASCENDING)
@@ -17,8 +22,7 @@ module Sh
17
22
  album = iter[COL_ALBUM]
18
23
  if album
19
24
  view.stop
20
- songs = $db.songs(:album_id => album.db_id)
21
- view.queue = songs.sort_by {|s| (s.to_s || '')}
25
+ view.queue = album.songs.sort_by {|s| (s.to_s || '')}
22
26
  view.play
23
27
  end
24
28
  end
@@ -35,15 +39,15 @@ module Sh
35
39
 
36
40
  def fill_model
37
41
  @model.clear
38
- $db.albums.each do |album|
42
+ Album.each do |album|
39
43
  begin
40
44
  pixbuf = Gdk::Pixbuf.new(album.image_path).scale(128, 128)
41
45
  iter = @model.append
42
46
  iter[COL_ALBUM] = album
43
47
  iter[COL_PIXBUF] = pixbuf
44
- rescue Exception
48
+ rescue
45
49
  # Insufficient data about album
46
- end if album
50
+ end
47
51
  end
48
52
  end
49
53