the_little_streamer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.md +25 -0
  2. data/bin/the_little_streamer +218 -0
  3. metadata +97 -0
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # The Little Streamer
2
+
3
+ Extremely simple music streamer using Sinatra.
4
+
5
+ ## Install
6
+
7
+ gem install the_little_streamer
8
+
9
+ ## Use
10
+
11
+ the_little_streamer /path/to/music
12
+
13
+ Browse to http://localhost:4567
14
+
15
+ ## Dependencies
16
+
17
+ * [Sinatra](http://www.sinatrarb.com/)
18
+ * [ruby-taglib2](https://github.com/rumblehq/ruby-taglib2)
19
+ * A browser that supports HTML5, like [Chrome](http://www.google.com/chrome/)
20
+
21
+ You may also want to use [Mongrel](https://github.com/fauna/mongrel) instead of WEBrick, as it will be way faster. Just install it and Sinatra will prefer it over WEBrick.
22
+
23
+ ## License
24
+
25
+ [MIT](http://www.opensource.org/licenses/mit-license.php)
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env ruby
2
+ #This is a simple Sinatra application to play mp3/ogg files through a browser
3
+ #using the HTML5 audio tag
4
+
5
+ require 'rubygems'
6
+ require 'taglib2'
7
+ require 'sinatra'
8
+ require 'cgi'
9
+ require 'pathname'
10
+
11
+ #Supply a directory with all the music in it
12
+ abort "Point me to the music!" unless ARGV[0]
13
+
14
+ #Wrap up in HTML
15
+ def html body
16
+ <<-HTML
17
+ <html>
18
+ <body>
19
+ #{body}
20
+ </body>
21
+ </html>
22
+ HTML
23
+ end
24
+
25
+ #Create a link
26
+ def link root, path, text = path
27
+ "<a href='#{root}#{CGI.escape path}'>#{text}</a>"
28
+ end
29
+
30
+ #Audio tag
31
+ def audio path
32
+ <<-HTML
33
+ <audio id='player' onEnded='javascript:play_next()' src=#{("/" << CGI.escapeHTML(path)).inspect} autobuffer controls autoplay >
34
+ You need the power of HTML5!
35
+ </audio>
36
+ <script type="text/javascript">
37
+ document.getElementById('player').volume = 0.3;
38
+ </script>
39
+ HTML
40
+ end
41
+
42
+ #Javascript for playlist
43
+ def playlist songs
44
+ <<-JAVASCRIPT
45
+ <script type="text/javascript">
46
+ var player = document.getElementById('player');
47
+ var artist = document.getElementById('artist');
48
+ var album = document.getElementById('album');
49
+ var title = document.getElementById('song_title');
50
+ var playlist = [#{songs.map { |s| song_to_js s }.join "," }]
51
+ var current_song = 0;
52
+
53
+ play_next = function(reverse) {
54
+ if(reverse && current_song > 0)
55
+ current_song--;
56
+ else if(!reverse && current_song < playlist.length)
57
+ current_song++;
58
+ else
59
+ return;
60
+
61
+ var song = playlist[current_song];
62
+ player.src = song.path;
63
+ artist.innerHTML = song.artist
64
+ album.innerHTML = song.album
65
+ title.innerHTML = song.title
66
+ player.play();
67
+ }
68
+ </script>
69
+ JAVASCRIPT
70
+ end
71
+
72
+ #Javascript for a song
73
+ def song_to_js song
74
+ <<-JAVASCRIPT
75
+ { artist: #{song.artist.inspect},
76
+ album: #{song.album.inspect},
77
+ title: #{song.title.inspect},
78
+ path: #{(CGI.escapeHTML "/" << song.path).inspect} }
79
+ JAVASCRIPT
80
+ end
81
+
82
+ #Back/forward links
83
+ def prev_and_next
84
+ "<a href='javascript:play_next(true)'>Prev</a>&nbsp;&nbsp;&nbsp;<a href='javascript:play_next()'>Next</a>"
85
+ end
86
+
87
+ #HTML for playing all songs by artist
88
+ def play_artist artist
89
+ songs = []
90
+
91
+ Music[artist].each_value do |album|
92
+ album.values.sort_by { |s| s.track }.each do |song|
93
+ songs << song
94
+ end
95
+ end
96
+
97
+ html <<-HTML
98
+ #{song_info songs.first}<br/>
99
+ #{audio songs.first.path}<br/>
100
+ #{prev_and_next}
101
+ #{playlist songs}
102
+ HTML
103
+ end
104
+
105
+ #HTML for playing all songs on an album
106
+ def play_album artist, album
107
+ songs = Music[artist][album].values.sort_by { |s| s.track }
108
+
109
+ html <<-HTML
110
+ #{song_info songs.first}<br/>
111
+ #{audio songs.first.path}<br/>
112
+ #{prev_and_next}
113
+ #{playlist songs}
114
+ HTML
115
+ end
116
+
117
+ #HTML for song information header
118
+ def song_info song
119
+ "\"<span id='song_title'>#{song.title}</span>\" by <span id='artist'>#{song.artist}</span> (<span id='album'>#{song.album}</span>)"
120
+ end
121
+
122
+ #Storing all music information in here
123
+ Music = Hash.new do |h,k|
124
+ h[k] = Hash.new do |hash, key|
125
+ hash[key] = Hash.new
126
+ end
127
+ end
128
+
129
+ #Song information
130
+ Song = Struct.new :artist, :album, :title, :track, :path
131
+
132
+ #Used to figure out path to music files
133
+ root = Pathname.new ARGV[0]
134
+
135
+ #Make song files public
136
+ set :public, ARGV[0]
137
+
138
+ #Make sure Sinatra sings
139
+ set :run, true
140
+
141
+ #Grab information from all the song files
142
+ Dir.glob "#{ARGV[0]}/**/*.{mp3,ogg}" do |file|
143
+ begin
144
+ info = TagLib2::File.new(file)
145
+
146
+ artist, album, title, track = info.artist, info.album, info.title, info.track
147
+ artist ||= "Unknown"
148
+ album ||= "Unknown"
149
+ info = nil
150
+
151
+ if title
152
+ [artist, album, title].each { |i| i.tr!('/', '-') }
153
+ Music[artist][album][title] = Song.new(artist, album, title, track, Pathname.new(file).relative_path_from(root).to_s)
154
+ end
155
+ rescue Exception => e
156
+ $stderr.puts e if $DEBUG
157
+ end
158
+ end
159
+
160
+ GC.start #Clean up after TagLib2
161
+
162
+ #List artists
163
+ get '/' do
164
+ path = '/artist/'
165
+ html Music.keys.sort.map { |a| link path, a }.join "<br/>"
166
+ end
167
+
168
+ #List albums by given artist
169
+ get '/artist/:artist/?' do |artist|
170
+ unless Music[artist].empty?
171
+ path = "/artist/#{artist}/album/"
172
+ html Music[artist].keys.sort.map { |a| link path, a }.join("<br/>") << "<br/><br/>" <<
173
+ link("/artist/#{artist}/", "play", "Play All")
174
+ else
175
+ html "Could not find <b>#{artist}</b>."
176
+ end
177
+ end
178
+
179
+ #Play songs by given artist
180
+ get '/artist/:artist/play/?' do |artist|
181
+ unless Music[artist].empty?
182
+ play_artist artist
183
+ else
184
+ html "Could not find <b>#{artist}</b>."
185
+ end
186
+ end
187
+
188
+ #List songs on given album
189
+ get '/artist/:artist/album/:album/?' do |artist, album|
190
+ unless Music[artist][album].empty?
191
+ path = "/artist/#{artist}/album/#{album}/song/"
192
+ html Music[artist][album].values.sort_by { |s| s.track || 0}.map { |s| link path, s.title }.join("<br/>") << "<br/><br/>" <<
193
+ link("/artist/#{artist}/album/#{album}/", "play", "Play All")
194
+ else
195
+ html "Could not find <b>#{album}</b> for <b>#{artist}</b>."
196
+ end
197
+ end
198
+
199
+ #Play all songs from a given album
200
+ get '/artist/:artist/album/:album/play/?' do |artist, album|
201
+ if Music[artist][album]
202
+ play_album artist, album
203
+ else
204
+ html "Could not find <b>#{album}</b> by <b>#{artist}</b>."
205
+ end
206
+ end
207
+
208
+ #Play song!
209
+ get '/artist/:artist/album/:album/song/:song/?' do |artist, album, title|
210
+ if song = Music[artist][album][title]
211
+ html <<-HTML
212
+ #{song_info song}<br/>
213
+ #{audio song.path}
214
+ HTML
215
+ else
216
+ html "Could not find <b>#{title}</b> on <b>#{album}</b> by <b>#{artist}</b>."
217
+ end
218
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: the_little_streamer
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Justin Collins
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-14 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sinatra
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 0
33
+ version: "1.0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: ruby-taglib2
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 11
45
+ segments:
46
+ - 1
47
+ - 2
48
+ version: "1.02"
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ description: Point the Little Streamer to your music directory and it will serve up the tunes using the HTML5 audio tag.
52
+ email:
53
+ executables:
54
+ - the_little_streamer
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - bin/the_little_streamer
61
+ - README.md
62
+ has_rdoc: true
63
+ homepage: http://github.com/presidentbeef/the_little_streamer
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ requirements: []
90
+
91
+ rubyforge_project:
92
+ rubygems_version: 1.4.1
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: Sinatra application for streaming music.
96
+ test_files: []
97
+