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
@@ -20,6 +20,7 @@ module UI
|
|
20
20
|
|
21
21
|
class ListSelector
|
22
22
|
attr_reader :start_pos
|
23
|
+
|
23
24
|
def start(pos)
|
24
25
|
@start_pos = pos
|
25
26
|
end
|
@@ -35,51 +36,49 @@ module UI
|
|
35
36
|
end
|
36
37
|
|
37
38
|
class ListSearch
|
38
|
-
attr_accessor :direction
|
39
|
+
attr_accessor :direction
|
40
|
+
|
41
|
+
def initialize(search: '', direction: :down)
|
42
|
+
@search, @direction = search, direction
|
43
|
+
end
|
39
44
|
|
40
|
-
def
|
41
|
-
@
|
42
|
-
@direction = direction
|
43
|
-
self.search=(search)
|
45
|
+
def search=(search)
|
46
|
+
@search = Regexp.new(search.downcase) rescue search.downcase
|
44
47
|
end
|
45
48
|
|
46
|
-
def comp(item
|
49
|
+
private def comp(item)
|
47
50
|
if item.is_a?String or item.is_a?Symbol
|
48
|
-
return item.downcase =~
|
51
|
+
return item.downcase =~ @search
|
49
52
|
elsif item.is_a?Hash
|
50
53
|
%w(title artist album).each do |key|
|
51
|
-
return true if
|
54
|
+
return true if comp(item[key])
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
58
|
false
|
56
59
|
end
|
57
60
|
|
58
|
-
def
|
59
|
-
|
60
|
-
@search = search
|
61
|
-
@current = 0
|
62
|
-
@result = @source.size.times.select {|i| self.comp(@source[i], search) }
|
63
|
-
end
|
61
|
+
def next(*a) @direction == :up ? search_up(*a): search_down(*a) end
|
62
|
+
def prev(*a) @direction == :up ? search_down(*a) : search_up(*a) end
|
64
63
|
|
65
|
-
def
|
66
|
-
|
67
|
-
def prev(p) @direction == :up ? search_down(p) : search_up(p) end
|
64
|
+
def search_up(current_pos, source)
|
65
|
+
start_pos = (current_pos - 1).clamp(0, source.size)
|
68
66
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
)
|
67
|
+
start_pos.downto(0).each do |i|
|
68
|
+
return i if comp(source[i])
|
69
|
+
end
|
73
70
|
|
74
|
-
|
71
|
+
source.size
|
75
72
|
end
|
76
73
|
|
77
|
-
def search_down(
|
78
|
-
|
79
|
-
|
80
|
-
)
|
74
|
+
def search_down(current_pos, source)
|
75
|
+
start_pos = (current_pos + 1).clamp(0, source.size)
|
76
|
+
|
77
|
+
start_pos.upto(source.size).each do |i|
|
78
|
+
return i if comp(source[i])
|
79
|
+
end
|
81
80
|
|
82
|
-
|
81
|
+
0
|
83
82
|
end
|
84
83
|
end
|
85
84
|
|
@@ -96,14 +95,13 @@ module UI
|
|
96
95
|
@selection = ListSelector.new
|
97
96
|
end
|
98
97
|
|
99
|
-
def search_next; self.selected=(@search.next(@selected)
|
100
|
-
def search_prev; self.selected=(@search.prev(@selected)
|
101
|
-
def search_up; self.search_start(:up)
|
102
|
-
def search_down; self.search_start(:down)
|
98
|
+
def search_next; self.selected=(@search.next(@selected, @list)) end
|
99
|
+
def search_prev; self.selected=(@search.prev(@selected, @list)) end
|
100
|
+
def search_up; self.search_start(:up) end
|
101
|
+
def search_down; self.search_start(:down) end
|
103
102
|
def search_start(direction)
|
104
103
|
UI::Input.readline(@pos, @size.update(height: 1), prompt: '> ', add_hist: true) do |result|
|
105
104
|
if result
|
106
|
-
@search.source=(@list)
|
107
105
|
@search.direction=(direction)
|
108
106
|
@search.search=(result)
|
109
107
|
search_next
|
@@ -163,8 +161,11 @@ module UI
|
|
163
161
|
def list=(list)
|
164
162
|
with_lock do
|
165
163
|
@list = list
|
164
|
+
|
166
165
|
@cursor = @selected = 0
|
167
166
|
self.selected=(0)
|
167
|
+
self.force_cursorpos(0)
|
168
|
+
|
168
169
|
want_redraw
|
169
170
|
end
|
170
171
|
end
|
@@ -178,7 +179,7 @@ module UI
|
|
178
179
|
|
179
180
|
self.lock
|
180
181
|
|
181
|
-
old_cursor, new_cursor = @cursor, @cursor + @selected - old_selected
|
182
|
+
old_cursor, new_cursor = @cursor, @cursor + (@selected - old_selected)
|
182
183
|
|
183
184
|
if new_cursor.between?(0, @size.height - 1)
|
184
185
|
# new selected item resides in current screen,
|
@@ -189,7 +190,7 @@ module UI
|
|
189
190
|
return want_redraw if @selection.started?
|
190
191
|
|
191
192
|
write_at(old_cursor); render(old_selected)
|
192
|
-
write_at(new_cursor); render(
|
193
|
+
write_at(new_cursor); render(@selected, selected: true)
|
193
194
|
_check
|
194
195
|
want_refresh
|
195
196
|
elsif (new_cursor.between?(-(@size.height - 1), (2 * @size.height - 1)))
|
@@ -145,6 +145,9 @@ module UI
|
|
145
145
|
super(**opts)
|
146
146
|
@win = ICurses.newwin(@size.height, @size.width, @pos.y, @pos.x)
|
147
147
|
@win.keypad(true)
|
148
|
+
@win.idlok(true)
|
149
|
+
@win.leaveok(true)
|
150
|
+
@win.bkgdset(UI::Colors.init_pair_cached(:default, :default))
|
148
151
|
end
|
149
152
|
|
150
153
|
def layout
|
@@ -154,6 +157,10 @@ module UI
|
|
154
157
|
end
|
155
158
|
|
156
159
|
def refresh
|
160
|
+
@win.refresh
|
161
|
+
end
|
162
|
+
|
163
|
+
def noutrefresh
|
157
164
|
@win.noutrefresh
|
158
165
|
end
|
159
166
|
end
|
@@ -164,6 +171,10 @@ module UI
|
|
164
171
|
def initialize(**opts)
|
165
172
|
super(**opts)
|
166
173
|
@win = ICurses.newpad(@size.height, @size.width)
|
174
|
+
@win.keypad(true)
|
175
|
+
@win.idlok(true)
|
176
|
+
@win.leaveok(true)
|
177
|
+
@win.bkgdset(UI::Colors.init_pair_cached(:default, :default))
|
167
178
|
@pad_minrow = @pad_mincol = 0
|
168
179
|
end
|
169
180
|
|
@@ -230,6 +241,14 @@ module UI
|
|
230
241
|
end
|
231
242
|
|
232
243
|
def refresh
|
244
|
+
@win.prefresh(
|
245
|
+
@pad_minrow, @pad_mincol,
|
246
|
+
@pos.y, @pos.x,
|
247
|
+
@pos.y + @size.height - 1, @pos.x + @size.width - 1
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
251
|
+
def noutrefresh
|
233
252
|
@win.pnoutrefresh(
|
234
253
|
@pad_minrow, @pad_mincol,
|
235
254
|
@pos.y, @pos.x,
|
data/lib/ektoplayer/ui.rb
CHANGED
@@ -27,7 +27,7 @@ module UI
|
|
27
27
|
@@widget = nil
|
28
28
|
|
29
29
|
%w(initscr cbreak noecho start_color use_default_colors).
|
30
|
-
each
|
30
|
+
each(&ICurses.method(:send))
|
31
31
|
ICurses.mousemask(ICurses::ALL_MOUSE_EVENTS | ICurses::REPORT_MOUSE_POSITION)
|
32
32
|
ICurses.stdscr.keypad(true)
|
33
33
|
UI::Colors.start
|
@@ -50,11 +50,6 @@ module UI
|
|
50
50
|
widget
|
51
51
|
end
|
52
52
|
|
53
|
-
#def self.getch(timeout=-1)
|
54
|
-
# ICurses.stdscr.timeout(timeout)
|
55
|
-
# UI::Input::KEYMAP_WORKAROUND[ICurses.stdscr.getch]
|
56
|
-
#end
|
57
|
-
|
58
53
|
def self.update_screen(force_redraw=false, force_resize=false)
|
59
54
|
@@updating ||= Mutex.new
|
60
55
|
@@want_resize ||= false
|
@@ -97,12 +92,9 @@ module UI
|
|
97
92
|
KEYMAP_WORKAROUND.default_proc = proc { |h,k| k }
|
98
93
|
KEYMAP_WORKAROUND.freeze
|
99
94
|
|
100
|
-
#def self.getch(timeout=-1)
|
101
|
-
# KEYMAP_WORKAROUND[@@widget.getch(timeout)]
|
102
|
-
#end
|
103
|
-
|
104
95
|
def self.start_loop
|
105
96
|
@@readline_obj ||= ReadlineWindow.new
|
97
|
+
inactive = 0
|
106
98
|
|
107
99
|
loop do
|
108
100
|
unless @@readline_obj.active?
|
@@ -112,14 +104,20 @@ module UI
|
|
112
104
|
begin
|
113
105
|
UI::Canvas.widget.win.keypad(true)
|
114
106
|
|
115
|
-
if (c = UI::Canvas.widget.win.getch1(
|
107
|
+
if (c = (UI::Canvas.widget.win.getch1(500).ord rescue -1)) > -1
|
108
|
+
inactive = 0
|
109
|
+
|
116
110
|
if c == ICurses::KEY_MOUSE
|
117
111
|
if c = ICurses.getmouse
|
118
112
|
UI::Canvas.widget.mouse_click(c)
|
119
113
|
end
|
120
114
|
else
|
121
|
-
|
122
|
-
|
115
|
+
UI::Canvas.widget.key_press(KEYMAP_WORKAROUND[c])
|
116
|
+
end
|
117
|
+
else
|
118
|
+
if (inactive += 1) > 40
|
119
|
+
s = STDIN.readpartial(10)
|
120
|
+
ICurses.ungetch(s[0].ord) if s.size == 1
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
@@ -133,7 +131,7 @@ module UI
|
|
133
131
|
win = UI::Canvas.widget.win
|
134
132
|
win.keypad(false)
|
135
133
|
@@readline_obj.redraw
|
136
|
-
next unless (c = (win.getch1(100).ord rescue -1)) >
|
134
|
+
next unless (c = (win.getch1(100).ord rescue -1)) > -1
|
137
135
|
|
138
136
|
if c == 10 or c == 4
|
139
137
|
@@readline_obj.feed(?\n.ord)
|
@@ -142,16 +140,14 @@ module UI
|
|
142
140
|
|
143
141
|
if c == 27 # pass 3-character escape sequence
|
144
142
|
win.timeout(5)
|
145
|
-
if (c = (win.getch.ord rescue -1)) >
|
143
|
+
if (c = (win.getch.ord rescue -1)) > -1
|
146
144
|
@@readline_obj.feed(c)
|
147
|
-
if (c = (win.getch.ord rescue -1)) >
|
145
|
+
if (c = (win.getch.ord rescue -1)) > -1
|
148
146
|
@@readline_obj.feed(c)
|
149
147
|
end
|
150
148
|
end
|
151
149
|
end
|
152
150
|
end
|
153
|
-
#rescue
|
154
|
-
# getch() returned something weird that could not be chr()d
|
155
151
|
end while @@readline_obj.active?
|
156
152
|
end
|
157
153
|
end
|
@@ -168,24 +164,27 @@ module UI
|
|
168
164
|
def initialize
|
169
165
|
Readline.input, @readline_in_write = IO.pipe
|
170
166
|
Readline.output = File.open(File::NULL, ?w)
|
167
|
+
@window = ICurses.newwin(0,0,0,0)
|
171
168
|
@thread = nil
|
172
169
|
end
|
173
170
|
|
174
171
|
def active?; @thread; end
|
175
172
|
|
176
173
|
def redraw
|
177
|
-
|
174
|
+
@window.resize(@size.height, @size.width)
|
175
|
+
@window.mvwin(@pos.y, @pos.x)
|
178
176
|
@window.erase
|
179
177
|
buffer = @prompt + Readline.line_buffer.to_s
|
180
178
|
@window.addstr(buffer[(buffer.size - @size.width).clamp(0, buffer.size)..-1])
|
181
179
|
@window.move(0, Readline.point + @prompt.size)
|
182
180
|
@window.refresh
|
181
|
+
rescue
|
182
|
+
nil
|
183
183
|
end
|
184
184
|
|
185
185
|
def readline(pos, size, prompt: '', add_hist: false, &block)
|
186
186
|
@thread ||= Thread.new do
|
187
|
-
@size, @prompt = size, prompt
|
188
|
-
@window = ICurses.newwin(size.height, size.width, pos.y, pos.x)
|
187
|
+
@size, @pos, @prompt = size, pos, prompt
|
189
188
|
|
190
189
|
begin
|
191
190
|
Readline.set_screen_size(size.height, size.width)
|
@@ -194,7 +193,7 @@ module UI
|
|
194
193
|
block.(Readline.readline(prompt, add_hist))
|
195
194
|
ensure
|
196
195
|
@window.clear
|
197
|
-
@
|
196
|
+
@thread = nil
|
198
197
|
UI::Canvas.update_screen(true)
|
199
198
|
end
|
200
199
|
end
|
@@ -308,7 +307,7 @@ module ICurses
|
|
308
307
|
def size; UI::Size.new(height: maxy, width: maxx) end
|
309
308
|
|
310
309
|
def cursor=(new)
|
311
|
-
move(new.y, new.x)
|
310
|
+
move(new.y, new.x) #or warn "Could not set cursor: #{new} #{size}"
|
312
311
|
end
|
313
312
|
|
314
313
|
def pos=(new)
|
data/lib/ektoplayer/updater.rb
CHANGED
@@ -9,9 +9,8 @@ module Ektoplayer
|
|
9
9
|
FREE_MUSIC_URL = "#{MAIN_URL}/section/free-music".freeze
|
10
10
|
|
11
11
|
class DatabaseUpdater
|
12
|
-
ALBUM_STR_TAGS = Set.new(%w(url title date
|
13
|
-
description download_count rating votes
|
14
|
-
released_by released_by_url posted_by posted_by_url).map(&:to_sym)).freeze
|
12
|
+
ALBUM_STR_TAGS = Set.new(%w(url title date cover_url
|
13
|
+
description download_count rating votes).map(&:to_sym)).freeze
|
15
14
|
|
16
15
|
TRACK_STR_TAGS = Set.new(%w(url number title remix artist bpm).map(&:to_sym)).freeze
|
17
16
|
|
@@ -33,7 +32,7 @@ module Ektoplayer
|
|
33
32
|
queue << Thread.new do
|
34
33
|
results << BrowsePage.new(url)
|
35
34
|
queue.pop # unregister our thread
|
36
|
-
end.priority
|
35
|
+
end.priority
|
37
36
|
|
38
37
|
if results.size > 40
|
39
38
|
@db.transaction
|
@@ -6,8 +6,13 @@ module Ektoplayer
|
|
6
6
|
class Browser < UI::ListWidget
|
7
7
|
def initialize(**opts)
|
8
8
|
super(**opts)
|
9
|
-
|
10
|
-
|
9
|
+
if ICurses.colors == 256
|
10
|
+
f = Config[:'playlist.format_256']
|
11
|
+
else
|
12
|
+
f = Config[:'playlist.format']
|
13
|
+
end
|
14
|
+
|
15
|
+
self.item_renderer=(TrackRenderer.new(width: @size.width, format: f))
|
11
16
|
end
|
12
17
|
|
13
18
|
def attach(browser)
|
@@ -5,7 +5,10 @@ require_relative '../theme'
|
|
5
5
|
module Ektoplayer
|
6
6
|
module Views
|
7
7
|
class Help < UI::Pad
|
8
|
-
def draw
|
8
|
+
def draw;
|
9
|
+
end
|
10
|
+
|
11
|
+
def layout
|
9
12
|
self.pad_size=(UI::Size.new(
|
10
13
|
height: (Bindings.bindings.values.map(&:size).sum +
|
11
14
|
Bindings.bindings.size * 2),
|
@@ -32,7 +35,7 @@ module Ektoplayer
|
|
32
35
|
@win.mvaddstr(@win.cury, 18, name.to_s)
|
33
36
|
|
34
37
|
@win.attrset(Theme[:'help.command_desc'])
|
35
|
-
@win.mvaddstr(@win.cury,
|
38
|
+
@win.mvaddstr(@win.cury, 45, Bindings.commands[name.to_sym])
|
36
39
|
|
37
40
|
@win.next_line
|
38
41
|
end
|
@@ -20,7 +20,7 @@ module Ektoplayer
|
|
20
20
|
player, playlist, trackloader, database
|
21
21
|
|
22
22
|
Thread.new do
|
23
|
-
loop { sleep 1;
|
23
|
+
loop { sleep 1; draw if visible? }
|
24
24
|
end.priority=(-10)
|
25
25
|
end
|
26
26
|
|
@@ -59,20 +59,18 @@ module Ektoplayer
|
|
59
59
|
def draw_download(file, percent, error)
|
60
60
|
@win.attrset(Theme[:'info.download.file'])
|
61
61
|
@win.mvaddstr(@win.cury + 1, START_TAG, file)
|
62
|
+
@win.addch(32) # ' '
|
62
63
|
|
63
64
|
@win.attrset(Theme[:'info.download.percent'])
|
64
|
-
@win.addstr(
|
65
|
+
@win.addstr(percent.to_s)
|
65
66
|
|
66
67
|
if error
|
68
|
+
@win.addch(32) # ' '
|
67
69
|
@win.attrset(Theme[:'info.download.error'])
|
68
|
-
@win.addstr(
|
70
|
+
@win.addstr(error.to_s)
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
def get_cover_url(album)
|
73
|
-
"#{Application::EKTOPLAZM_COVER_BASE_URL}/#{album}"
|
74
|
-
end
|
75
|
-
|
76
74
|
def draw
|
77
75
|
return unless @player
|
78
76
|
|
@@ -87,7 +85,7 @@ module Ektoplayer
|
|
87
85
|
|
88
86
|
if @track = (@playlist[@playlist.current_playing] rescue nil)
|
89
87
|
draw_heading('Current track')
|
90
|
-
draw_tag('Number',
|
88
|
+
draw_tag('Number', '%0.2d' % @track['number'])
|
91
89
|
draw_tag('Title', @track['title'])
|
92
90
|
draw_tag('Remix', @track['remix']) if @track['remix']
|
93
91
|
draw_tag('Artist', @track['artist'])
|
@@ -97,22 +95,18 @@ module Ektoplayer
|
|
97
95
|
@win.next_line
|
98
96
|
|
99
97
|
draw_heading('Current album')
|
100
|
-
|
98
|
+
|
99
|
+
draw_tag('Album')
|
100
|
+
draw_url(Application.album_url(@track['album_url']), @track['album'])
|
101
101
|
draw_tag('Artist', @track['album__artist']) if @track['album_artist']
|
102
102
|
draw_tag('Date', @track['date'])
|
103
103
|
|
104
|
-
if url = @track['released_by_url']
|
105
|
-
draw_tag('Released by'); draw_url(url, @track['released_by'])
|
106
|
-
end
|
107
|
-
|
108
|
-
if url = @track['posted_by_url']
|
109
|
-
draw_tag('Posted by'); draw_url(url, @track['posted_by'])
|
110
|
-
end
|
111
|
-
|
112
104
|
draw_tag('Styles', @track['styles'].gsub(?,, ', '))
|
113
105
|
draw_tag('Downloads', @track['download_count'])
|
114
|
-
draw_tag('Rating',
|
115
|
-
draw_tag('Cover')
|
106
|
+
draw_tag('Rating', '%0.2d%% (%d Votes)' % [@track['rating'], @track['votes']])
|
107
|
+
draw_tag('Cover')
|
108
|
+
draw_url(Application.cover_url(@track['cover_url']), 'Cover')
|
109
|
+
|
116
110
|
@win.next_line
|
117
111
|
|
118
112
|
# -- description
|
@@ -123,14 +117,14 @@ module Ektoplayer
|
|
123
117
|
|
124
118
|
Nokogiri::HTML("<p>#{@track['description']}</p>").css(?p).each do |p|
|
125
119
|
p.children.each do |element|
|
126
|
-
if element[
|
120
|
+
if element['href']
|
127
121
|
if (line_length += element.text.size) > wrap_length
|
128
122
|
@win.move(@win.cury + 1, START_TAG)
|
129
123
|
line_length = START_TAG
|
130
124
|
end
|
131
125
|
|
132
|
-
draw_url(element[:href], element.text.strip)
|
133
126
|
@win.addch(32) # ' '
|
127
|
+
draw_url(element['href'], element.text.strip)
|
134
128
|
else
|
135
129
|
element.text.split(' ').each do |text|
|
136
130
|
if (line_length += text.size) > wrap_length
|
@@ -138,10 +132,10 @@ module Ektoplayer
|
|
138
132
|
line_length = START_TAG
|
139
133
|
end
|
140
134
|
|
135
|
+
@win.addch(32) # ' '
|
141
136
|
@win.attrset(Theme[:'info.description'])
|
142
137
|
@win.mv_left(1) if text =~ /^[\.,:;]$/
|
143
138
|
@win << text
|
144
|
-
@win.addch(32) # ' '
|
145
139
|
end
|
146
140
|
end
|
147
141
|
end
|
@@ -155,9 +149,8 @@ module Ektoplayer
|
|
155
149
|
draw_heading('Downloads')
|
156
150
|
@trackloader.downloads.each do |dl|
|
157
151
|
name = File.basename(dl.filename)
|
158
|
-
percent =
|
159
|
-
percent
|
160
|
-
draw_download(name, ?( + percent + '%)', dl.error)
|
152
|
+
percent = '%0.2f' % dl.progress
|
153
|
+
draw_download(name, "(#{percent}%)", dl.error)
|
161
154
|
end
|
162
155
|
@win.next_line
|
163
156
|
end
|
@@ -166,12 +159,14 @@ module Ektoplayer
|
|
166
159
|
draw_info('Version', Application::VERSION)
|
167
160
|
draw_info('Tracks in database', @database.track_count)
|
168
161
|
draw_info('Albums in database', @database.album_count)
|
169
|
-
draw_info('
|
170
|
-
draw_info('
|
162
|
+
draw_info('Tracks in playlist', @playlist.size)
|
163
|
+
draw_info('Cache dir size', '%dMB' % (Dir.size(Config[:cache_dir]) / (1024 ** 2) rescue 0))
|
164
|
+
draw_info('Archive dir size', '%dMB' % (Dir.size(Config[:archive_dir]) / (1024 ** 2) rescue 0))
|
171
165
|
draw_info('Ektoplazm URL'); draw_url(Application::EKTOPLAZM_URL)
|
172
166
|
draw_info('Github URL'); draw_url(Application::GITHUB_URL)
|
173
167
|
|
174
168
|
self.pad_size=(@size.update(height: [@win.cursor.y + 2, @size.height].max))
|
169
|
+
noutrefresh
|
175
170
|
end
|
176
171
|
end
|
177
172
|
end
|
@@ -28,23 +28,9 @@ module Ektoplayer
|
|
28
28
|
with_lock { @track = t; want_redraw }
|
29
29
|
end
|
30
30
|
|
31
|
-
def length=(l)
|
32
|
-
return if @length == l.to_i
|
33
|
-
@length = l.to_i
|
34
|
-
draw_position_and_length
|
35
|
-
end
|
36
|
-
|
37
|
-
def position=(p)
|
38
|
-
return if @position == p.to_i
|
39
|
-
@position = p.to_i
|
40
|
-
draw_position_and_length
|
41
|
-
end
|
42
|
-
|
43
31
|
def draw_position_and_length
|
44
|
-
return unless visible?
|
45
32
|
@win.attrset(Theme[:'playinginfo.position'])
|
46
33
|
@win.mvaddstr(0, 0, "[#{Common::to_time(@position)}/#{Common::to_time(@length)}]")
|
47
|
-
@win.noutrefresh
|
48
34
|
end
|
49
35
|
|
50
36
|
def attach(playlist, player)
|
@@ -53,15 +39,22 @@ module Ektoplayer
|
|
53
39
|
player.events.on(:play) { self.playing! }
|
54
40
|
|
55
41
|
player.events.on(:position_change) do
|
56
|
-
|
57
|
-
|
42
|
+
old_pos, old_length = @position, @length
|
43
|
+
@position = player.position.to_i
|
44
|
+
@length = player.length.to_i
|
45
|
+
|
46
|
+
if old_pos != @position or old_length != @length
|
47
|
+
if visible?
|
48
|
+
draw_position_and_length
|
49
|
+
refresh
|
50
|
+
end
|
51
|
+
end
|
58
52
|
end
|
59
53
|
|
60
54
|
playlist.events.on(:current_changed) {
|
61
55
|
self.track=(playlist[playlist.current_playing])
|
62
56
|
}
|
63
57
|
|
64
|
-
# TODO: move mouse?
|
65
58
|
self.mouse.on(ICurses::BUTTON1_CLICKED) do |mevent|
|
66
59
|
player.toggle
|
67
60
|
end
|
@@ -88,9 +81,17 @@ module Ektoplayer
|
|
88
81
|
def draw
|
89
82
|
@win.erase
|
90
83
|
draw_position_and_length
|
84
|
+
|
85
|
+
if ICurses.colors == 256
|
86
|
+
top_format = Config[:'playinginfo.format_top_256']
|
87
|
+
bottom_format = Config[:'playinginfo.format_bottom_256']
|
88
|
+
else
|
89
|
+
top_format = Config[:'playinginfo.format_top']
|
90
|
+
bottom_format = Config[:'playinginfo.format_bottom']
|
91
|
+
end
|
91
92
|
|
92
93
|
if @track
|
93
|
-
fill(
|
94
|
+
fill(top_format).each_with_index do |fmt,i|
|
94
95
|
@win.center(fmt[:sum]) if i == 0
|
95
96
|
@win.attrset(UI::Colors.set(nil, *fmt[:curses_attrs]))
|
96
97
|
@win << fmt[:filled]
|
@@ -101,7 +102,7 @@ module Ektoplayer
|
|
101
102
|
|
102
103
|
@win.next_line
|
103
104
|
|
104
|
-
fill(
|
105
|
+
fill(bottom_format).each_with_index do |fmt,i|
|
105
106
|
@win.center(fmt[:sum]) if i == 0
|
106
107
|
@win.attrset(UI::Colors.set(nil, *fmt[:curses_attrs]))
|
107
108
|
@win << fmt[:filled]
|
@@ -8,9 +8,14 @@ module Ektoplayer
|
|
8
8
|
class Playlist < UI::ListWidget
|
9
9
|
def initialize(**opts)
|
10
10
|
super(**opts)
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
|
12
|
+
if ICurses.colors == 256
|
13
|
+
f = Config[:'playlist.format_256']
|
14
|
+
else
|
15
|
+
f = Config[:'playlist.format']
|
16
|
+
end
|
17
|
+
|
18
|
+
self.item_renderer=(TrackRenderer.new(width: @size.width, format: f))
|
14
19
|
end
|
15
20
|
|
16
21
|
def attach(playlist)
|