shroom 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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.3'
10
+ s.version = '0.0.4'
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'
@@ -0,0 +1,20 @@
1
+ module Sh
2
+ class Album
3
+ attr_writer :artist
4
+ attr_accessor :title, :mbid, :image_path, :info, :date
5
+ attr_accessor :db_id
6
+
7
+ def initialize
8
+ @songs = []
9
+ end
10
+
11
+ def artist
12
+ #@artist = $db.artists(:id => @artist.db_id).first if @artist and @artist.db_id
13
+ return @artist
14
+ end
15
+
16
+ def to_s
17
+ return self.title
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Sh
2
+ class Artist
3
+ attr_accessor :name, :mbid, :image_path, :info
4
+ attr_accessor :db_id
5
+
6
+ def initialize
7
+ @albums = []
8
+ end
9
+
10
+ def to_s
11
+ return self.name
12
+ end
13
+ end
14
+ end
@@ -9,13 +9,14 @@ module Sh
9
9
  col_artist.set_cell_data_func(ren_artist) do |tvc, cell, model, iter|
10
10
  cell.text = ''
11
11
  data = iter[0]
12
- cell.text = data if data.is_a? String
13
12
  if data.is_a? Sh::Song
14
13
  if data.title
15
14
  cell.text = sprintf("%.2d\t%s", data.track_num, data.title)
16
15
  else
17
16
  cell.text = data.path.split('/').last
18
17
  end
18
+ else
19
+ cell.text = data.to_s
19
20
  end
20
21
  end
21
22
  @tree.append_column col_artist
@@ -104,8 +105,8 @@ module Sh
104
105
  def fill_model
105
106
  artist_node = album_node = track_node = nil
106
107
  $db.songs.sort_by {|a| a.to_s}.each do |song|
107
- artist = song.artist || '!Unknown Artist!'
108
- if not artist_node or artist_node[0] != artist
108
+ artist = song.artist
109
+ if not artist_node or artist_node[0].db_id != artist.db_id
109
110
  artist_node = @model.append nil
110
111
  artist_node[0] = artist
111
112
  # Required for proper handling of multiple artists with on album
@@ -113,9 +114,9 @@ module Sh
113
114
  end
114
115
  artist_node[1] ||= []
115
116
  artist_node[1] << song
116
-
117
- album = song.album || '!Unknown Album!'
118
- if not album_node or album_node[0] != album
117
+
118
+ album = song.album
119
+ if not album_node or album_node[0].db_id != album.db_id
119
120
  album_node = @model.append artist_node
120
121
  album_node[0] = album
121
122
  end
@@ -6,7 +6,7 @@ module Sh
6
6
  class CoverArt
7
7
  def CoverArt.get_cover song
8
8
  if $prefs[:cover_art]
9
- artist, album = song.artist, song.album
9
+ artist, album = song.artist.name, song.album.title
10
10
  path = "#{$cover_dir}/#{artist} - #{album}"
11
11
  return path if File.exists? path
12
12
  doc = lastfm("album.getInfo", {:artist => artist, :album => album})
@@ -1,59 +1,150 @@
1
1
  require 'rubygems'
2
2
  require 'sequel'
3
3
  require 'sh_song'
4
+ require 'sh_album'
5
+ require 'sh_artist'
4
6
 
5
7
  module Sh
6
8
  class Database
7
9
  def initialize
8
10
  @db = Sequel.sqlite("#{$config_dir}/songs.db")
9
11
 
12
+ @db.create_table :artists do
13
+ primary_key :id
14
+ String :mbid
15
+ String :name
16
+ String :image_path
17
+ String :info
18
+ end unless @db.table_exists? :artists
19
+
20
+ @db.create_table :albums do
21
+ primary_key :id
22
+ String :mbid
23
+ String :title
24
+ String :image_path
25
+ String :info
26
+ String :date
27
+ end unless @db.table_exists? :albums
28
+
10
29
  @db.create_table :songs do
11
30
  primary_key :id
31
+ String :mbid
12
32
  String :path
13
33
  String :title
14
34
  String :lyrics
15
- String :image
16
- String :year
17
- String :album
18
- String :artist
35
+ String :image_path
19
36
  String :track_num
