cmus 2.0.4.4 → 2.0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cmus-remote.rb +6 -4
- data/lib/cmus/controller.rb +151 -5
- data/lib/cmus/controller/player.rb +29 -11
- data/lib/cmus/controller/status.rb +13 -12
- data/lib/cmus/controller/toggle.rb +24 -29
- data/lib/cmus/controller/window.rb +133 -0
- data/lib/cmus/version.rb +1 -1
- metadata +3 -2
data/bin/cmus-remote.rb
CHANGED
@@ -98,9 +98,11 @@ if options[:status]
|
|
98
98
|
puts "duration #{status.duration}" if status.duration
|
99
99
|
puts "position #{status.position}" if status.position
|
100
100
|
|
101
|
-
status.
|
102
|
-
|
103
|
-
|
101
|
+
if status.song
|
102
|
+
status.song.marshal_dump.each {|name, value|
|
103
|
+
puts "tag #{name} #{value}"
|
104
|
+
}
|
105
|
+
end
|
104
106
|
|
105
107
|
status.settings.marshal_dump.each {|name, value|
|
106
108
|
puts "set #{name} #{value}"
|
@@ -110,7 +112,7 @@ end
|
|
110
112
|
|
111
113
|
if options[:raw]
|
112
114
|
ARGV.each {|command|
|
113
|
-
controller.
|
115
|
+
controller.send command
|
114
116
|
}
|
115
117
|
|
116
118
|
while line = controller.readline
|
data/lib/cmus/controller.rb
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
|
11
11
|
require 'socket'
|
12
12
|
|
13
|
+
require 'cmus/controller/window'
|
13
14
|
require 'cmus/controller/toggle'
|
14
15
|
require 'cmus/controller/player'
|
15
16
|
require 'cmus/controller/status'
|
@@ -22,9 +23,10 @@ module Cmus
|
|
22
23
|
class Controller
|
23
24
|
attr_reader :path
|
24
25
|
|
25
|
-
def initialize (path = '~/.cmus/socket')
|
26
|
-
@path
|
27
|
-
@socket
|
26
|
+
def initialize (path = '~/.cmus/socket', timeout = 0.005)
|
27
|
+
@path = File.expand_path(path)
|
28
|
+
@socket = UNIXSocket.new(@path)
|
29
|
+
@timeout = timeout
|
28
30
|
end
|
29
31
|
|
30
32
|
def respond_to_missing? (id)
|
@@ -35,16 +37,138 @@ class Controller
|
|
35
37
|
@socket.__send__ id, *args, &block
|
36
38
|
end
|
37
39
|
|
40
|
+
def send (text)
|
41
|
+
@socket.puts(text)
|
42
|
+
end
|
43
|
+
|
44
|
+
def source (path)
|
45
|
+
send "source #{File.realpath(File.expand_path(path))}"
|
46
|
+
check_for_error
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def save
|
52
|
+
send 'save'
|
53
|
+
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def quit
|
58
|
+
send 'quit'
|
59
|
+
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def set (name, value)
|
64
|
+
send "set #{name}=#{value}"
|
65
|
+
check_for_error
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def set? (name)
|
71
|
+
send "set #{name}"
|
72
|
+
|
73
|
+
if text = check_for_error
|
74
|
+
text[/=(.*?)'/, 1]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def colorscheme (name)
|
79
|
+
send "colorscheme #{name}"
|
80
|
+
check_for_error
|
81
|
+
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
38
85
|
# clear the context
|
39
86
|
def clear (context = :playlist)
|
40
|
-
|
87
|
+
send "clear -#{context.to_s[0]}"
|
88
|
+
check_for_error
|
89
|
+
|
90
|
+
self
|
41
91
|
end
|
42
92
|
|
43
93
|
# add a file to the context
|
44
94
|
def add (context = :playlist, *paths)
|
45
95
|
paths.flatten.compact.uniq.each {|path|
|
46
|
-
|
96
|
+
send "add -#{context.to_s[0]} #{File.realpath(File.expand_path(path))}"
|
97
|
+
check_for_error
|
47
98
|
}
|
99
|
+
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
def bind (context = :common, key, command)
|
104
|
+
send "bind #{context} #{key} #{command}"
|
105
|
+
check_for_error
|
106
|
+
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
def bind! (context = :common, key, command)
|
111
|
+
send "bind -f #{context} #{key} #{command}"
|
112
|
+
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
def unbind (context = :common, key)
|
117
|
+
send "unbind #{context} #{key}"
|
118
|
+
check_for_error
|
119
|
+
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
def unbind! (context = :common, key)
|
124
|
+
send "unbind -f #{context} #{key}"
|
125
|
+
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def bind? (context = :common, key)
|
130
|
+
send "showbind #{context} #{key}"
|
131
|
+
|
132
|
+
if text = check_for_error
|
133
|
+
Struct.new(:context, :key, :command).new(context, *text.split(' ')[2, 2])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def mark (filter)
|
138
|
+
send "mark #{filter}"
|
139
|
+
check_for_error
|
140
|
+
|
141
|
+
self
|
142
|
+
end
|
143
|
+
|
144
|
+
def unmark
|
145
|
+
send 'unmark'
|
146
|
+
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
150
|
+
def update_cache
|
151
|
+
send 'update-cache'
|
152
|
+
|
153
|
+
self
|
154
|
+
end
|
155
|
+
|
156
|
+
def echo (text)
|
157
|
+
send "echo #{text}"
|
158
|
+
check_for_error
|
159
|
+
|
160
|
+
self
|
161
|
+
end
|
162
|
+
|
163
|
+
def filter (filter, live = false)
|
164
|
+
send "#{'live-' if live}filter #{filter}"
|
165
|
+
check_for_error
|
166
|
+
|
167
|
+
self
|
168
|
+
end
|
169
|
+
|
170
|
+
def window
|
171
|
+
@window ||= Window.new(self)
|
48
172
|
end
|
49
173
|
|
50
174
|
# returns the toggle facilities
|
@@ -61,6 +185,28 @@ class Controller
|
|
61
185
|
def status
|
62
186
|
Status.new(self)
|
63
187
|
end
|
188
|
+
|
189
|
+
def wait_for_data (timeout = @timeout)
|
190
|
+
IO.select([@socket], nil, nil, timeout)
|
191
|
+
|
192
|
+
buffer = ""
|
193
|
+
|
194
|
+
while tmp = (@socket.read_nonblock(4096) rescue nil)
|
195
|
+
buffer << tmp
|
196
|
+
end
|
197
|
+
|
198
|
+
buffer
|
199
|
+
rescue
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
|
203
|
+
def check_for_error (data = nil)
|
204
|
+
if error = data || wait_for_data and !error.strip.empty? && error.start_with?('Error:')
|
205
|
+
raise ArgumentError, error.strip.split(/:\s*/, 2).last
|
206
|
+
end
|
207
|
+
|
208
|
+
error
|
209
|
+
end
|
64
210
|
end
|
65
211
|
|
66
212
|
end
|
@@ -20,49 +20,67 @@ class Player
|
|
20
20
|
# play the current selection or the passed file
|
21
21
|
def play (file = nil)
|
22
22
|
if file
|
23
|
-
controller.
|
23
|
+
controller.send "player-play #{File.real_path(File.expand_path(file))}"
|
24
24
|
else
|
25
|
-
controller.
|
25
|
+
controller.send 'player-play'
|
26
26
|
end
|
27
|
+
|
28
|
+
self
|
27
29
|
end
|
28
30
|
|
29
31
|
# pause the current song
|
30
32
|
def pause
|
31
|
-
return if controller.status == :paused
|
33
|
+
return self if controller.status == :paused
|
34
|
+
|
35
|
+
controller.send 'player-pause'
|
32
36
|
|
33
|
-
|
37
|
+
self
|
34
38
|
end
|
35
39
|
|
36
40
|
# unpause the current song
|
37
41
|
def unpause
|
38
|
-
return unless controller.status == :paused
|
42
|
+
return self unless controller.status == :paused
|
39
43
|
|
40
|
-
controller.
|
44
|
+
controller.send 'player-pause'
|
45
|
+
|
46
|
+
self
|
41
47
|
end
|
42
48
|
|
43
49
|
# stop the current song
|
44
50
|
def stop
|
45
|
-
controller.
|
51
|
+
controller.send 'player-stop'
|
52
|
+
|
53
|
+
self
|
46
54
|
end
|
47
55
|
|
48
56
|
# go to the next song in the playlist
|
49
57
|
def next
|
50
|
-
controller.
|
58
|
+
controller.send 'player-next'
|
59
|
+
|
60
|
+
self
|
51
61
|
end
|
52
62
|
|
53
63
|
# go to the previous song in the playlist
|
54
64
|
def prev
|
55
|
-
controller.
|
65
|
+
controller.send 'player-prev'
|
66
|
+
|
67
|
+
self
|
56
68
|
end
|
57
69
|
|
58
70
|
# change the volume
|
59
71
|
def volume (volume)
|
60
|
-
controller.
|
72
|
+
controller.send "vol #{volume}"
|
73
|
+
controller.check_for_error
|
74
|
+
|
75
|
+
self
|
61
76
|
end
|
62
77
|
|
63
78
|
# seek to the passed second
|
64
79
|
def seek (second)
|
65
|
-
controller.
|
80
|
+
controller.send "seek #{second}"
|
81
|
+
controller.check_for_error
|
82
|
+
|
83
|
+
self
|
66
84
|
end
|
67
85
|
end
|
68
86
|
|
@@ -13,23 +13,16 @@ require 'ostruct'
|
|
13
13
|
module Cmus; class Controller
|
14
14
|
|
15
15
|
class Status
|
16
|
-
attr_reader :controller, :path, :duration, :position, :
|
16
|
+
attr_reader :controller, :path, :duration, :position, :song, :settings
|
17
17
|
|
18
18
|
def initialize (controller)
|
19
19
|
@controller = controller
|
20
20
|
|
21
|
-
@
|
21
|
+
@song = OpenStruct.new
|
22
22
|
@settings = OpenStruct.new
|
23
23
|
|
24
|
-
controller.
|
25
|
-
|
26
|
-
buffer = controller.read(1)
|
27
|
-
|
28
|
-
while tmp = (controller.read_nonblock(2048) rescue nil)
|
29
|
-
buffer << tmp
|
30
|
-
end
|
31
|
-
|
32
|
-
buffer.each_line {|line|
|
24
|
+
controller.send 'status'
|
25
|
+
controller.wait_for_data.buffer.each_line {|line|
|
33
26
|
type, data = line.chomp.split ' ', 2
|
34
27
|
|
35
28
|
next unless type
|
@@ -50,7 +43,7 @@ class Status
|
|
50
43
|
when :tag
|
51
44
|
name, data = data.split ' ', 2
|
52
45
|
|
53
|
-
@
|
46
|
+
@song.send "#{name}=", data
|
54
47
|
|
55
48
|
when :set
|
56
49
|
name, data = data.split ' ', 2
|
@@ -70,6 +63,14 @@ class Status
|
|
70
63
|
@settings.send "#{name}=", data
|
71
64
|
end
|
72
65
|
}
|
66
|
+
|
67
|
+
if @song.marshal_dump.empty?
|
68
|
+
@song = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def volume
|
73
|
+
(settings.vol_left + settings.vol_right) / 2.0
|
73
74
|
end
|
74
75
|
|
75
76
|
def == (other)
|
@@ -18,60 +18,55 @@ class Toggle
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def toggle (name)
|
21
|
-
controller.
|
21
|
+
controller.send "toggle #{name}"
|
22
22
|
|
23
23
|
self
|
24
24
|
end
|
25
25
|
|
26
26
|
def on (name)
|
27
|
-
unless
|
28
|
-
controller.
|
27
|
+
unless on? name
|
28
|
+
controller.send "toggle #{name}"
|
29
29
|
end
|
30
30
|
|
31
31
|
self
|
32
32
|
end
|
33
33
|
|
34
34
|
def off (name)
|
35
|
-
if
|
36
|
-
controller.
|
35
|
+
if on? name
|
36
|
+
controller.send "toggle #{name}"
|
37
37
|
end
|
38
38
|
|
39
39
|
self
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
toggle :Repeat
|
42
|
+
def on? (name)
|
43
|
+
controller.status.settings.send(name)
|
45
44
|
end
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
on :Repeat
|
50
|
-
end
|
46
|
+
%w[show_hidden continue play_library repeat_current aaa_mode play_sorted repeat shuffle show_remaining_time].each {|name|
|
47
|
+
option_name = name
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
49
|
+
define_method name do
|
50
|
+
toggle option_name
|
51
|
+
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
53
|
+
define_method "#{name}!" do
|
54
|
+
on option_name
|
55
|
+
end
|
61
56
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
57
|
+
define_method "no_#{name}!" do
|
58
|
+
off option_name
|
59
|
+
end
|
60
|
+
|
61
|
+
define_method "#{name}?" do
|
62
|
+
on? option_name
|
63
|
+
end
|
64
|
+
}
|
66
65
|
|
67
|
-
# disable shuffle
|
68
|
-
def no_shuffle!
|
69
|
-
off :Shuffle
|
70
|
-
end
|
71
66
|
|
72
67
|
# toggle the pause status
|
73
68
|
def pause
|
74
|
-
controller.
|
69
|
+
controller.send 'player-pause'
|
75
70
|
|
76
71
|
self
|
77
72
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
module Cmus; class Controller
|
12
|
+
|
13
|
+
class Window
|
14
|
+
attr_reader :controller
|
15
|
+
|
16
|
+
def initialize (controller)
|
17
|
+
@controller = controller
|
18
|
+
end
|
19
|
+
|
20
|
+
def view (name)
|
21
|
+
controller.send "view #{name}"
|
22
|
+
controller.check_for_error
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def refresh
|
28
|
+
controller.send 'refresh'
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def activate
|
34
|
+
controller.send 'win-activate'
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def add (context = :playlist)
|
40
|
+
controller.send "win-add-#{context.to_s.downcase[0]}"
|
41
|
+
controller.check_for_error
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def bottom
|
47
|
+
controller.send 'win-bottom'
|
48
|
+
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def down
|
53
|
+
controller.send 'win-down'
|
54
|
+
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def up
|
59
|
+
controller.send 'win-up'
|
60
|
+
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def top
|
65
|
+
controller.send 'win-top'
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def move (whence = :after)
|
71
|
+
controller.send "win-mv-#{whence}"
|
72
|
+
controller.check_for_error
|
73
|
+
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
def next
|
78
|
+
controller.send 'win-next'
|
79
|
+
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
def page_up
|
84
|
+
controller.send 'win-page-up'
|
85
|
+
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
def page_down
|
90
|
+
controller.send 'win-page-down'
|
91
|
+
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def remove
|
96
|
+
controller.send 'win-remove'
|
97
|
+
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def select_current
|
102
|
+
controller.send 'win-sel-cur'
|
103
|
+
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def toggle
|
108
|
+
controller.send 'win-toggle'
|
109
|
+
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def update
|
114
|
+
controller.send 'win-update'
|
115
|
+
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
def update_cache
|
120
|
+
controller.send 'win-update-cache'
|
121
|
+
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
def search (whence = :next)
|
126
|
+
controller.send "search-#{whence}"
|
127
|
+
controller.check_for_error
|
128
|
+
|
129
|
+
self
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end; end
|
data/lib/cmus/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cmus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.4.
|
4
|
+
version: 2.0.4.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: meh@paranoici.org
|
@@ -26,6 +26,7 @@ files:
|
|
26
26
|
- lib/cmus/controller/player.rb
|
27
27
|
- lib/cmus/controller/status.rb
|
28
28
|
- lib/cmus/controller/toggle.rb
|
29
|
+
- lib/cmus/controller/window.rb
|
29
30
|
- lib/cmus/version.rb
|
30
31
|
homepage: http://github.com/meh/ruby-cmus
|
31
32
|
licenses: []
|