ektoplayer 0.1.12 → 0.1.16
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.
- checksums.yaml +4 -4
- data/lib/ektoplayer/application.rb +49 -19
- data/lib/ektoplayer/bindings.rb +91 -87
- data/lib/ektoplayer/browsepage.rb +14 -27
- data/lib/ektoplayer/common.rb +12 -67
- data/lib/ektoplayer/compat.rb +5 -11
- data/lib/ektoplayer/config.rb +52 -17
- data/lib/ektoplayer/controllers/browser.rb +10 -5
- data/lib/ektoplayer/database.rb +7 -20
- data/lib/ektoplayer/download/externaldownload.rb +65 -0
- data/lib/ektoplayer/download/rubydownload.rb +69 -0
- data/lib/ektoplayer/icurses/curses.rb +18 -2
- data/lib/ektoplayer/icurses/{ffi_ncurses.rb → ffi-ncurses.rb} +1 -0
- data/lib/ektoplayer/icurses/ncurses.rb +10 -0
- data/lib/ektoplayer/icurses.rb +13 -5
- data/lib/ektoplayer/models/browser.rb +11 -11
- data/lib/ektoplayer/models/player.rb +4 -5
- data/lib/ektoplayer/operations/browser.rb +9 -1
- data/lib/ektoplayer/operations/playlist.rb +1 -1
- data/lib/ektoplayer/players/mpg_wrapper_player.rb +98 -40
- data/lib/ektoplayer/theme.rb +78 -63
- data/lib/ektoplayer/trackloader.rb +25 -74
- data/lib/ektoplayer/ui/colors.rb +33 -5
- data/lib/ektoplayer/ui/widgets/container.rb +1 -1
- data/lib/ektoplayer/ui/widgets/listwidget.rb +35 -34
- data/lib/ektoplayer/ui/widgets.rb +19 -0
- data/lib/ektoplayer/ui.rb +22 -23
- data/lib/ektoplayer/updater.rb +3 -4
- data/lib/ektoplayer/views/browser.rb +7 -2
- data/lib/ektoplayer/views/help.rb +5 -2
- data/lib/ektoplayer/views/info.rb +22 -27
- data/lib/ektoplayer/views/playinginfo.rb +20 -19
- data/lib/ektoplayer/views/playlist.rb +8 -3
- data/lib/ektoplayer/views/progressbar.rb +26 -33
- data/lib/ektoplayer/views/splash.rb +14 -22
- data/lib/ektoplayer/views/trackrenderer.rb +14 -10
- metadata +7 -5
data/lib/ektoplayer/config.rb
CHANGED
@@ -24,12 +24,14 @@ module Ektoplayer
|
|
24
24
|
|
25
25
|
def self.parse_simple_format(format)
|
26
26
|
self._parse_markup(format).map do |fmt|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
fmt[:curses_attrs]
|
27
|
+
fmt[:curses_attrs] = [
|
28
|
+
(fmt[:fg] and Integer(fmt[:fg]) rescue fmt[:fg].to_sym),
|
29
|
+
(fmt[:bg] and Integer(fmt[:bg]) rescue fmt[:bg].to_sym),
|
30
|
+
]
|
31
|
+
fmt[:curses_attrs] << :bold if fmt[:bold]
|
32
|
+
fmt[:curses_attrs] << :blink if fmt[:blink]
|
33
|
+
fmt[:curses_attrs] << :standout if fmt[:standout]
|
34
|
+
fmt[:curses_attrs] << :underline if fmt[:underline]
|
33
35
|
fmt
|
34
36
|
end
|
35
37
|
end
|
@@ -56,14 +58,28 @@ module Ektoplayer
|
|
56
58
|
<album rel="30" fg="red" />
|
57
59
|
<title rel="33" fg="yellow" />
|
58
60
|
<styles rel="20" fg="cyan" />
|
59
|
-
<bpm size="
|
61
|
+
<bpm size="3" fg="green" justify="right" />}.squeeze(' ').freeze
|
60
62
|
|
61
|
-
|
63
|
+
DEFAULT_PLAYINGINFO_FORMAT_TOP =
|
62
64
|
'<text fg="black"><< </text><title bold="on" fg="yellow" /><text fg="black"> >></text>'.freeze
|
63
65
|
|
64
|
-
|
66
|
+
DEFAULT_PLAYINGINFO_FORMAT_BOTTOM =
|
65
67
|
'<artist bold="on" fg="blue" /><text> - </text><album bold="on" fg="red" /><text> (</text><year fg="cyan" /><text>)</text>'.freeze
|
66
68
|
|
69
|
+
DEFAULT_PLAYLIST_FORMAT_256 = %{
|
70
|
+
<number size="3" fg="97" />
|
71
|
+
<artist rel="25" fg="24" />
|
72
|
+
<album rel="30" fg="160" />
|
73
|
+
<title rel="33" fg="178" />
|
74
|
+
<styles rel="20" fg="37" />
|
75
|
+
<bpm size="3" fg="28" justify="right" />}.squeeze(' ').freeze
|
76
|
+
|
77
|
+
DEFAULT_PLAYINGINFO_FORMAT_TOP_256 =
|
78
|
+
'<text fg="236"><< </text><title bold="on" fg="178" /><text fg="236"> >></text>'.freeze
|
79
|
+
|
80
|
+
DEFAULT_PLAYINGINFO_FORMAT_BOTTOM_256 =
|
81
|
+
'<artist bold="on" fg="24" /><text> - </text><album bold="on" fg="160" /><text> (</text><year fg="37" /><text>)</text>'.freeze
|
82
|
+
|
67
83
|
def register(key, description, default, method=nil)
|
68
84
|
# parameter `description` is used by tools/mkconfig.rb, but not here
|
69
85
|
|
@@ -118,7 +134,7 @@ module Ektoplayer
|
|
118
134
|
|
119
135
|
reg :playlist_load_newest,
|
120
136
|
%{How many tracks from database should be added to
|
121
|
-
the playlist on application start.},
|
137
|
+
the playlist on application start.}, 1000
|
122
138
|
|
123
139
|
reg :use_cache,
|
124
140
|
%{Enable/disable local mp3 cache.
|
@@ -143,12 +159,20 @@ module Ektoplayer
|
|
143
159
|
'Number of donwload threads during database update',
|
144
160
|
20, lambda { |v| fail if Integer(v) < 1; Integer(v) }
|
145
161
|
|
146
|
-
|
162
|
+
# - Playlist
|
163
|
+
reg 'playlist.format', 'Format of playlist columns',
|
147
164
|
DEFAULT_PLAYLIST_FORMAT, ColumnFormat.method(:parse_column_format)
|
148
165
|
|
149
|
-
reg 'playlist.
|
166
|
+
reg 'playlist.format_256', 'Format of playlist columns (256 colors)',
|
167
|
+
DEFAULT_PLAYLIST_FORMAT_256, ColumnFormat.method(:parse_column_format)
|
168
|
+
|
169
|
+
# - Browser
|
170
|
+
reg 'browser.format', 'Format of browser columns',
|
150
171
|
DEFAULT_PLAYLIST_FORMAT, ColumnFormat.method(:parse_column_format)
|
151
172
|
|
173
|
+
reg 'browser.format_256', 'Format of browser columns (256 colors)',
|
174
|
+
DEFAULT_PLAYLIST_FORMAT_256, ColumnFormat.method(:parse_column_format)
|
175
|
+
|
152
176
|
# - Progressbar
|
153
177
|
reg 'progressbar.display',
|
154
178
|
'Enable/disable progressbar', true
|
@@ -163,12 +187,24 @@ module Ektoplayer
|
|
163
187
|
reg 'playinginfo.display',
|
164
188
|
'Enable/display playinginfo', true
|
165
189
|
|
166
|
-
reg 'playinginfo.
|
167
|
-
'Format of first line in playinginfo',
|
190
|
+
reg 'playinginfo.format_top',
|
191
|
+
'Format of first line in playinginfo',
|
192
|
+
DEFAULT_PLAYINGINFO_FORMAT_TOP,
|
193
|
+
ColumnFormat.method(:parse_simple_format)
|
194
|
+
|
195
|
+
reg 'playinginfo.format_top_256',
|
196
|
+
'Format of first line in playinginfo (256 colors)',
|
197
|
+
DEFAULT_PLAYINGINFO_FORMAT_TOP_256,
|
198
|
+
ColumnFormat.method(:parse_simple_format)
|
199
|
+
|
200
|
+
reg 'playinginfo.format_bottom',
|
201
|
+
'Format of second line in playinginfo',
|
202
|
+
DEFAULT_PLAYINGINFO_FORMAT_BOTTOM,
|
168
203
|
ColumnFormat.method(:parse_simple_format)
|
169
204
|
|
170
|
-
reg 'playinginfo.
|
171
|
-
'Format of second line in playinginfo',
|
205
|
+
reg 'playinginfo.format_bottom_256',
|
206
|
+
'Format of second line in playinginfo (256 colors)',
|
207
|
+
DEFAULT_PLAYINGINFO_FORMAT_BOTTOM_256,
|
172
208
|
ColumnFormat.method(:parse_simple_format)
|
173
209
|
|
174
210
|
# - Tabbar
|
@@ -232,7 +268,6 @@ module Ektoplayer
|
|
232
268
|
begin
|
233
269
|
cb = callbacks[command.to_sym]
|
234
270
|
cb.call(*args)
|
235
|
-
#fail "Command '#{command}' given args: #{args.size}, wanted #{cb.arity}" if args.size != cb.arity
|
236
271
|
rescue
|
237
272
|
fail "#{file}:#{$.}: #{command}: #{$!}"
|
238
273
|
end
|
@@ -16,19 +16,24 @@ module Ektoplayer
|
|
16
16
|
each { |op| register.(op, &view.method(op)) }
|
17
17
|
|
18
18
|
register.(:enter) do
|
19
|
-
|
19
|
+
selection = view.get_selection
|
20
|
+
|
21
|
+
operations.send(:'browser.enter', selection[0])
|
22
|
+
|
23
|
+
if selection.size > 1
|
24
|
+
selection[1..-1].each do |index|
|
25
|
+
operations.send(:'browser.add_to_playlist', index)
|
26
|
+
end
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
30
|
register.(:add_to_playlist) do
|
23
|
-
#if tracks = browser.tracks(view.selected)
|
24
31
|
view.get_selection.each do |index|
|
25
32
|
operations.send(:'browser.add_to_playlist', index)
|
26
33
|
end
|
27
|
-
#end
|
28
34
|
end
|
29
35
|
|
30
|
-
|
31
|
-
view.mouse.on(65536) do view.up(5) end
|
36
|
+
view.mouse.on(65536) do view.up(5) end
|
32
37
|
view.mouse.on(2097152) do view.down(5) end
|
33
38
|
|
34
39
|
[ICurses::BUTTON1_DOUBLE_CLICKED, ICurses::BUTTON3_CLICKED].each do |btn|
|
data/lib/ektoplayer/database.rb
CHANGED
@@ -25,12 +25,7 @@ module Ektoplayer
|
|
25
25
|
|
26
26
|
a.artist AS album_artist,
|
27
27
|
a.title AS album,
|
28
|
-
a.released_by AS released_by,
|
29
|
-
a.released_by_url AS released_by_url,
|
30
|
-
a.posted_by AS posted_by,
|
31
|
-
a.posted_by_url AS posted_by_url,
|
32
28
|
a.cover_url AS cover_url,
|
33
|
-
a.category AS category,
|
34
29
|
a.description AS description,
|
35
30
|
a.date AS date,
|
36
31
|
a.rating AS rating,
|
@@ -75,12 +70,7 @@ module Ektoplayer
|
|
75
70
|
url TEXT NOT NULL,
|
76
71
|
title TEXT NOT NULL,
|
77
72
|
artist TEXT,
|
78
|
-
released_by TEXT,
|
79
|
-
released_by_url TEXT,
|
80
|
-
posted_by TEXT,
|
81
|
-
posted_by_url TEXT,
|
82
73
|
cover_url TEXT,
|
83
|
-
category TEXT,
|
84
74
|
description TEXT,
|
85
75
|
date DATE,
|
86
76
|
rating FLOAT NOT NULL DEFAULT -1,
|
@@ -144,10 +134,8 @@ module Ektoplayer
|
|
144
134
|
insert_into(table, hash, mode: :replace)
|
145
135
|
end
|
146
136
|
|
147
|
-
def execute(query, params=
|
148
|
-
|
149
|
-
stm.bind_params(*params) if params
|
150
|
-
stm.execute.to_a
|
137
|
+
def execute(query, params=[])
|
138
|
+
@db.execute(query, *params)
|
151
139
|
rescue
|
152
140
|
Application.log(self, $!)
|
153
141
|
end
|
@@ -156,7 +144,7 @@ module Ektoplayer
|
|
156
144
|
columns: ?*,
|
157
145
|
filters: [],
|
158
146
|
group_by: 'url',
|
159
|
-
order_by: 'album,
|
147
|
+
order_by: 'album,number',
|
160
148
|
limit: nil
|
161
149
|
)
|
162
150
|
where_clauses, where_params = [], []
|
@@ -182,7 +170,7 @@ module Ektoplayer
|
|
182
170
|
|
183
171
|
limit = "LIMIT #{limit}" if limit
|
184
172
|
|
185
|
-
|
173
|
+
query = SELECT % {
|
186
174
|
SELECT_COLUMNS: columns,
|
187
175
|
WHERE: where_clauses.join(' '),
|
188
176
|
GROUP_BY: group_by,
|
@@ -190,8 +178,7 @@ module Ektoplayer
|
|
190
178
|
LIMIT: limit
|
191
179
|
}
|
192
180
|
|
193
|
-
|
194
|
-
stm.execute.to_a
|
181
|
+
@db.execute(query, *where_params)
|
195
182
|
rescue
|
196
183
|
Application.log(self, $!)
|
197
184
|
end
|
@@ -201,11 +188,11 @@ module Ektoplayer
|
|
201
188
|
end
|
202
189
|
|
203
190
|
def track_count
|
204
|
-
@db.
|
191
|
+
@db.get_first_value('SELECT COUNT(*) FROM tracks')
|
205
192
|
end
|
206
193
|
|
207
194
|
def album_count
|
208
|
-
@db.
|
195
|
+
@db.get_first_value('SELECT COUNT(*) FROM albums')
|
209
196
|
end
|
210
197
|
end
|
211
198
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
require_relative '../events'
|
5
|
+
|
6
|
+
class ExternalDownload
|
7
|
+
attr_reader :events, :url, :progress, :filename, :error
|
8
|
+
|
9
|
+
def initialize(url, filename)
|
10
|
+
@events = Events.new(:completed, :failed)
|
11
|
+
@url = URI.parse(url)
|
12
|
+
@filename = filename
|
13
|
+
@progress = 0
|
14
|
+
@error = nil
|
15
|
+
@tries = 3
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.get_wget_cmd(url, file)
|
19
|
+
%w(wget -nv --show-progress --progress=dot:binary -O) + [file, url]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.get_curl_cmd(url, file)
|
23
|
+
%w(curl -# -o) + [file, url]
|
24
|
+
end
|
25
|
+
|
26
|
+
def start!
|
27
|
+
Thread.new do
|
28
|
+
args = CMD.(@url.to_s, @filename)
|
29
|
+
dl_in, dl_out, dl_err, @dl_proc = Open3.popen3(*args)
|
30
|
+
|
31
|
+
begin
|
32
|
+
while (line = dl_err.readpartial(1024))
|
33
|
+
@last_line = line
|
34
|
+
|
35
|
+
if (progress = line.scan(/(\d+(\.\d+)?%)/)[0][0].delete(?%).to_f rescue nil)
|
36
|
+
@progress = progress
|
37
|
+
end
|
38
|
+
end
|
39
|
+
rescue
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
@dl_proc.join
|
45
|
+
raise if @dl_proc.value.exitstatus > 0
|
46
|
+
@progress = 100.0
|
47
|
+
@events.trigger(:completed)
|
48
|
+
rescue
|
49
|
+
@events.trigger(:failed, (@error = @last_line))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
sleep 0.1 while @dl_proc.nil?
|
54
|
+
sleep 0.2
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
if system('wget --version >/dev/null 2>/dev/null')
|
59
|
+
CMD = method :get_wget_cmd
|
60
|
+
elsif system('curl --version >/dev/null 2>/dev/null')
|
61
|
+
CMD = method :get_curl_cmd
|
62
|
+
else
|
63
|
+
fail LoadError, 'wget/curl not installed'
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
require_relative '../events'
|
5
|
+
|
6
|
+
class RubyDownload
|
7
|
+
attr_reader :events, :url, :filename, :error
|
8
|
+
|
9
|
+
def initialize(url, filename)
|
10
|
+
@events = Events.new(:completed, :failed)
|
11
|
+
@url = URI.parse(url)
|
12
|
+
@filename = filename
|
13
|
+
@bytes_read = 0
|
14
|
+
@error, @total = nil, nil
|
15
|
+
@tries = 3
|
16
|
+
end
|
17
|
+
|
18
|
+
def progress
|
19
|
+
(@bytes_read.to_f / @total * 100) rescue 0).clamp(0, 100).to_f
|
20
|
+
end
|
21
|
+
|
22
|
+
def start!
|
23
|
+
Thread.new do
|
24
|
+
success = false
|
25
|
+
|
26
|
+
@tries.times do |try|
|
27
|
+
begin
|
28
|
+
do_download
|
29
|
+
@events.trigger(:completed)
|
30
|
+
success = true
|
31
|
+
break
|
32
|
+
rescue
|
33
|
+
@_lasterror = $!
|
34
|
+
sleep 3
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
unless success
|
39
|
+
@events.trigger(:failed, @_lasterror)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
sleep 0.1 while @total.nil?
|
44
|
+
sleep 0.2
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
private def do_download
|
49
|
+
@file = File.open(filename, ?w)
|
50
|
+
@bytes_read, @total, @error = 0, nil, nil
|
51
|
+
|
52
|
+
http = Net::HTTP.new(@url.host, @url.port)
|
53
|
+
|
54
|
+
http.request(Net::HTTP::Get.new(@url.request_uri)) do |res|
|
55
|
+
fail res.body unless res.code == '200'
|
56
|
+
|
57
|
+
@total = res.header['Content-Length'].to_i
|
58
|
+
|
59
|
+
res.read_body do |chunk|
|
60
|
+
@bytes_read += chunk.size
|
61
|
+
@file << chunk
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
fail 'filesize mismatch' if @bytes_read != @total
|
66
|
+
ensure
|
67
|
+
(@file.close rescue nil) if @file
|
68
|
+
end
|
69
|
+
end
|
@@ -17,10 +17,25 @@ module Curses
|
|
17
17
|
alias_method :"get#{method}", method.to_sym
|
18
18
|
end
|
19
19
|
|
20
|
+
def leaveok(*_); end # Curses does not
|
21
|
+
def notimeout(*_); end # provide these functions
|
22
|
+
|
20
23
|
alias :timeout :timeout=
|
21
|
-
alias :notimeout :nodelay= #todo
|
22
24
|
alias :nodelay :nodelay=
|
23
25
|
|
26
|
+
def bkgd(attr)
|
27
|
+
@bkgd_color = attr
|
28
|
+
end
|
29
|
+
alias :bkgdset :bkgd
|
30
|
+
|
31
|
+
def erase
|
32
|
+
setpos(0, 0)
|
33
|
+
attrset((@bkgd_color or 0))
|
34
|
+
addstr(' ' * (maxx * maxy))
|
35
|
+
attroff((@bkgd_color or 0))
|
36
|
+
setpos(0, 0)
|
37
|
+
end
|
38
|
+
|
24
39
|
alias :mvwin :move # 'fix' this Gem
|
25
40
|
def move(y, x)
|
26
41
|
setpos(y, x)
|
@@ -28,7 +43,8 @@ module Curses
|
|
28
43
|
end
|
29
44
|
|
30
45
|
class Pad < Window
|
31
|
-
alias :pnoutrefresh :
|
46
|
+
alias :pnoutrefresh :noutrefresh
|
47
|
+
alias :prefresh :refresh
|
32
48
|
end
|
33
49
|
end
|
34
50
|
|
@@ -17,6 +17,7 @@ module Ncurses
|
|
17
17
|
end
|
18
18
|
|
19
19
|
%w(getcurx getcury getmaxx getmaxy getbegx getbegy
|
20
|
+
clearok idlok idcok immedok leaveok setscrreg scrollok nl nonl
|
20
21
|
keypad nodelay notimeout prefresh pnoutrefresh).each do |meth|
|
21
22
|
define_method(meth) do |*args|
|
22
23
|
Ncurses.send(meth, @w, *args)
|
@@ -36,6 +37,15 @@ module Ncurses
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
40
|
+
|
41
|
+
if $USING_CURSES == 'ncurses'
|
42
|
+
### FIX: 'attrset' in ncurses is broken!
|
43
|
+
def attrset(attributes)
|
44
|
+
Ncurses.send(:wattr_get, @w, old_a=[], old_c=[], nil)
|
45
|
+
Ncurses.send(:wattroff, @w, old_a[0] | old_c[0])
|
46
|
+
Ncurses.send(:wattron, @w, attributes)
|
47
|
+
end
|
48
|
+
end
|
39
49
|
end
|
40
50
|
end
|
41
51
|
|
data/lib/ektoplayer/icurses.rb
CHANGED
@@ -9,13 +9,21 @@
|
|
9
9
|
end
|
10
10
|
|
11
11
|
fail %{
|
12
|
-
No
|
13
|
-
-
|
14
|
-
-
|
15
|
-
- ncurses-ruby
|
16
|
-
-
|
12
|
+
No module for ncurses found. Please install one of the following gems:
|
13
|
+
- ffi-ncurses (preferred)
|
14
|
+
- ncursesw (good)
|
15
|
+
- ncurses-ruby (good)
|
16
|
+
- curses (works...)
|
17
17
|
|
18
18
|
Maybe your distribution ships one of these already as a package.
|
19
|
+
|
20
|
+
Arch Linux:
|
21
|
+
yaourt -S ruby-curses # or
|
22
|
+
yaourt -S ruby-ncursesw
|
23
|
+
|
24
|
+
Debian / Ubuntu:
|
25
|
+
apt-get install ruby-ncurses
|
26
|
+
|
19
27
|
} unless $USING_CURSES
|
20
28
|
|
21
29
|
require_relative 'icurses/sugar'
|
@@ -6,13 +6,11 @@ module Ektoplayer
|
|
6
6
|
PARENT_DIRECTORY = '..'.freeze
|
7
7
|
|
8
8
|
PATHS = {
|
9
|
-
artist:
|
10
|
-
album:
|
11
|
-
style:
|
12
|
-
year:
|
13
|
-
title:
|
14
|
-
released_by: [:released_by].freeze,
|
15
|
-
posted_by: [:posted_by ].freeze
|
9
|
+
artist: [:artist].freeze,
|
10
|
+
album: [:album ].freeze,
|
11
|
+
style: [:style ].freeze,
|
12
|
+
year: [:year ].freeze,
|
13
|
+
title: [].freeze
|
16
14
|
}.freeze
|
17
15
|
|
18
16
|
def initialize(client)
|
@@ -36,16 +34,18 @@ module Ektoplayer
|
|
36
34
|
end
|
37
35
|
|
38
36
|
def enter(index)
|
39
|
-
return unless (sub = current.enter(index))
|
37
|
+
return false unless (sub = current.enter(index))
|
40
38
|
return back() if sub == :parent
|
41
39
|
@stack.push(sub)
|
42
40
|
@events.trigger(:changed)
|
41
|
+
true
|
43
42
|
end
|
44
43
|
|
45
44
|
def back
|
46
|
-
return unless @stack.size > 1
|
45
|
+
return false unless @stack.size > 1
|
47
46
|
@stack.pop
|
48
47
|
@events.trigger(:changed)
|
48
|
+
true
|
49
49
|
end
|
50
50
|
|
51
51
|
class BrowsableCollection
|
@@ -91,7 +91,7 @@ module Ektoplayer
|
|
91
91
|
return [] if index == 0
|
92
92
|
return [ @contents[index] ]
|
93
93
|
else
|
94
|
-
@database.select(filters: new_filters(index))
|
94
|
+
@database.select(filters: new_filters(index))
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
@@ -121,7 +121,7 @@ module Ektoplayer
|
|
121
121
|
|
122
122
|
def tracks(index)
|
123
123
|
@database.select(
|
124
|
-
order_by: CONTENTS[index].to_s + ",album,
|
124
|
+
order_by: 'album,' + CONTENTS[index].to_s + ",album,number"
|
125
125
|
)
|
126
126
|
end
|
127
127
|
end
|
@@ -8,11 +8,12 @@ module Ektoplayer
|
|
8
8
|
super()
|
9
9
|
@client = client
|
10
10
|
@player = MpgWrapperPlayer.new
|
11
|
-
@events
|
12
|
-
|
11
|
+
@events = @player.events
|
12
|
+
#@events.register(:position_change, :track_completed, :pause, :stop, :play)
|
13
|
+
#@player.events.on_all(&@events.method(:trigger))
|
13
14
|
|
14
15
|
%w(pause toggle stop forward backward seek
|
15
|
-
length position position_percent
|
16
|
+
length position position_percent can_http?).each do |m|
|
16
17
|
self.define_singleton_method(m, &@player.method(m))
|
17
18
|
end
|
18
19
|
end
|
@@ -21,8 +22,6 @@ module Ektoplayer
|
|
21
22
|
Application.log(self, 'playing', file)
|
22
23
|
@player.play(file) rescue Application.log(self, $!)
|
23
24
|
end
|
24
|
-
|
25
|
-
def close; @player.close end
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
@@ -7,8 +7,16 @@ module Ektoplayer
|
|
7
7
|
# +add_to_playlist+:: see
|
8
8
|
def initialize(operations, browser, playlist)
|
9
9
|
register = operations.with_register('browser.')
|
10
|
-
register.(:enter, &browser.method(:enter))
|
11
10
|
register.(:back, &browser.method(:back))
|
11
|
+
|
12
|
+
register.(:enter) do |index|
|
13
|
+
unless browser.enter(index)
|
14
|
+
tracks = browser.tracks(index)
|
15
|
+
playlist.add(*tracks)
|
16
|
+
operations.send(:'playlist.play', playlist.size - tracks.size)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
register.(:add_to_playlist) do |index|
|
13
21
|
tracks = browser.tracks(index)
|
14
22
|
playlist.add(*tracks)
|
@@ -35,7 +35,7 @@ module Ektoplayer
|
|
35
35
|
return unless track = @playlist[index]
|
36
36
|
@playlist.current_playing=(index)
|
37
37
|
Thread.new do
|
38
|
-
@player.play(@trackloader.get_track_file(track['url']))
|
38
|
+
@player.play(@trackloader.get_track_file(track['url'], http_okay: @player.can_http?))
|
39
39
|
end.join(0.3) # prevent too many hits
|
40
40
|
end
|
41
41
|
|