37
+ foreign_key :album_id, :albums
38
+ foreign_key :artist_id, :artists
20
39
  end unless @db.table_exists? :songs
21
40
  end
22
41
 
23
42
  def save_song song
24
- hash = {
43
+ # Get artist info
44
+ artist = song.artist
45
+ artist_hash = {
46
+ :mbid => artist.mbid,
47
+ :name => artist.name,
48
+ :image_path => artist.image_path,
49
+ :info => artist.info
50
+ }
51
+
52
+ # Insert/update artist in database
53
+ artist_id = nil
54
+ row_artist = @db[:artists][:name => artist.name]
55
+ if row_artist
56
+ artist_hash.each do |k, v|
57
+ if artist_hash[k] != v
58
+ @db[:artists].filter(:name => artist.name).update(k => v)
59
+ end
60
+ end
61
+ artist_id = row_artist[:id]
62
+ else
63
+ artist_id = @db[:artists].insert(artist_hash)
64
+ end
65
+ artist.db_id = artist_id
66
+
67
+ # Get album info
68
+ album = song.album
69
+ album_hash = {
70
+ :mbid => album.mbid,
71
+ :title => album.title,
72
+ :image_path => album.image_path,
73
+ :date => album.date,
74
+ :info => album.info,
75
+ }
76
+
77
+ # Insert/update artist in database
78
+ album_id = nil
79
+ row_album = @db[:albums][:title => album.title]
80
+ if row_album
81
+ album_hash.each do |k, v|
82
+ if album_hash[k] != v
83
+ @db[:albums].filter(:title => album.title).update(k => v)
84
+ end
85
+ end
86
+ album_id = row_album[:id]
87
+ else
88
+ album_id = @db[:albums].insert(album_hash)
89
+ end
90
+ album.db_id = album_id
91
+
92
+ song_hash = {
25
93
  :path => song.path,
94
+ :mbid => song.mbid,
26
95
  :title => song.title,
27
96
  :lyrics => song.lyrics,
28
- :image => song.image,
29
- :year => song.year,
30
- :album => song.album,
31
- :artist => song.artist,
32
- :track_num => song.track_num
97
+ :track_num => song.track_num,
98
+ :album_id => album_id,
99
+ :artist_id => artist_id
33
100
  }
34
101
 
35
102
  song_id = nil
36
103
  row_song = @db[:songs][:path => song.path]
37
104
  if row_song
38
- hash.each do |k, v|
105
+ song_hash.each do |k, v|
39
106
  if row_song[k] != v
40
107
  @db[:songs].filter(:path => song.path).update(k => v)
41
108
  end
42
109
  end
43
110
  song_id = row_song[:id]
44
111
  else
45
- # Create row in db for song
46
- song_id = @db[:songs].insert(hash)
47
- # Retrieve row to return
112
+ song_id = @db[:songs].insert(song_hash)
48
113
  row_song = @db[:songs][:id => song_id]
49
114
  end
115
+ song.db_id = song_id
50
116
 
51
117
  return row_song
52
118
  end
53
119
 
54
- def songs
120
+ def artists(params={})
121
+ artists = []
122
+ params ||= {}
123
+ rows = @db[:artists]
124
+ rows = rows.filter(params) unless params == {}
125
+ rows.each do |hash|
126
+ artists << hash_to_artist(hash)
127
+ end
128
+ return artists
129
+ end
130
+
131
+ def albums(params={})
132
+ albums = []
133
+ params ||= {}
134
+ rows = @db[:albums]
135
+ rows = rows.filter(params) unless params == {}
136
+ rows.each do |hash|
137
+ albums << hash_to_album(hash)
138
+ end
139
+ return albums
140
+ end
141
+
142
+ def songs(params={})
55
143
  songs = []
56
- @db[:songs].each do |hash|
144
+ params ||= {}
145
+ rows = @db[:songs]
146
+ rows = rows.filter(params) unless params == {}
147
+ rows.each do |hash|
57
148
  songs << hash_to_song(hash)
58
149
  end
59
150
  return songs
@@ -80,7 +171,32 @@ module Sh
80
171
  assign = (k.to_s + '=').to_sym
81
172
  song.send assign, v if song.respond_to? assign
82
173
  end
174
+ song.db_id = hash[:id]
175
+ song.album = hash_to_album(@db[:albums][:id => hash[:album_id]])
176
+ song.artist = hash_to_artist(@db[:artists][:id => hash[:artist_id]])
83
177
  return song
84
178
  end
179
+
180
+ def hash_to_album hash
181
+ album = Sh::Album.new
182
+ return album unless hash
183
+ hash.each do |k, v|
184
+ assign = (k.to_s + '=').to_sym
185
+ album.send assign, v if album.respond_to? assign
186
+ end
187
+ album.db_id = hash[:id]
188
+ return album
189
+ end
190
+
191
+ def hash_to_artist hash
192
+ artist = Sh::Artist.new
193
+ return artist unless hash
194
+ hash.each do |k, v|
195
+ assign = (k.to_s + '=').to_sym
196
+ artist.send assign, v if artist.respond_to? assign
197
+ end
198
+ artist.db_id = hash[:id]
199
+ return artist
200
+ end
85
201
  end
86
202
  end
@@ -5,7 +5,7 @@ require 'cgi'
5
5
  module Sh
6
6
  class Lyrics
7
7
  def Lyrics.get_lyrics song
8
- artist, title = song.artist, song.title
8
+ artist, title = song.artist.name, song.title
9
9
  return "" unless artist and title
10
10
  LyricsWiki.get_lyrics(artist, title)
11
11
  end
@@ -90,9 +90,9 @@ module Sh
90
90
  @@scrobble_queue << Scrobbler::Scrobble.new(
91
91
  :session_id => auth.session_id,
92
92
  :submission_url => auth.submission_url,
93
- :artist => song.artist,
93
+ :artist => song.artist.name,
94
94
  :track => song.title,
95
- :album => song.album,
95
+ :album => song.album.title,
96
96
  :time => Time.new,
97
97
  :length => duration,
98
98
  :track_number => song.track_num)
@@ -0,0 +1,51 @@
1
+ module Sh
2
+ class Queue
3
+ def initialize view
4
+ @view = view
5
+ sw = ScrolledWindow.new(nil, nil)
6
+ @widget = sw
7
+ sw.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
8
+ @sto_tabs = ListStore.new(String, Song)
9
+ lst_tabs = TreeView.new @sto_tabs
10
+ renderer = CellRendererText.new
11
+ column = TreeViewColumn.new('Artist',
12
+ renderer,
13
+ 'text' => 0)
14
+ lst_tabs.append_column column
15
+ renderer = CellRendererText.new
16
+ column = TreeViewColumn.new('Songs', renderer)
17
+ column.set_cell_data_func(renderer) do |tvc, cell, model, iter|
18
+ cell.text = ''
19
+ data = iter[1]
20
+ if data.title
21
+ cell.text = sprintf("%.2d\t%s", data.track_num, data.title)
22
+ else
23
+ cell.text = data.path.split('/').last
24
+ end
25
+ end
26
+ lst_tabs.append_column column
27
+ sw.add lst_tabs
28
+
29
+ lst_tabs.signal_connect('row_activated') do |widget, path, col|
30
+ iter = lst_tabs.model.get_iter(path)
31
+ song = iter[1]
32
+ view.stop
33
+ view.queue_pos = path.indices.first
34
+ view.play
35
+ end
36
+ end
37
+
38
+ def update
39
+ @sto_tabs.clear
40
+ @view.queue.each do |song|
41
+ iter = @sto_tabs.append
42
+ iter[0] = song.artist.name
43
+ iter[1] = song
44
+ end if @view.queue
45
+ end
46
+
47
+ def widget
48
+ return @widget
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'sh_tagreader'
3
+ require 'sh_album'
4
+ require 'sh_artist'
3
5
  require 'earworm'
4
6
  require 'rbrainz'
5
7
  include MusicBrainz
@@ -7,17 +9,30 @@ include MusicBrainz
7
9
  module Sh
8
10
  class Song
9
11
  attr_reader :path, :mime, :matches
10
- attr_accessor :title, :artist, :album, :image, :lyrics, :track_num, :year
12
+ attr_writer :album, :artist
13
+ attr_accessor :title, :mbid, :lyrics, :track_num
14
+ attr_accessor :db_id
11
15
 
12
16
  def initialize path
13
17
  @path = File.expand_path path
18
+ self.artist = Sh::Artist.new
19
+ self.album = Sh::Album.new
20
+ end
21
+
22
+ def album
23
+ #@album = $db.albums(:id => @album.db_id).first if @album and @album.db_id
24
+ return @album
25
+ end
26
+
27
+ def artist
28
+ #@artist = $db.artists(:id => @artist.db_id).first if @artist and @artist.db_id
29
+ return @artist
14
30
  end
15
31
 
16
32
  def duration
17
33
  @duration ||= Sh::TagReader.read(path)[:duration]
18
34
  end
19
35
 
20
-
21
36
  def lookup!
22
37
  track = lookup_multiple.first
23
38
  if track
@@ -25,14 +40,14 @@ module Sh
25
40
  track.artist.disambiguation = false
26
41
  # Pull data from response
27
42
  self.title = track.title
28
- self.artist = track.artist.to_s
29
- artistid = track.artist.id.to_mbid.uuid
43
+ artist.name = track.artist.to_s
44
+ artist.mbid = track.artist.id.to_mbid.uuid
30
45
  rel = track.releases.to_a.first
31
- self.album = rel.title
32
- releaseid = rel.id.to_mbid.uuid
46
+ album.title = rel.title
47
+ album.mbid = rel.id.to_mbid.uuid
33
48
  # Determine track number
34
49
  query = Webservice::Query.new
35
- filter = Webservice::TrackFilter.new(:artistid => artistid, :releaseid => releaseid)
50
+ filter = Webservice::TrackFilter.new(:artistid => artist.mbid, :releaseid => album.mbid)
36
51
  tracks = query.get_tracks(filter).entities
37
52
  tracks.to_a.each_with_index do |t, i|
38
53
  self.track_num = i + 1 if t.title == track.title and t.duration == track.duration
@@ -52,12 +67,12 @@ module Sh
52
67
  end
53
68
  puids = info.puid_list
54
69
  self.title = info.title
55
- self.artist = info.artist_name
70
+ self.artist.name = info.artist_name
56
71
  # Return if no matches are found
57
- return if not title or not artist
72
+ return if not title or not artist.name
58
73
  # Get more information from MusicBrainz
59
74
  query = Webservice::Query.new
60
- filter = Webservice::TrackFilter.new(:artist => artist, :title => title, :puid => puids.first)
75
+ filter = Webservice::TrackFilter.new(:artist => artist.name, :title => title, :puid => puids.first)
61
76
  tracks = query.get_tracks(filter).entities
62
77
  @matches = tracks || []
63
78
  end
@@ -67,16 +82,16 @@ module Sh
67
82
  Sh::TagReader.read(path) do |data|
68
83
  if overwrite
69
84
  @title = data[:title]
70
- @artist = data[:artist]
71
- @album = data[:album]
72
- @year = data[:year]
85
+ artist.name = data[:artist]
86
+ album.title = data[:album]
87
+ album.date = data[:year]
73
88
  @track_num = data[:track_num]
74
89
  @duration = data[:duration]
75
90
  else
76
91
  @title ||= data[:title]
77
- @artist ||= data[:artist]
78
- @album ||= data[:album]
79
- @year ||= data[:year]
92
+ artist.name ||= data[:artist]
93
+ album.title ||= data[:album]
94
+ album.date ||= data[:year]
80
95
  @track_num ||= data[:track_num]
81
96
  @duration ||= data[:duration]
82
97
  end
@@ -92,10 +107,10 @@ module Sh
92
107
  t = title
93
108
  t = "Unknown" if not t or t.is_binary_data?
94
109
  t.gsub!("<", "&lt;")
95
- ar = artist
110
+ ar = artist.name
96
111
  ar = "Unknown" if not ar or ar.is_binary_data?
97
112
  ar.gsub!("<", "&lt;")
98
- al = album
113
+ al = album.title
99
114
  al = "Unknown" if not al or al.is_binary_data?
100
115
  al.gsub!("<", "&lt;")
101
116
  return "<b>#{t}</b> by <i>#{ar}</i> from <i>#{al}</i>".gsub("&", "&amp;")
@@ -37,7 +37,7 @@ module Kelp
37
37
  end
38
38
 
39
39
  def message=(msg)
40
- @lbl_message.set_markup(msg)
40
+ @lbl_message.text = msg
41
41
  end
42
42
 
43
43
  def message
@@ -1,4 +1,5 @@
1
1
  require 'sh_browse'
2
+ require 'sh_queue'
2
3
  require 'sh_lyrics'
3
4
  require 'sh_cover_art'
4
5
  require 'libglade2'
@@ -198,7 +199,7 @@ module Sh
198
199
  event_box = EventBox.new
199
200
  event_box.add @img_cover
200
201
  event_box.signal_connect("button-press-event") do |w, event|
201
- Kelp::ImageDialog.new(@pixbuf, @player.song.album).show if @pixbuf and @player
202
+ Kelp::ImageDialog.new(@pixbuf, @player.song.album.title).show if @pixbuf and @player
202
203
  end
203
204
  @img_cover.height_request = 150
204
205
  sidebar.pack_start event_box, false, false, 0
@@ -210,11 +211,13 @@ module Sh
210
211
  scr_lyrics.add @txt_lyrics
211
212
  # Browse area
212
213
  browse = Sh::Browse.new self
214
+ queue = Sh::Queue.new self
213
215
  lst_tabs.selection.signal_connect('changed') do |selection|
214
216
  frm_content.remove frm_content.child if frm_content.child
215
217
  case selection.selected.path.indices[0]
216
218
  when TAB_QUEUE
217
- frm_content.child = Label.new 'Queue'
219
+ frm_content.child = queue.widget
220
+ queue.update
218
221
  when TAB_BROWSE
219
222
  frm_content.child = browse.widget
220
223
  when TAB_LYRICS
@@ -337,25 +340,25 @@ module Sh
337
340
  @note = nil
338
341
  if @rnotify
339
342
  # Prepare notification
340
- msg = "by <i>#{song.artist}</i> from <i>#{song.album}</i>"
343
+ msg = "by <i>#{song.artist.name}</i> from <i>#{song.album.title}</i>"
341
344
  @note = Notify::Notification.new(song.title || 'Unknown track', msg, nil, @status_icon)
342
345
  end
343
346
  # Cover art
344
347
  if $prefs[:cover_art]
345
348
  @pixbuf = nil
346
- (@pixbuf = Gdk::Pixbuf.new(song.image)) rescue Exception
349
+ (@pixbuf = Gdk::Pixbuf.new(song.album.image_path)) rescue Exception
347
350
  if @pixbuf
348
351
  @note.pixbuf_icon = @pixbuf.scale(48, 48) if @rnotify
349
352
  @img_cover.pixbuf = @pixbuf.scale(132, 132)
350
353
  else
351
354
  @img_cover.pixbuf = nil
352
355
  Thread.new do
353
- song.image = Sh::CoverArt.get_cover(song)
356
+ song.album.image_path = Sh::CoverArt.get_cover(song)
354
357
  $db.save_song song
355
358
  # Show cover unless requests have been shuffled
356
359
  if song == @player.song
357
360
  @pixbuf = nil
358
- (@pixbuf = Gdk::Pixbuf.new(song.image)) rescue Exception
361
+ (@pixbuf = Gdk::Pixbuf.new(song.album.image_path)) rescue Exception
359
362
  if @pixbuf
360
363
  if @rnotify
361
364
  @note.close
@@ -391,6 +394,10 @@ module Sh
391
394
  end
392
395
 
393
396
  public
397
+ def queue
398
+ return @queue
399
+ end
400
+
394
401
  def queue=(queue)
395
402
  @queue_pos = 0
396
403
  @queue = queue
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shroom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aiden Nibali
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-23 00:00:00 +10:00
12
+ date: 2009-07-26 00:00:00 +10:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -129,7 +129,10 @@ files:
129
129
  - lib/sh_global.rb
130
130
  - lib/sh_browse.rb
131
131
  - lib/sh_main.rb
132
+ - lib/sh_queue.rb
133
+ - lib/sh_album.rb
132
134
  - lib/sh_song.rb
135
+ - lib/sh_artist.rb
133
136
  - lib/sh_cover_art.rb
134
137
  - lib/sh_tagreader.rb
135
138
  - lib/sh_lyrics.rb