ektoplayer 0.1.12 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|