ektoplayer 0.1.6 → 0.1.11
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/README.md +26 -12
- data/lib/ektoplayer/application.rb +6 -5
- data/lib/ektoplayer/bindings.rb +61 -55
- data/lib/ektoplayer/common.rb +19 -6
- data/lib/ektoplayer/compat.rb +3 -3
- data/lib/ektoplayer/config.rb +1 -11
- data/lib/ektoplayer/controllers/browser.rb +7 -5
- data/lib/ektoplayer/controllers/help.rb +1 -1
- data/lib/ektoplayer/controllers/info.rb +1 -1
- data/lib/ektoplayer/controllers/playlist.rb +24 -12
- data/lib/ektoplayer/icurses.rb +21 -0
- data/lib/ektoplayer/icurses/curses.rb +53 -0
- data/lib/ektoplayer/icurses/ffi_ncurses.rb +69 -0
- data/lib/ektoplayer/icurses/ncurses.rb +79 -0
- data/lib/ektoplayer/icurses/ncursesw.rb +1 -0
- data/lib/ektoplayer/icurses/sugar.rb +65 -0
- data/lib/ektoplayer/icurses/test.rb +99 -0
- data/lib/ektoplayer/models/player.rb +2 -2
- data/lib/ektoplayer/{mp3player.rb → players/mpg_portaudio_player.rb} +3 -3
- data/lib/ektoplayer/players/mpg_wrapper_player.rb +107 -0
- data/lib/ektoplayer/theme.rb +1 -6
- data/lib/ektoplayer/ui.rb +100 -129
- data/lib/ektoplayer/ui/colors.rb +14 -14
- data/lib/ektoplayer/ui/widgets.rb +4 -4
- data/lib/ektoplayer/ui/widgets/labelwidget.rb +1 -1
- data/lib/ektoplayer/ui/widgets/listwidget.rb +115 -46
- data/lib/ektoplayer/views/help.rb +7 -10
- data/lib/ektoplayer/views/info.rb +29 -38
- data/lib/ektoplayer/views/mainwindow.rb +2 -5
- data/lib/ektoplayer/views/playinginfo.rb +15 -20
- data/lib/ektoplayer/views/progressbar.rb +30 -10
- data/lib/ektoplayer/views/splash.rb +24 -25
- data/lib/ektoplayer/views/tabbar.rb +6 -5
- data/lib/ektoplayer/views/trackrenderer.rb +20 -14
- metadata +15 -47
- data/lib/ektoplayer/views/volumemeter.rb +0 -76
@@ -10,7 +10,7 @@ module Ektoplayer
|
|
10
10
|
|
11
11
|
register = view_operations.with_register('playlist.')
|
12
12
|
%w(up down page_up page_down top bottom
|
13
|
-
search_up search_down search_next search_prev).
|
13
|
+
search_up search_down search_next search_prev toggle_selection).
|
14
14
|
each { |op| register.(op, &@view.method(op)) }
|
15
15
|
|
16
16
|
register.(:play) do
|
@@ -18,24 +18,36 @@ module Ektoplayer
|
|
18
18
|
end
|
19
19
|
|
20
20
|
register.(:reload) do
|
21
|
-
|
21
|
+
view.get_selection.each do |index|
|
22
|
+
operations.send(:'playlist.reload', index)
|
23
|
+
end
|
22
24
|
end
|
23
25
|
|
24
26
|
register.(:download_album) do
|
25
|
-
|
27
|
+
view.get_selection.each do |index|
|
28
|
+
operations.send(:'playlist.download_album', index)
|
29
|
+
end
|
26
30
|
end
|
27
31
|
|
28
32
|
register.(:delete) do
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
view.with_lock do
|
34
|
+
old_cursor, selection = view.cursor, view.get_selection
|
35
|
+
|
36
|
+
selection.each do
|
37
|
+
operations.send(:'playlist.delete', selection[0])
|
38
|
+
end
|
39
|
+
|
40
|
+
view.selected=(selection[0])
|
41
|
+
view.force_cursorpos(old_cursor)
|
42
|
+
end
|
33
43
|
end
|
34
44
|
|
35
45
|
register.(:goto_current) do
|
36
|
-
|
37
|
-
|
38
|
-
|
46
|
+
view.with_lock do
|
47
|
+
if index = playlist.current_playing
|
48
|
+
view.selected=(index)
|
49
|
+
view.center()
|
50
|
+
end
|
39
51
|
end
|
40
52
|
end
|
41
53
|
|
@@ -43,14 +55,14 @@ module Ektoplayer
|
|
43
55
|
view.mouse.on(65536) do view.up(5) end
|
44
56
|
view.mouse.on(2097152) do view.down(5) end
|
45
57
|
|
46
|
-
[
|
58
|
+
[ICurses::BUTTON1_CLICKED, ICurses::BUTTON2_CLICKED].
|
47
59
|
each do |button|
|
48
60
|
view.mouse.on(button) do |mevent|
|
49
61
|
view.select_from_cursorpos(mevent.y)
|
50
62
|
end
|
51
63
|
end
|
52
64
|
|
53
|
-
[
|
65
|
+
[ICurses::BUTTON1_DOUBLE_CLICKED, ICurses::BUTTON3_CLICKED].each do |btn|
|
54
66
|
view.mouse.on(btn) do |mevent|
|
55
67
|
view.select_from_cursorpos(mevent.y)
|
56
68
|
view_operations.send('playlist.play')
|
@@ -0,0 +1,21 @@
|
|
1
|
+
%w(ffi-ncurses ncursesw ncurses curses).each do |f|
|
2
|
+
begin
|
3
|
+
$USING_CURSES = f
|
4
|
+
require_relative "icurses/#{f}"
|
5
|
+
break
|
6
|
+
rescue LoadError
|
7
|
+
$USING_CURSES = nil
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
fail %{
|
12
|
+
No interface for ncurses found. Please install one of the following gems
|
13
|
+
- curses
|
14
|
+
- ffi-ncurses
|
15
|
+
- ncurses-ruby
|
16
|
+
- ncursesw
|
17
|
+
|
18
|
+
Maybe your distribution ships one of these already as a package.
|
19
|
+
} unless $USING_CURSES
|
20
|
+
|
21
|
+
require_relative 'icurses/sugar'
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'curses'
|
2
|
+
|
3
|
+
module Curses
|
4
|
+
def Curses.initscr; init_screen end
|
5
|
+
def Curses.endwin; close_screen end
|
6
|
+
|
7
|
+
def Curses.newwin(*a) Curses::Window.new(*a) end
|
8
|
+
def Curses.newpad(*a) Curses::Pad.new(*a) end
|
9
|
+
|
10
|
+
class Window
|
11
|
+
def mvaddstr(y, x, s)
|
12
|
+
move(y, x)
|
13
|
+
addstr(s)
|
14
|
+
end
|
15
|
+
|
16
|
+
%w(curx cury maxx maxy begx begy).each do |method|
|
17
|
+
alias_method :"get#{method}", method.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
alias :timeout :timeout=
|
21
|
+
alias :notimeout :nodelay= #todo
|
22
|
+
alias :nodelay :nodelay=
|
23
|
+
|
24
|
+
alias :mvwin :move # 'fix' this Gem
|
25
|
+
def move(y, x)
|
26
|
+
setpos(y, x)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Pad < Window
|
31
|
+
alias :pnoutrefresh :refresh
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ICurses
|
36
|
+
include Curses
|
37
|
+
|
38
|
+
(Curses.public_methods - public_methods).each do |method|
|
39
|
+
define_singleton_method(method, &Curses.method(method))
|
40
|
+
end
|
41
|
+
|
42
|
+
def mousemask(mask, *a); Curses.mousemask(mask) end
|
43
|
+
module_function :mousemask
|
44
|
+
|
45
|
+
def getmouse(mevent=nil)
|
46
|
+
if mevent = Curses.getmouse()
|
47
|
+
return IMouseEvent.new(mevent)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
module_function :getmouse
|
51
|
+
|
52
|
+
IWindow = Curses::Window
|
53
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'ffi-ncurses'
|
2
|
+
|
3
|
+
module FFI::NCurses
|
4
|
+
alias_method :_newwin, :newwin
|
5
|
+
def newwin(*a)
|
6
|
+
IWindow.new(_newwin(*a))
|
7
|
+
end
|
8
|
+
module_function :newwin
|
9
|
+
|
10
|
+
alias_method :_newpad, :newpad
|
11
|
+
def newpad(*a)
|
12
|
+
IWindow.new(_newpad(*a))
|
13
|
+
end
|
14
|
+
module_function :newpad
|
15
|
+
|
16
|
+
alias_method :_stdscr, :stdscr
|
17
|
+
def stdscr
|
18
|
+
IWindow.new(_stdscr)
|
19
|
+
end
|
20
|
+
module_function :stdscr
|
21
|
+
|
22
|
+
alias_method :_mousemask, :mousemask
|
23
|
+
def mousemask(mask, *_)
|
24
|
+
_mousemask(mask, nil)
|
25
|
+
end
|
26
|
+
module_function :mousemask
|
27
|
+
|
28
|
+
alias_method :_getmouse, :getmouse
|
29
|
+
def getmouse(mevent=nil)
|
30
|
+
mevent = FFI::NCurses::Mouse::MEVENT.new
|
31
|
+
if _getmouse(mevent) > -1
|
32
|
+
return IMouseEvent.new(mevent)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
module_function :getmouse
|
36
|
+
|
37
|
+
|
38
|
+
class Window
|
39
|
+
def initialize(w)
|
40
|
+
@w = w
|
41
|
+
end
|
42
|
+
|
43
|
+
FFI::NCurses.public_methods.each do |method|
|
44
|
+
if method =~ /^(mv)?w/
|
45
|
+
define_method(method) do |*args|
|
46
|
+
FFI::NCurses.send(method, @w, *args)
|
47
|
+
end
|
48
|
+
|
49
|
+
next if method =~ /win$/
|
50
|
+
|
51
|
+
define_method(method.to_s.sub(?w, '')) do |*args|
|
52
|
+
FFI::NCurses.send(method, @w, *args)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
%w(getcurx getcury getmaxx getmaxy getbegx getbegy
|
58
|
+
keypad nodelay notimeout prefresh pnoutrefresh).each do |meth|
|
59
|
+
|
60
|
+
define_method(meth) do |*args|
|
61
|
+
FFI::NCurses.send(meth, @w, *args)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
IWindow = Window
|
67
|
+
end
|
68
|
+
|
69
|
+
ICurses = FFI::NCurses
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require $USING_CURSES
|
2
|
+
|
3
|
+
Ncurses.initscr
|
4
|
+
|
5
|
+
module Ncurses
|
6
|
+
class IWindow
|
7
|
+
def initialize(w)
|
8
|
+
@w = w
|
9
|
+
end
|
10
|
+
|
11
|
+
def getch
|
12
|
+
return Ncurses::wgetch(self)
|
13
|
+
y, x = Ncurses::getcury(self), Ncurses::getcurx(self)
|
14
|
+
c = Ncurses::wgetch(self)
|
15
|
+
Ncurses::wmove(self, y, x)
|
16
|
+
c
|
17
|
+
end
|
18
|
+
|
19
|
+
%w(getcurx getcury getmaxx getmaxy getbegx getbegy
|
20
|
+
keypad nodelay notimeout prefresh pnoutrefresh).each do |meth|
|
21
|
+
define_method(meth) do |*args|
|
22
|
+
Ncurses.send(meth, @w, *args)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Ncurses.public_methods.each do |meth|
|
27
|
+
if meth =~ /^(mv)?w/
|
28
|
+
define_method(meth) do |*args|
|
29
|
+
Ncurses.send(meth, @w, *args)
|
30
|
+
end
|
31
|
+
|
32
|
+
next if meth =~ /win$/
|
33
|
+
|
34
|
+
define_method(meth.to_s.sub(?w, '')) do |*args|
|
35
|
+
Ncurses.send(meth, @w, *args)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module ICurses
|
43
|
+
include Ncurses
|
44
|
+
|
45
|
+
def method_missing(m, *a)
|
46
|
+
Ncurses.send(m, *a)
|
47
|
+
rescue NoMethodError
|
48
|
+
Ncurses.send(m.downcase, *a)
|
49
|
+
end
|
50
|
+
module_function :method_missing
|
51
|
+
|
52
|
+
def initscr; end # do nothing
|
53
|
+
module_function :initscr
|
54
|
+
|
55
|
+
def newwin(*a)
|
56
|
+
ICurses::IWindow.new( Ncurses.newwin(*a) )
|
57
|
+
end
|
58
|
+
module_function :newwin
|
59
|
+
|
60
|
+
def newpad(*a)
|
61
|
+
ICurses::IWindow.new( Ncurses.newpad(*a) )
|
62
|
+
end
|
63
|
+
module_function :newpad
|
64
|
+
|
65
|
+
def mousemask(mask, *_)
|
66
|
+
Ncurses.mousemask(mask, [])
|
67
|
+
end
|
68
|
+
module_function :mousemask
|
69
|
+
|
70
|
+
def getmouse(mevent=nil)
|
71
|
+
mevent = Ncurses::MEVENT.new
|
72
|
+
if Ncurses.getmouse(mevent) > -1
|
73
|
+
return IMouseEvent.new(mevent)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
module_function :getmouse
|
77
|
+
|
78
|
+
IWindow = Ncurses::IWindow
|
79
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'ncurses'
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module ICurses
|
2
|
+
class IMouseEvent
|
3
|
+
attr_accessor :x, :y, :z, :bstate
|
4
|
+
|
5
|
+
def initialize(mouse_event=nil)
|
6
|
+
from_mouse_event!(mouse_event)
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key) send(key) end
|
10
|
+
def []=(key, value) send("#{key}=", value) end
|
11
|
+
|
12
|
+
def from_mouse_event!(m)
|
13
|
+
@x, @y, @z, @bstate = m.x, m.y, m.z, m.bstate
|
14
|
+
rescue
|
15
|
+
@x, @y, @z, @bstate = m[:x], m[:y], m[:z], m[:bstate]
|
16
|
+
rescue
|
17
|
+
@x= @y= @z= @bstate = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def update!(x: nil, y: nil, z: nil, bstate: nil)
|
21
|
+
@x = x if x
|
22
|
+
@y = y if y
|
23
|
+
@z = z if z
|
24
|
+
@bstate = (bstate or @bstate)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ICurses
|
30
|
+
%w(lines cols colors init_pair color_pair).each do |meth|
|
31
|
+
meth_up = meth.upcase
|
32
|
+
|
33
|
+
if not respond_to? meth
|
34
|
+
alias_method(meth, meth_up) rescue (
|
35
|
+
define_method(meth) do |*args|
|
36
|
+
method_missing(meth_up, *args)
|
37
|
+
end
|
38
|
+
)
|
39
|
+
|
40
|
+
module_function(meth)
|
41
|
+
elsif not respond_to? meth_up
|
42
|
+
alias_method(meth_up, meth) rescue (
|
43
|
+
define_method(meth_up) do |*args|
|
44
|
+
method_missing(meth, *args)
|
45
|
+
end
|
46
|
+
)
|
47
|
+
module_function(meth_up)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class IWindow
|
52
|
+
unless respond_to? :<<
|
53
|
+
alias_method(:<<, :addstr)
|
54
|
+
end
|
55
|
+
|
56
|
+
%w(curx cury maxx maxy begx begy).each do |meth|
|
57
|
+
full = 'get' + meth
|
58
|
+
if not respond_to? meth
|
59
|
+
alias_method(meth, full)
|
60
|
+
elsif not respond_to? full
|
61
|
+
alias_method(full, meth)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
unless ARGV[0]
|
4
|
+
%w(curses ncurses ncursesw ffi_curses).each do |i|
|
5
|
+
puts i
|
6
|
+
fail i unless system($0, i)
|
7
|
+
end
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
|
11
|
+
$USING_CURSES = ARGV[0]
|
12
|
+
require_relative ARGV[0]
|
13
|
+
require_relative 'sugar'
|
14
|
+
|
15
|
+
begin
|
16
|
+
warn 'call: initscr'
|
17
|
+
ICurses.initscr
|
18
|
+
|
19
|
+
warn 'call: stdscr'
|
20
|
+
s = ICurses.stdscr
|
21
|
+
warn 'call: stdscr.clear, stdscr.refresh'
|
22
|
+
s.clear; s.refresh
|
23
|
+
|
24
|
+
warn 'call: newwin(0,0,0,0)'
|
25
|
+
w = ICurses.newwin(0,0,0,0)
|
26
|
+
warn 'call: win.erase'
|
27
|
+
w.erase
|
28
|
+
|
29
|
+
warn 'call: win.addstr, win.mvaddstr, win.move, win.getcurx, win.getcury'
|
30
|
+
w.addstr(ARGV[0])
|
31
|
+
w.mvaddstr(1,0, 'test 1')
|
32
|
+
w.move(2,0);
|
33
|
+
w.addstr('test 2')
|
34
|
+
x, y = w.getcurx, w.getcury
|
35
|
+
w.mvaddstr(y + 1, 0, 'test 3')
|
36
|
+
|
37
|
+
warn 'call win.getch'
|
38
|
+
w.getch
|
39
|
+
|
40
|
+
warn 'call: LINES COLS'
|
41
|
+
w.addstr("my term is #{ICurses.LINES} lines and #{ICurses.COLS} cols")
|
42
|
+
|
43
|
+
warn 'call: win.resize'
|
44
|
+
w.resize(50, 30)
|
45
|
+
|
46
|
+
warn 'call: win.refresh, win.noutrefresh'
|
47
|
+
w.refresh; w.noutrefresh
|
48
|
+
|
49
|
+
warn 'call: keypad(true)'
|
50
|
+
w.keypad(true)
|
51
|
+
|
52
|
+
warn 'call: timeout(-1)'
|
53
|
+
w.timeout(1000)
|
54
|
+
|
55
|
+
warn 'call: nodelay(false)'
|
56
|
+
w.nodelay(false)
|
57
|
+
|
58
|
+
warn 'call: notimeout(true)'
|
59
|
+
w.notimeout(true)
|
60
|
+
|
61
|
+
warn 'call: curs_set, nl, nonl, echo, noecho'
|
62
|
+
ICurses.curs_set(1); ICurses.curs_set(0)
|
63
|
+
ICurses.nl; ICurses.nonl
|
64
|
+
ICurses.echo; ICurses.noecho
|
65
|
+
|
66
|
+
warn 'call: mousemask'
|
67
|
+
ICurses.mousemask(ICurses::ALL_MOUSE_EVENTS, [])
|
68
|
+
|
69
|
+
# === Colors === #
|
70
|
+
warn 'call: start_color, use_default_colors, init_pair, attron, attroff'
|
71
|
+
ICurses.start_color
|
72
|
+
ICurses.use_default_colors
|
73
|
+
ICurses.init_pair(1, ICurses::COLOR_BLACK, ICurses::COLOR_GREEN)
|
74
|
+
w.attron(ICurses.color_pair(1))
|
75
|
+
w.addstr("my term is has #{ICurses.COLORS}")
|
76
|
+
w.attroff(ICurses.color_pair(1))
|
77
|
+
|
78
|
+
# === Sugar ===
|
79
|
+
warn 'call: <<'
|
80
|
+
w << 'sugar'
|
81
|
+
|
82
|
+
loop do
|
83
|
+
sleep 0.1
|
84
|
+
warn 'call getch()'
|
85
|
+
c = w.getch
|
86
|
+
unless c
|
87
|
+
warn "empty getch"
|
88
|
+
next
|
89
|
+
end
|
90
|
+
warn "returned #{c} (#{c.ord})"
|
91
|
+
ch = c.chr rescue ''
|
92
|
+
w.addstr("#{ch}")
|
93
|
+
break if ch == ?q
|
94
|
+
end
|
95
|
+
ensure
|
96
|
+
ICurses.endwin rescue puts $!
|
97
|
+
end
|
98
|
+
|
99
|
+
exit 0
|