ruby-ampache 0.0.10 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +8 -13
- data/VERSION +1 -1
- data/bin/ruby-ampache +96 -66
- data/lib/lib-ampache.rb +73 -60
- data/lib/lib-classes.rb +176 -147
- metadata +4 -5
data/README.rdoc
CHANGED
@@ -6,15 +6,11 @@ Ruby-ampache is a really simple command line player for the ampache music server
|
|
6
6
|
|
7
7
|
You need to have mplayer installed to use ruby-ampache. Mplayer is used for playing music streams.
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
I've recently changed the way mplayer is invoked as mplayer slave mode is great,
|
10
|
+
but not good to manage playlists..
|
11
|
+
I'm still testing it right now but it should work far better.
|
11
12
|
|
12
|
-
the
|
13
|
-
set TIMEOUT variable in your .ruby-ampache config file
|
14
|
-
tuning it depending on your ampache server delay
|
15
|
-
|
16
|
-
Yes, this should be handled different
|
17
|
-
I'm free to any kind of suggestion on how to refactor this simple piece of software :)
|
13
|
+
A few options have been added to the menu and most of all it is full of colors now!
|
18
14
|
|
19
15
|
Gem can be installed as usual
|
20
16
|
|
@@ -27,11 +23,8 @@ example file:
|
|
27
23
|
AMPACHE_HOST="http://path_to_your_ampache_host"
|
28
24
|
AMPACHE_USER="username"
|
29
25
|
AMPACHE_USER_PSW="userpsw"
|
30
|
-
|
31
26
|
#optional (default is /usr/bin/mplayer)
|
32
27
|
MPLAYER_PATH="/usr/bin/mplayer"
|
33
|
-
# try to increase this value if you experience issues like "err on reading data"
|
34
|
-
TIMEOUT=20 #20 is a good value for a remote host
|
35
28
|
|
36
29
|
Simply execute ruby-ampache that should be found in you $PATH after installation
|
37
30
|
|
@@ -42,6 +35,10 @@ Also sometimes if mplayer get stucked playing a song the app does the same.
|
|
42
35
|
|
43
36
|
If you found more issues please let me know and I'll try to fix them as soon as possible
|
44
37
|
|
38
|
+
* fix encoding issues with file metadata retrieved from mplayer
|
39
|
+
|
40
|
+
|
41
|
+
|
45
42
|
== Notes
|
46
43
|
Special thanks goes to the developer of mplayer-ruby gem.
|
47
44
|
I've borrowed a couple of methods from his useful library
|
@@ -50,8 +47,6 @@ I've borrowed a couple of methods from his useful library
|
|
50
47
|
|
51
48
|
* Fork the project.
|
52
49
|
* Make your feature addition or bug fix.
|
53
|
-
* Add tests for it. This is important so I don't break it in a
|
54
|
-
future version unintentionally.
|
55
50
|
* Commit, do not mess with rakefile, version, or history.
|
56
51
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
57
52
|
* Send me a pull request. Bonus points for topic branches.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.1
|
data/bin/ruby-ampache
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
# encoding: UTF-8
|
3
3
|
|
4
4
|
def secure_require(name)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
begin
|
6
|
+
require name
|
7
|
+
rescue LoadError
|
8
|
+
$stderr.print "#{File.basename(__FILE__)} requires #{name} gem to work\n Pleas install it with: gem install #{name}\n"
|
9
|
+
exit
|
10
|
+
end
|
11
11
|
end
|
12
12
|
|
13
13
|
require 'rubygems'
|
@@ -16,77 +16,105 @@ secure_require 'highline/import'
|
|
16
16
|
secure_require 'parseconfig'
|
17
17
|
secure_require 'nokogiri'
|
18
18
|
secure_require 'iconv'
|
19
|
-
require File.join(File.dirname(__FILE__),'..','lib','lib-ampache')
|
20
|
-
require File.join(File.dirname(__FILE__),'..','lib','lib-classes')
|
19
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'lib-ampache')
|
20
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'lib-classes')
|
21
21
|
|
22
22
|
# XXX monkey patch for utf8 on ruby 1.9
|
23
23
|
if /^1\.9/ === RUBY_VERSION then
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
wrapped << line
|
41
|
-
end
|
42
|
-
return wrapped.join
|
24
|
+
class HighLine
|
25
|
+
def wrap (text)
|
26
|
+
text = text.force_encoding("UTF-8")
|
27
|
+
wrapped = []
|
28
|
+
text.each_line do |line|
|
29
|
+
while line =~ /([^\n]{#{@wrap_at + 1},})/
|
30
|
+
search = $1.dup
|
31
|
+
replace = $1.dup
|
32
|
+
if index = replace.rindex(" ", @wrap_at)
|
33
|
+
replace[index, 1] = "\n"
|
34
|
+
replace.sub!(/\n[ \t]+/, "\n")
|
35
|
+
line.sub!(search, replace)
|
36
|
+
else
|
37
|
+
line[$~.begin(1) + @wrap_at, 0] = "\n"
|
38
|
+
end
|
43
39
|
end
|
40
|
+
wrapped << line
|
41
|
+
end
|
42
|
+
return wrapped.join
|
44
43
|
end
|
44
|
+
end
|
45
45
|
end
|
46
46
|
|
47
47
|
# Ampache ruby parameters
|
48
48
|
begin
|
49
|
-
ar_config = ParseConfig.new(File.expand_path('~/.ruby-ampache'))
|
49
|
+
ar_config = ParseConfig.new(File.expand_path('~/.ruby-ampache'))
|
50
50
|
rescue
|
51
|
-
|
51
|
+
raise "\nPlease create a .ruby-ampache file on your home\n See http://github.com/ghedamat/ruby-ampache for infos\n"
|
52
52
|
end
|
53
53
|
|
54
54
|
# ruby-ampache highline version
|
55
55
|
$terminal.wrap_at = 80
|
56
56
|
$terminal.page_at = 22
|
57
57
|
|
58
|
+
def print_songs(album)
|
59
|
+
choose do |menu|
|
60
|
+
menu.prompt = "PICK A SONG (4..N), ADD WHOLE ALBUM (3), GO BACK(2) or BACK TO MENU(1)"
|
61
|
+
menu.choice(HighLine.new.color "BACK TO MENU", :red)
|
62
|
+
menu.choice(HighLine.new.color "BACK", :magenta) { print_albums(album.artist.albums) }
|
63
|
+
menu.choice(HighLine.new.color "ADD WHOLE ALBUM", :green) { album.add_to_playlist(@pl); print_albums(album.artist.albums) }
|
64
|
+
album.songs.each do |s|
|
65
|
+
menu.choice(s.title) { s.add_to_playlist(@pl); print_songs(album) }
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
58
71
|
def print_albums(albums)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
72
|
+
choose do |menu|
|
73
|
+
menu.prompt = "CHOOSE AN ALBUM (4..N), ADD WHOLE ARTIST(3), BACK TO LIST(2) or BACK TO MENU (1) "
|
74
|
+
menu.choice(HighLine.new.color "BACK TO MENU", :red)
|
75
|
+
menu.choice(HighLine.new.color "BACK", :magenta) { print_artists(@ar.artists) }
|
76
|
+
menu.choice(HighLine.new.color "ADD WHOLE ARTIST", :green) { albums.first.artist.add_to_playlist(@pl); print_artists(@ar.artists) }
|
77
|
+
|
78
|
+
albums.each do |a|
|
79
|
+
menu.choice(a.name) { print_songs(a) }
|
80
|
+
end
|
81
|
+
end
|
66
82
|
end
|
67
83
|
|
68
84
|
def print_artists(artists)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
85
|
+
if artists.empty?
|
86
|
+
reset_token
|
87
|
+
say("No results, retrying")
|
88
|
+
artists = @ar.artists
|
89
|
+
end
|
90
|
+
choose do |menu|
|
91
|
+
menu.prompt = "CHOOSE AN ARTIST (2..N) or BACK TO MENU (1)"
|
92
|
+
menu.choice(HighLine.new.color "BACK TO MENU", :red)
|
93
|
+
artists.each do |a|
|
94
|
+
menu.choice(a.name) { print_albums(a.albums) }
|
80
95
|
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def print_playlist
|
100
|
+
if @pl.list.empty?
|
101
|
+
say(HighLine.new.color "No more songs!\n",:red)
|
102
|
+
return
|
103
|
+
end
|
104
|
+
say(HighLine.new.color "Next Songs:", :yellow)
|
105
|
+
@pl.list.each_with_index do |p,i|
|
106
|
+
say(HighLine.new.color(i.to_s + " : ", :green) + p.title)
|
107
|
+
end
|
108
|
+
puts ""
|
81
109
|
end
|
82
110
|
|
83
111
|
# try to reset token if it's not valid
|
84
112
|
def reset_token
|
85
|
-
|
113
|
+
@ar.token = @ar.getAuthToken(@ar.user, @ar.psw)
|
86
114
|
end
|
87
115
|
|
88
116
|
def credits
|
89
|
-
|
117
|
+
s = <<STR
|
90
118
|
Ruby-Ampache: Ultra-simple, low-featured command line Ampache player (uses mplayer for playing)
|
91
119
|
Author: Mattia Gheda aka ghedamat
|
92
120
|
Homepage: http://github.com/ghedamat/ruby-ampache
|
@@ -94,32 +122,34 @@ Author-mail: thamayor@gmail.com
|
|
94
122
|
|
95
123
|
Usage: pick your choice from the menu.
|
96
124
|
You can start playing songs from your ampache server right now!
|
97
|
-
Simply choose an artist
|
125
|
+
Simply choose an artist,an album or a single song
|
98
126
|
You can queue up as many albums you like
|
99
|
-
Songs are queued up into mplayer playlist
|
100
|
-
|
101
127
|
STR
|
102
|
-
|
128
|
+
return s
|
103
129
|
end
|
104
130
|
|
105
131
|
# MAIN
|
106
|
-
@ar =AmpacheRuby.new(ar_config.get_value('AMPACHE_HOST'),ar_config.get_value('AMPACHE_USER'), ar_config.get_value('AMPACHE_USER_PSW'))
|
132
|
+
@ar =AmpacheRuby.new(ar_config.get_value('AMPACHE_HOST'), ar_config.get_value('AMPACHE_USER'), ar_config.get_value('AMPACHE_USER_PSW'))
|
107
133
|
$options = {}
|
108
134
|
$options[:path] = ar_config.get_value('MPLAYER_PATH')
|
109
135
|
$options[:timeout] = ar_config.get_value('TIMEOUT').to_i
|
110
136
|
@pl = AmpachePlaylist.new
|
111
137
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
138
|
+
say(HighLine.new.color "Welcome To ruby Ampache\n", :green)
|
139
|
+
while true
|
140
|
+
choose do |menu|
|
141
|
+
menu.prompt = HighLine.new.color("pick your choice!\n", :yellow)
|
142
|
+
menu.choice(HighLine.new.color("add artist/album/song to the playlist", :green)) { print_artists(@ar.artists); say(HighLine.new.color(@pl.now_playing, :red)) }
|
143
|
+
menu.choice(HighLine.new.color("search artist", :green)) { print_artists(@ar.artists(ask(HighLine.new.color("Artist name?", :red)))); say(HighLine.new.color(@pl.now_playing, :red)) }
|
144
|
+
|
145
|
+
menu.choice(HighLine.new.color("now playing", :magenta)) { say(HighLine.new.color(@pl.now_playing, :red)) }
|
146
|
+
menu.choice(HighLine.new.color("view next songs", :magenta)) {print_playlist}
|
147
|
+
menu.choice(HighLine.new.color("skip current song", :magenta)) { @pl.next; sleep 1;say(HighLine.new.color(@pl.now_playing, :red)) }
|
148
|
+
menu.choice(HighLine.new.color "stop playing and clear playlist", :magenta) { @pl.stop }
|
149
|
+
|
150
|
+
menu.choice(HighLine.new.color "pause playing",:magenta) { @pl.pause; say(HighLine.new.color("pause toggle!", :red)) }
|
151
|
+
menu.choice(HighLine.new.color "help and about", :yellow) { say(HighLine.new.color credits, :red) }
|
152
|
+
menu.choice("quit") { @pl.stop; exit }
|
153
|
+
end
|
124
154
|
end
|
125
155
|
|
data/lib/lib-ampache.rb
CHANGED
@@ -3,7 +3,7 @@ require 'net/http'
|
|
3
3
|
require 'open-uri'
|
4
4
|
require 'digest/sha2'
|
5
5
|
|
6
|
-
require File.join(File.dirname(__FILE__),'lib-ampache')
|
6
|
+
require File.join(File.dirname(__FILE__), 'lib-ampache')
|
7
7
|
|
8
8
|
=begin
|
9
9
|
Class is initialized with Hostname, user and password
|
@@ -13,78 +13,91 @@ To get the artist list from database you can
|
|
13
13
|
call the method artists(nil) and you'll get an array
|
14
14
|
of AmpacheArtists.
|
15
15
|
|
16
|
-
To get albums from an artist you can
|
16
|
+
To get albums from an artist you can use
|
17
17
|
artist_instance.albums or ampache_ruby.instance.albums(artist_instance)
|
18
18
|
=end
|
19
|
+
|
19
20
|
class AmpacheRuby
|
20
|
-
|
21
|
-
|
22
|
-
def initialize(host,user,psw)
|
23
|
-
uri = URI.parse(host)
|
24
|
-
@host = uri.host
|
25
|
-
@path = uri.path
|
26
|
-
@user = user
|
27
|
-
@psw = psw
|
28
|
-
@token = nil
|
29
|
-
@token = getAuthToken(user,psw)
|
30
|
-
end
|
31
21
|
|
32
|
-
attr_accessor :host, :path, :user, :psw, :token, :playlist
|
33
|
-
|
34
|
-
# tryies to obtain an auth token
|
35
|
-
def getAuthToken(user,psw)
|
36
|
-
action= "handshake"
|
37
|
-
# auth string
|
38
|
-
key = Digest::SHA2.new << psw
|
39
|
-
time = Time.now.to_i.to_s
|
40
|
-
psk = Digest::SHA2.new << (time + key.to_s)
|
41
22
|
|
42
|
-
|
43
|
-
|
23
|
+
def initialize(host, user, psw)
|
24
|
+
uri = URI.parse(host)
|
25
|
+
@host = uri.host
|
26
|
+
@path = uri.path
|
27
|
+
@user = user
|
28
|
+
@psw = psw
|
29
|
+
@token = nil
|
30
|
+
@token = getAuthToken(user, psw)
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :host, :path, :user, :psw, :token, :playlist
|
34
|
+
|
35
|
+
# tryies to obtain an auth token
|
36
|
+
def getAuthToken(user, psw)
|
37
|
+
begin
|
38
|
+
action= "handshake"
|
39
|
+
# auth string
|
40
|
+
key = Digest::SHA2.new << psw
|
41
|
+
time = Time.now.to_i.to_s
|
42
|
+
psk = Digest::SHA2.new << (time + key.to_s)
|
44
43
|
|
45
|
-
|
44
|
+
args = {'auth' => psk, 'timestamp'=> time, 'version' => '350001', 'user' => user}
|
45
|
+
doc = callApiMethod(action, args);
|
46
|
+
|
47
|
+
return doc.at("auth").content
|
48
|
+
rescue Exception => e
|
49
|
+
warn ""
|
50
|
+
warn "token not valid or expired, check your username and password"
|
51
|
+
warn ""
|
46
52
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
end
|
54
|
+
|
55
|
+
# generic api method call
|
56
|
+
def callApiMethod(method, args={})
|
57
|
+
begin
|
58
|
+
args['auth'] ||= token if token
|
59
|
+
url = path + "/server/xml.server.php?action=#{method}&#{args.keys.collect { |k| "#{k}=#{args[k]}" }.join('&')}"
|
60
|
+
response = Net::HTTP.get_response(host, url)
|
61
|
+
return Nokogiri::XML(response.body)
|
62
|
+
rescue Errno::ECONNREFUSED => e
|
63
|
+
warn "Ampache closed with the following error"
|
64
|
+
warn e.message
|
65
|
+
exit
|
54
66
|
end
|
67
|
+
end
|
55
68
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
return artists
|
69
|
+
# retrive artists lists from database,
|
70
|
+
# name is an optional filter
|
71
|
+
def artists(name = nil)
|
72
|
+
args = {}
|
73
|
+
args = {'filter' => name.to_s} if name # artist search
|
74
|
+
artists = []
|
75
|
+
doc = callApiMethod("artists", args)
|
76
|
+
doc.xpath("//artist").each do |a|
|
77
|
+
artists << AmpacheArtist.new(self, a['id'], a.at("name").content)
|
67
78
|
end
|
79
|
+
return artists
|
80
|
+
end
|
68
81
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
76
|
-
return albums
|
82
|
+
def albums(artist)
|
83
|
+
albums = []
|
84
|
+
args = {'filter' => artist.uid.to_s}
|
85
|
+
doc = callApiMethod("artist_albums", args)
|
86
|
+
doc.xpath("//album").each do |a|
|
87
|
+
albums << AmpacheAlbum.new(self, a['id'], a.at("name").content, artist)
|
77
88
|
end
|
89
|
+
return albums
|
90
|
+
end
|
78
91
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
return songs
|
92
|
+
def songs(album)
|
93
|
+
songs = []
|
94
|
+
args = {'filter' => album.uid.to_s}
|
95
|
+
doc = callApiMethod("album_songs", args)
|
96
|
+
doc.xpath("//song").each do |s|
|
97
|
+
songs << AmpacheSong.new(self, s['id'], s.at("title").content, album.artist, album, s.at("url").content)
|
87
98
|
end
|
88
|
-
|
99
|
+
return songs
|
100
|
+
end
|
101
|
+
|
89
102
|
end
|
90
103
|
|
data/lib/lib-classes.rb
CHANGED
@@ -1,185 +1,214 @@
|
|
1
1
|
require 'open4'
|
2
2
|
require 'timeout'
|
3
3
|
class AmpacheArtist
|
4
|
-
|
5
|
-
# include play module
|
6
|
-
def initialize(ar,uid,name)
|
7
|
-
@ar = ar
|
8
|
-
@uid = uid
|
9
|
-
@name = name
|
10
|
-
end
|
11
4
|
|
12
|
-
|
5
|
+
# include play module
|
6
|
+
def initialize(ar, uid, name)
|
7
|
+
@ar = ar
|
8
|
+
@uid = uid
|
9
|
+
@name = name
|
10
|
+
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
attr_reader :uid, :name
|
13
|
+
|
14
|
+
def albums
|
15
|
+
@albums ||= @ar.albums(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_to_playlist(pl)
|
19
|
+
albums.each do |s|
|
20
|
+
s.add_to_playlist(pl)
|
21
|
+
sleep 1
|
22
|
+
end
|
23
|
+
end
|
17
24
|
end
|
18
25
|
|
19
26
|
|
20
27
|
class AmpacheAlbum
|
21
|
-
|
22
|
-
def initialize(ar,uid,name,artist)
|
23
|
-
@ar = ar
|
24
|
-
@uid = uid
|
25
|
-
@name = name
|
26
|
-
@artist = artist
|
27
|
-
end
|
28
28
|
|
29
|
-
|
29
|
+
def initialize(ar, uid, name, artist)
|
30
|
+
@ar = ar
|
31
|
+
@uid = uid
|
32
|
+
@name = name
|
33
|
+
@artist = artist
|
34
|
+
end
|
30
35
|
|
31
|
-
|
32
|
-
@songs ||= @ar.songs(self)
|
33
|
-
end
|
36
|
+
attr_reader :uid, :name, :artist
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
def songs
|
39
|
+
@songs ||= @ar.songs(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_to_playlist(pl)
|
43
|
+
songs.each do |s|
|
44
|
+
s.add_to_playlist(pl)
|
39
45
|
end
|
46
|
+
end
|
40
47
|
|
41
48
|
end
|
42
49
|
|
43
50
|
class AmpacheSong
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
def initialize(ar, uid, title, artist, album, url)
|
53
|
+
@ar = ar
|
54
|
+
@uid = uid
|
55
|
+
@title = title
|
56
|
+
@artist = artist
|
57
|
+
@album = album
|
58
|
+
@url = url
|
59
|
+
end
|
53
60
|
|
54
|
-
|
61
|
+
attr_reader :uid, :title, :artist, :album, :url
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
def add_to_playlist(pl)
|
64
|
+
pl.add(self)
|
65
|
+
end
|
59
66
|
|
60
67
|
end
|
61
68
|
|
62
|
-
class AmpachePlaylist
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
69
|
+
class AmpachePlaylist
|
70
|
+
|
71
|
+
def initialize
|
72
|
+
@started = false
|
73
|
+
@list = []
|
74
|
+
end
|
75
|
+
|
76
|
+
attr_reader :list
|
77
|
+
|
78
|
+
def started?
|
79
|
+
@started == true
|
80
|
+
end
|
81
|
+
|
82
|
+
def started!
|
83
|
+
@started = true
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def mplayer_start(song)
|
88
|
+
#puts song.inspect
|
89
|
+
$options[:path] ||= '/usr/bin/mplayer'
|
90
|
+
$options[:timeout] ||= 15
|
91
|
+
mplayer_options = "-slave -quiet"
|
92
|
+
mplayer = "#{$options[:path]} #{mplayer_options} \"#{song.url}\""
|
93
|
+
@pid, @stdin, @stdout, @stderr = Open4.popen4(mplayer)
|
94
|
+
#puts mplayer
|
95
|
+
started!
|
96
|
+
Thread.new do
|
97
|
+
ignored, status = Process::waitpid2 @pid
|
98
|
+
next_song = @list.slice!(0)
|
99
|
+
if next_song && started?
|
100
|
+
mplayer_start(next_song)
|
101
|
+
else
|
102
|
+
puts "PLAYLIST OVER"
|
103
|
+
@started = false
|
104
|
+
@pid = nil
|
105
|
+
end
|
91
106
|
end
|
107
|
+
end
|
92
108
|
|
93
|
-
|
94
|
-
|
109
|
+
def console
|
110
|
+
while ((cmd = gets.chomp) != 'exit' )
|
111
|
+
@stdin.puts cmd
|
95
112
|
end
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
113
|
+
end
|
114
|
+
|
115
|
+
def add(song)
|
116
|
+
say(HighLine.new.color("adding song ",:green) + "#{song.title}")
|
117
|
+
if !@pid && !started?
|
118
|
+
mplayer_start(song)
|
119
|
+
else
|
120
|
+
@list << song
|
104
121
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
122
|
+
end
|
123
|
+
|
124
|
+
def stop
|
125
|
+
begin
|
126
|
+
@started = false
|
127
|
+
@list = []
|
128
|
+
@stdin.puts "quit" if @pid
|
129
|
+
rescue Errno::EPIPE
|
130
|
+
puts "playlist is over"
|
112
131
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
132
|
+
@pid = nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def pause
|
136
|
+
begin
|
137
|
+
@stdin.puts "pause" if @pid && started?
|
138
|
+
rescue Errno::EPIPE
|
139
|
+
puts "playlist is over"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def next
|
144
|
+
begin
|
145
|
+
# quit current mplayer instance.. thread will fire up next song!
|
146
|
+
@stdin.puts "quit" if @pid && started?
|
147
|
+
rescue Errno::EPIPE => e
|
148
|
+
puts "playlist is over on next"
|
149
|
+
@pid = nil
|
121
150
|
end
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
rescue Timeout::Error
|
139
|
-
@tim += 1
|
140
|
-
if (@tim > 3 )
|
141
|
-
@tim = 0
|
142
|
-
return "err"
|
143
|
-
else
|
144
|
-
return nowPlaying
|
145
|
-
end
|
146
|
-
end
|
147
|
-
rescue Errno::EPIPE => e
|
148
|
-
@pid = nil
|
149
|
-
return "playlist is over here" #, or you got an ERROR from mplayer: #{e.to_s}"
|
151
|
+
end
|
152
|
+
|
153
|
+
def now_playing
|
154
|
+
return "Not playing man!" unless started? && !@pid.nil?
|
155
|
+
begin
|
156
|
+
s = get("meta_title")
|
157
|
+
return "data not available OR playlist is over" if s.nil?
|
158
|
+
s+= get("meta_artist") rescue s
|
159
|
+
s+= get("meta_album") rescue s
|
160
|
+
s.chomp!
|
161
|
+
return s
|
162
|
+
|
163
|
+
rescue Errno::EPIPE => e
|
164
|
+
@pid = nil
|
165
|
+
@started = false
|
166
|
+
return "playlist is over here" #, or you got an ERROR from mplayer: #{e.to_s}"
|
150
167
|
|
151
|
-
end
|
152
168
|
end
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
169
|
+
end
|
170
|
+
|
171
|
+
# I borrowed these two methods from the author of mplayer-ruby!
|
172
|
+
# so my thanks to Artuh Chiu and his great gem mplayer-ruby
|
173
|
+
def get(value)
|
174
|
+
field = value.to_s
|
175
|
+
match = case field
|
176
|
+
when "time_pos" then
|
177
|
+
"ANS_TIME_POSITION"
|
178
|
+
when "time_length" then
|
179
|
+
"ANS_LENGTH"
|
180
|
+
when "file_name" then
|
181
|
+
"ANS_FILENAME"
|
182
|
+
else
|
183
|
+
"ANS_#{field.upcase}"
|
166
184
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
response
|
185
|
+
res = command("get_#{value}", /#{match}/)
|
186
|
+
res.gsub("#{match}=", "").gsub("'", "") unless res.nil?
|
187
|
+
end
|
188
|
+
|
189
|
+
def command(cmd, match = //)
|
190
|
+
@stdin.puts(cmd)
|
191
|
+
response = ""
|
192
|
+
begin
|
193
|
+
t = Timeout::timeout(3) do
|
194
|
+
until response =~ match
|
195
|
+
response = @stdout.gets
|
196
|
+
#puts response
|
197
|
+
#XXX escaping bad utf8 chars
|
198
|
+
ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
|
199
|
+
if response
|
200
|
+
response =ic.iconv(response + ' ')[0..-2]
|
201
|
+
else
|
202
|
+
response == ''
|
203
|
+
end
|
179
204
|
end
|
180
205
|
end
|
181
|
-
response.gsub("\e[A\r\e[K","")
|
206
|
+
return response.gsub("\e[A\r\e[K", "")
|
207
|
+
rescue Timeout::Error
|
208
|
+
return
|
182
209
|
end
|
183
210
|
|
211
|
+
end
|
212
|
+
|
184
213
|
end
|
185
214
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ruby-ampache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- ghedmat
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-09-26 00:00:00 +02:00
|
14
14
|
default_executable: ruby-ampache
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -104,6 +104,5 @@ rubygems_version: 1.5.0
|
|
104
104
|
signing_key:
|
105
105
|
specification_version: 3
|
106
106
|
summary: Ruby ampache command line client
|
107
|
-
test_files:
|
108
|
-
|
109
|
-
- test/test_ruby-ampache.rb
|
107
|
+
test_files: []
|
108
|
+
|