the_little_streamer 0.0.1 → 0.0.2
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.md +1 -1
- data/bin/the_little_streamer +148 -119
- metadata +4 -4
data/README.md
CHANGED
data/bin/the_little_streamer
CHANGED
@@ -13,117 +13,146 @@ abort "Point me to the music!" unless ARGV[0]
|
|
13
13
|
|
14
14
|
#Wrap up in HTML
|
15
15
|
def html body
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
<<-HTML
|
17
|
+
<html>
|
18
|
+
<head>
|
19
|
+
<style type="text/css">
|
20
|
+
#{css}
|
21
|
+
</style>
|
22
|
+
</head>
|
23
|
+
<body>
|
24
|
+
#{body}
|
25
|
+
</body>
|
26
|
+
</html>
|
27
|
+
HTML
|
28
|
+
end
|
29
|
+
|
30
|
+
def css
|
31
|
+
<<-CSS
|
32
|
+
body {
|
33
|
+
font-family: Helvetica,Verdana,Arial,sans-serif;
|
34
|
+
font-size: 13pt;
|
35
|
+
}
|
36
|
+
|
37
|
+
span#title {
|
38
|
+
font-size: 14pt;
|
39
|
+
font-weight: bold;
|
40
|
+
}
|
41
|
+
|
42
|
+
span#artist {
|
43
|
+
font-size: 14pt;
|
44
|
+
font-weight: bold;
|
45
|
+
}
|
46
|
+
|
47
|
+
span#album {
|
48
|
+
font-style: italic;
|
49
|
+
}
|
50
|
+
CSS
|
23
51
|
end
|
24
52
|
|
25
53
|
#Create a link
|
26
54
|
def link root, path, text = path
|
27
|
-
|
55
|
+
full_path = root.split('/').map! {|r| CGI.escape r }.join('/') << "/" << CGI.escape(path)
|
56
|
+
"<a href=\"#{full_path}\">#{text}</a>"
|
28
57
|
end
|
29
58
|
|
30
59
|
#Audio tag
|
31
60
|
def audio path
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
61
|
+
<<-HTML
|
62
|
+
<audio id='player' onEnded='javascript:play_next()' src=#{("/" << CGI.escapeHTML(path)).inspect} autobuffer controls autoplay >
|
63
|
+
You need the power of HTML5!
|
64
|
+
</audio>
|
65
|
+
<script type="text/javascript">
|
66
|
+
document.getElementById('player').volume = 0.3;
|
67
|
+
</script>
|
68
|
+
HTML
|
40
69
|
end
|
41
70
|
|
42
71
|
#Javascript for playlist
|
43
72
|
def playlist songs
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
<<-JAVASCRIPT
|
74
|
+
<script type="text/javascript">
|
75
|
+
var player = document.getElementById('player');
|
76
|
+
var artist = document.getElementById('artist');
|
77
|
+
var album = document.getElementById('album');
|
78
|
+
var title = document.getElementById('title');
|
79
|
+
var playlist = [#{songs.map { |s| song_to_js s }.join "," }]
|
80
|
+
var current_song = 0;
|
81
|
+
|
82
|
+
play_next = function(reverse) {
|
83
|
+
if(reverse && current_song > 0)
|
84
|
+
current_song--;
|
85
|
+
else if(!reverse && current_song < playlist.length)
|
86
|
+
current_song++;
|
87
|
+
else
|
88
|
+
return;
|
89
|
+
|
90
|
+
var song = playlist[current_song];
|
91
|
+
player.src = song.path;
|
92
|
+
artist.innerHTML = song.artist
|
93
|
+
album.innerHTML = song.album
|
94
|
+
title.innerHTML = song.title
|
95
|
+
player.play();
|
96
|
+
}
|
97
|
+
</script>
|
98
|
+
JAVASCRIPT
|
70
99
|
end
|
71
100
|
|
72
101
|
#Javascript for a song
|
73
102
|
def song_to_js song
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
103
|
+
<<-JAVASCRIPT
|
104
|
+
{ artist: #{song.artist.inspect},
|
105
|
+
album: #{song.album.inspect},
|
106
|
+
title: #{song.title.inspect},
|
107
|
+
path: #{(CGI.escapeHTML "/" << song.path).inspect} }
|
108
|
+
JAVASCRIPT
|
80
109
|
end
|
81
110
|
|
82
111
|
#Back/forward links
|
83
112
|
def prev_and_next
|
84
|
-
|
113
|
+
"<a href='javascript:play_next(true)'>Prev</a> <a href='javascript:play_next()'>Next</a>"
|
85
114
|
end
|
86
115
|
|
87
116
|
#HTML for playing all songs by artist
|
88
117
|
def play_artist artist
|
89
|
-
|
118
|
+
songs = []
|
90
119
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
120
|
+
Music[artist].each_value do |album|
|
121
|
+
album.values.sort_by { |s| s.track }.each do |song|
|
122
|
+
songs << song
|
123
|
+
end
|
124
|
+
end
|
96
125
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
126
|
+
html <<-HTML
|
127
|
+
#{song_info songs.first}<br/>
|
128
|
+
#{audio songs.first.path}<br/>
|
129
|
+
#{prev_and_next if songs.length > 1}
|
130
|
+
#{playlist songs}
|
131
|
+
HTML
|
103
132
|
end
|
104
133
|
|
105
134
|
#HTML for playing all songs on an album
|
106
135
|
def play_album artist, album
|
107
|
-
|
136
|
+
songs = Music[artist][album].values.sort_by { |s| s.track }
|
108
137
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
138
|
+
html <<-HTML
|
139
|
+
#{song_info songs.first}<br/>
|
140
|
+
#{audio songs.first.path}<br/>
|
141
|
+
#{prev_and_next if songs.length > 1}
|
142
|
+
#{playlist songs}
|
143
|
+
HTML
|
115
144
|
end
|
116
145
|
|
117
146
|
#HTML for song information header
|
118
147
|
def song_info song
|
119
|
-
|
148
|
+
"<span id='title'>#{song.title}</span> by <span id='artist'>#{song.artist}</span><br/><span id='album'>#{song.album}</span>"
|
120
149
|
end
|
121
150
|
|
122
151
|
#Storing all music information in here
|
123
152
|
Music = Hash.new do |h,k|
|
124
|
-
|
125
|
-
|
126
|
-
|
153
|
+
h[k] = Hash.new do |hash, key|
|
154
|
+
hash[key] = Hash.new
|
155
|
+
end
|
127
156
|
end
|
128
157
|
|
129
158
|
#Song information
|
@@ -140,79 +169,79 @@ set :run, true
|
|
140
169
|
|
141
170
|
#Grab information from all the song files
|
142
171
|
Dir.glob "#{ARGV[0]}/**/*.{mp3,ogg}" do |file|
|
143
|
-
|
144
|
-
|
172
|
+
begin
|
173
|
+
info = TagLib2::File.new(file)
|
145
174
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
175
|
+
artist, album, title, track = info.artist, info.album, info.title, info.track
|
176
|
+
artist ||= "Unknown"
|
177
|
+
album ||= "Unknown"
|
178
|
+
info = nil
|
150
179
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
180
|
+
if title
|
181
|
+
[artist, album, title].each { |i| i.tr!('/', '-') }
|
182
|
+
Music[artist][album][title] = Song.new(artist, album, title, track, Pathname.new(file).relative_path_from(root).to_s)
|
183
|
+
end
|
184
|
+
rescue Exception => e
|
185
|
+
$stderr.puts e if $DEBUG
|
186
|
+
end
|
158
187
|
end
|
159
188
|
|
160
189
|
GC.start #Clean up after TagLib2
|
161
190
|
|
162
191
|
#List artists
|
163
192
|
get '/' do
|
164
|
-
|
165
|
-
|
193
|
+
path = '/artist/'
|
194
|
+
html Music.keys.sort.map { |a| link path, a }.join "<br/>"
|
166
195
|
end
|
167
196
|
|
168
197
|
#List albums by given artist
|
169
198
|
get '/artist/:artist/?' do |artist|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
199
|
+
unless Music[artist].empty?
|
200
|
+
path = "/artist/#{artist}/album/"
|
201
|
+
html Music[artist].keys.sort.map { |a| link path, a }.join("<br/>") << "<br/><br/>" <<
|
202
|
+
link("/artist/#{artist}/", "play", "Play All")
|
203
|
+
else
|
204
|
+
html "Could not find <b>#{artist}</b>."
|
205
|
+
end
|
177
206
|
end
|
178
207
|
|
179
208
|
#Play songs by given artist
|
180
209
|
get '/artist/:artist/play/?' do |artist|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
210
|
+
unless Music[artist].empty?
|
211
|
+
play_artist artist
|
212
|
+
else
|
213
|
+
html "Could not find <b>#{artist}</b>."
|
214
|
+
end
|
186
215
|
end
|
187
216
|
|
188
217
|
#List songs on given album
|
189
218
|
get '/artist/:artist/album/:album/?' do |artist, album|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
219
|
+
unless Music[artist][album].empty?
|
220
|
+
path = "/artist/#{artist}/album/#{album}/song/"
|
221
|
+
html Music[artist][album].values.sort_by { |s| s.track || 0}.map { |s| link path, s.title }.join("<br/>") << "<br/><br/>" <<
|
222
|
+
link("/artist/#{artist}/album/#{album}/", "play", "Play All")
|
223
|
+
else
|
224
|
+
html "Could not find <b>#{album}</b> for <b>#{artist}</b>."
|
225
|
+
end
|
197
226
|
end
|
198
227
|
|
199
228
|
#Play all songs from a given album
|
200
229
|
get '/artist/:artist/album/:album/play/?' do |artist, album|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
230
|
+
if Music[artist][album]
|
231
|
+
play_album artist, album
|
232
|
+
else
|
233
|
+
html "Could not find <b>#{album}</b> by <b>#{artist}</b>."
|
234
|
+
end
|
206
235
|
end
|
207
236
|
|
208
237
|
#Play song!
|
209
238
|
get '/artist/:artist/album/:album/song/:song/?' do |artist, album, title|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
239
|
+
if song = Music[artist][album][title]
|
240
|
+
html <<-HTML
|
241
|
+
#{song_info song}<br/>
|
242
|
+
#{audio song.path}
|
243
|
+
HTML
|
244
|
+
else
|
245
|
+
html "Could not find <b>#{title}</b> on <b>#{album}</b> by <b>#{artist}</b>."
|
246
|
+
end
|
218
247
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: the_little_streamer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Justin Collins
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-04-01 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|