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 +1 -1
- data/lib/sh_album.rb +20 -0
- data/lib/sh_artist.rb +14 -0
- data/lib/sh_browse.rb +7 -6
- data/lib/sh_cover_art.rb +1 -1
- data/lib/sh_database.rb +132 -16
- data/lib/sh_lyrics.rb +1 -1
- data/lib/sh_player.rb +2 -2
- data/lib/sh_queue.rb +51 -0
- data/lib/sh_song.rb +33 -18
- data/lib/sh_util.rb +1 -1
- data/lib/sh_view.rb +13 -6
- metadata +5 -2
data/Rakefile
CHANGED
data/lib/sh_album.rb
ADDED
@@ -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
|
data/lib/sh_artist.rb
ADDED
data/lib/sh_browse.rb
CHANGED
@@ -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
|
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
|
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
|
data/lib/sh_cover_art.rb
CHANGED
@@ -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})
|
data/lib/sh_database.rb
CHANGED
@@ -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 :
|
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
|
-
|
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
|
-
:
|
29
|
-
:
|
30
|
-
:
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
data/lib/sh_lyrics.rb
CHANGED
data/lib/sh_player.rb
CHANGED
@@ -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)
|
data/lib/sh_queue.rb
ADDED
@@ -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
|
data/lib/sh_song.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
29
|
-
|
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
|
-
|
32
|
-
|
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 =>
|
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
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
78
|
-
|
79
|
-
|
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!("<", "<")
|
95
|
-
ar = artist
|
110
|
+
ar = artist.name
|
96
111
|
ar = "Unknown" if not ar or ar.is_binary_data?
|
97
112
|
ar.gsub!("<", "<")
|
98
|
-
al = album
|
113
|
+
al = album.title
|
99
114
|
al = "Unknown" if not al or al.is_binary_data?
|
100
115
|
al.gsub!("<", "<")
|
101
116
|
return "<b>#{t}</b> by <i>#{ar}</i> from <i>#{al}</i>".gsub("&", "&")
|
data/lib/sh_util.rb
CHANGED
data/lib/sh_view.rb
CHANGED
@@ -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 =
|
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.
|
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.
|
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.
|
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.
|
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-
|
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
|