the_little_streamer 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/the_little_streamer +60 -18
- metadata +10 -7
data/bin/the_little_streamer
CHANGED
@@ -11,6 +11,11 @@ require 'pathname'
|
|
11
11
|
#Supply a directory with all the music in it
|
12
12
|
abort "Point me to the music!" unless ARGV[0]
|
13
13
|
|
14
|
+
trap "INT" do
|
15
|
+
$stderr.puts "Exiting..."
|
16
|
+
exit!
|
17
|
+
end
|
18
|
+
|
14
19
|
#Wrap up in HTML
|
15
20
|
def html body
|
16
21
|
<<-HTML
|
@@ -27,7 +32,7 @@ def html body
|
|
27
32
|
<script>
|
28
33
|
if(document.getElementById('artist')) {
|
29
34
|
window.onload = function() {
|
30
|
-
var artist = document.getElementById('artist').
|
35
|
+
var artist = document.getElementById('artist').firstChild.innerText;
|
31
36
|
var title = document.getElementById('title').innerHTML;
|
32
37
|
document.title = title + " by " + artist;
|
33
38
|
}
|
@@ -54,10 +59,28 @@ def css
|
|
54
59
|
font-weight: bold;
|
55
60
|
}
|
56
61
|
|
62
|
+
span#artist a {
|
63
|
+
text-decoration: none;
|
64
|
+
color: black;
|
65
|
+
}
|
66
|
+
|
67
|
+
span#artist a:hover {
|
68
|
+
text-decoration: underline;
|
69
|
+
}
|
70
|
+
|
57
71
|
span#album {
|
58
72
|
font-style: italic;
|
59
73
|
}
|
60
74
|
|
75
|
+
span#album a {
|
76
|
+
text-decoration: none;
|
77
|
+
color: black;
|
78
|
+
}
|
79
|
+
|
80
|
+
span#album a:hover {
|
81
|
+
text-decoration: underline;
|
82
|
+
}
|
83
|
+
|
61
84
|
div#playlist {
|
62
85
|
float: left;
|
63
86
|
margin-top: 15px;
|
@@ -80,10 +103,19 @@ def link root, path, text = path, params = {}
|
|
80
103
|
"<a href=\"#{full_path}?#{params}\">#{text}</a>"
|
81
104
|
end
|
82
105
|
|
106
|
+
#Some navigation
|
107
|
+
def title artist, album = nil
|
108
|
+
if album
|
109
|
+
"<h3>#{link "/", "", "Music"} : #{link "/artist/", artist, artist} : #{album}</h3>"
|
110
|
+
else
|
111
|
+
"<h3>#{link "/", "", "Music"} : #{artist}</h3>"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
83
115
|
#Audio tag
|
84
116
|
def audio path
|
85
117
|
<<-HTML
|
86
|
-
<audio id='player' onEnded='javascript:play_next()' src=#{("/" << CGI.
|
118
|
+
<audio id='player' onEnded='javascript:play_next()' src=#{("/" << CGI.escape(path)).inspect} autobuffer controls autoplay >
|
87
119
|
You need the power of HTML5!
|
88
120
|
</audio>
|
89
121
|
<script type="text/javascript">
|
@@ -138,7 +170,7 @@ def playlist_js songs
|
|
138
170
|
artist.innerHTML = song.artist
|
139
171
|
album.innerHTML = song.album
|
140
172
|
title.innerHTML = song.title
|
141
|
-
document.title = song.title + " by " +
|
173
|
+
document.title = song.title + " by " + artist.firstChild.innerText;
|
142
174
|
player.play();
|
143
175
|
}
|
144
176
|
|
@@ -153,10 +185,10 @@ end
|
|
153
185
|
#Javascript for a song
|
154
186
|
def song_to_js song
|
155
187
|
<<-JAVASCRIPT
|
156
|
-
{ artist: #{song.artist.inspect},
|
157
|
-
album: #{song.album.inspect},
|
188
|
+
{ artist: #{link("/artist", song.artist, song.artist).inspect},
|
189
|
+
album: #{link("/artist/#{song.artist}/album/", song.album, song.album).inspect},
|
158
190
|
title: #{song.title.inspect},
|
159
|
-
path: #{(CGI.escapeHTML "/" << song.path).inspect} }
|
191
|
+
path: #{(CGI.escapeHTML "/" << CGI.escape(song.path)).inspect} }
|
160
192
|
JAVASCRIPT
|
161
193
|
end
|
162
194
|
|
@@ -174,6 +206,7 @@ def player_html songs
|
|
174
206
|
#{prev_and_next if songs.length > 1}
|
175
207
|
#{playlist_js songs}
|
176
208
|
#{playlist_html songs if songs.length > 1}
|
209
|
+
<div style="clear:both">#{link "/", "", "Back to All Music"}</div>
|
177
210
|
</div>
|
178
211
|
HTML
|
179
212
|
end
|
@@ -244,7 +277,7 @@ end
|
|
244
277
|
|
245
278
|
#HTML for song information header
|
246
279
|
def song_info song
|
247
|
-
"<span id='title'>#{song.title}</span> by <span id='artist'>#{song.artist}</span><br/><span id='album'>#{song.album}</span>"
|
280
|
+
"<span id='title'>#{song.title}</span> by <span id='artist'>#{link "/artist/", song.artist}</span><br/><span id='album'>#{link "/artist/#{song.artist}/album", song.album}</span>"
|
248
281
|
end
|
249
282
|
|
250
283
|
#Storing all music information in here
|
@@ -266,14 +299,21 @@ set :public, ARGV[0]
|
|
266
299
|
#Make sure Sinatra sings
|
267
300
|
set :run, true
|
268
301
|
|
302
|
+
$stderr.puts "Scanning music..."
|
303
|
+
|
304
|
+
old_stderr = $stderr.dup
|
305
|
+
|
306
|
+
$stderr.reopen("/dev/null", "w")
|
307
|
+
|
269
308
|
#Grab information from all the song files
|
270
309
|
Dir.glob "#{ARGV[0]}/**/*.{mp3,ogg}", File::FNM_CASEFOLD do |file|
|
271
310
|
begin
|
272
311
|
info = TagLib2::File.new(file)
|
273
312
|
|
274
313
|
artist, album, title, track = info.artist, info.album, info.title, info.track
|
275
|
-
artist
|
276
|
-
album
|
314
|
+
artist = "Unknown" if artist.nil? or artist.empty?
|
315
|
+
album = "Unknown" if album.nil? or album.empty?
|
316
|
+
|
277
317
|
info = nil
|
278
318
|
|
279
319
|
if title
|
@@ -285,17 +325,20 @@ Dir.glob "#{ARGV[0]}/**/*.{mp3,ogg}", File::FNM_CASEFOLD do |file|
|
|
285
325
|
end
|
286
326
|
end
|
287
327
|
|
328
|
+
$stderr = old_stderr
|
329
|
+
|
288
330
|
GC.start #Clean up after TagLib2
|
289
331
|
|
290
332
|
#List artists
|
291
333
|
get '/' do
|
292
334
|
path = '/artist/'
|
293
335
|
html <<-HTML
|
294
|
-
|
295
|
-
Random
|
336
|
+
(Random
|
296
337
|
#{link("/", "all", "10", :limit => 10, :order => :random)}
|
297
338
|
#{link("/", "all", "50", :limit => 50, :order => :random) }
|
298
|
-
#{link("/", "all", "100", :limit => 100, :order => :random) }
|
339
|
+
#{link("/", "all", "100", :limit => 100, :order => :random) })<br/><hr/>
|
340
|
+
|
341
|
+
#{Music.keys.sort.map { |a| link path, a }.join "<br/>"}<br/><br/>
|
299
342
|
HTML
|
300
343
|
end
|
301
344
|
|
@@ -307,7 +350,8 @@ end
|
|
307
350
|
get '/artist/:artist/?' do |artist|
|
308
351
|
unless Music[artist].empty?
|
309
352
|
path = "/artist/#{artist}/album/"
|
310
|
-
html
|
353
|
+
html title(artist) <<
|
354
|
+
Music[artist].keys.sort.map { |a| link path, a }.join("<br/>") << "<br/><br/>" <<
|
311
355
|
link("/artist/#{artist}/", "play", "Play All") << " - " <<
|
312
356
|
link("/artist/#{artist}/", "play", "Randomly", :order => :random)
|
313
357
|
|
@@ -329,7 +373,8 @@ end
|
|
329
373
|
get '/artist/:artist/album/:album/?' do |artist, album|
|
330
374
|
unless Music[artist][album].empty?
|
331
375
|
path = "/artist/#{artist}/album/#{album}/song/"
|
332
|
-
html
|
376
|
+
html title(artist, album) <<
|
377
|
+
Music[artist][album].values.sort_by { |s| s.track || 0}.map { |s| link path, s.title }.join("<br/>") << "<br/><br/>" <<
|
333
378
|
link("/artist/#{artist}/album/#{album}/", "play", "Play All") << " - " <<
|
334
379
|
link("/artist/#{artist}/album/#{album}/", "play", "Randomly", :order => :random)
|
335
380
|
else
|
@@ -349,10 +394,7 @@ end
|
|
349
394
|
#Play song!
|
350
395
|
get '/artist/:artist/album/:album/song/:song/?' do |artist, album, title|
|
351
396
|
if song = Music[artist][album][title]
|
352
|
-
|
353
|
-
#{song_info song}<br/>
|
354
|
-
#{audio song.path}
|
355
|
-
HTML
|
397
|
+
player_html [song]
|
356
398
|
else
|
357
399
|
html "Could not find <b>#{title}</b> on <b>#{album}</b> by <b>#{artist}</b>."
|
358
400
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: the_little_streamer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
+
- 4
|
8
9
|
- 0
|
9
|
-
version: 0.
|
10
|
+
version: 0.4.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Justin Collins
|
@@ -14,8 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
-
default_executable:
|
18
|
+
date: 2012-01-07 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: sinatra
|
@@ -25,6 +25,7 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
+
hash: 15
|
28
29
|
segments:
|
29
30
|
- 1
|
30
31
|
- 0
|
@@ -39,6 +40,7 @@ dependencies:
|
|
39
40
|
requirements:
|
40
41
|
- - ~>
|
41
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 11
|
42
44
|
segments:
|
43
45
|
- 1
|
44
46
|
- 2
|
@@ -56,7 +58,6 @@ extra_rdoc_files: []
|
|
56
58
|
files:
|
57
59
|
- bin/the_little_streamer
|
58
60
|
- README.md
|
59
|
-
has_rdoc: true
|
60
61
|
homepage: http://github.com/presidentbeef/the_little_streamer
|
61
62
|
licenses: []
|
62
63
|
|
@@ -70,6 +71,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
71
|
requirements:
|
71
72
|
- - ">="
|
72
73
|
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
73
75
|
segments:
|
74
76
|
- 0
|
75
77
|
version: "0"
|
@@ -78,13 +80,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
80
|
requirements:
|
79
81
|
- - ">="
|
80
82
|
- !ruby/object:Gem::Version
|
83
|
+
hash: 3
|
81
84
|
segments:
|
82
85
|
- 0
|
83
86
|
version: "0"
|
84
87
|
requirements: []
|
85
88
|
|
86
89
|
rubyforge_project:
|
87
|
-
rubygems_version: 1.
|
90
|
+
rubygems_version: 1.8.10
|
88
91
|
signing_key:
|
89
92
|
specification_version: 3
|
90
93
|
summary: Simple Sinatra application for streaming music.
|