moc 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -0
- data/bin/mocp.rb +8 -0
- data/lib/moc/controller/player.rb +121 -0
- data/lib/moc/controller/playlist.rb +42 -0
- data/lib/moc/controller/status.rb +103 -0
- data/lib/moc/controller/tags.rb +33 -0
- data/lib/moc/controller/toggle.rb +149 -0
- data/lib/moc/controller.rb +183 -0
- data/lib/moc/protocol/command.rb +76 -0
- data/lib/moc/protocol/event.rb +63 -0
- data/lib/moc/protocol/integer.rb +41 -0
- data/lib/moc/protocol/state.rb +23 -0
- data/lib/moc/protocol/string.rb +28 -0
- data/lib/moc/protocol/symbol.rb +63 -0
- data/lib/moc/protocol/time.rb +21 -0
- data/lib/moc/protocol.rb +33 -0
- data/lib/moc/version.rb +15 -0
- data/lib/moc.rb +12 -0
- data/moc.gemspec +16 -0
- metadata +64 -0
data/README.md
ADDED
data/bin/mocp.rb
ADDED
@@ -0,0 +1,121 @@
|
|
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 Moc; class Controller
|
12
|
+
|
13
|
+
class Player
|
14
|
+
class Queue
|
15
|
+
include Enumerable
|
16
|
+
|
17
|
+
attr_reader :controller
|
18
|
+
|
19
|
+
def initialize (controller)
|
20
|
+
@controller = controller
|
21
|
+
end
|
22
|
+
|
23
|
+
# add an item to the queue
|
24
|
+
def add (file)
|
25
|
+
controller.send_command :queue_add
|
26
|
+
controller.send_string File.realpath(File.expand_path(file))
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# remove an item from the queue
|
32
|
+
def remove (file)
|
33
|
+
controller.send_command :queue_del
|
34
|
+
controller.send_string File.realpath(File.expand_path(file))
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
# swap two items
|
40
|
+
def move (from, to)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# clear the queue
|
45
|
+
def clear
|
46
|
+
controller.send_command :queue_clear
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
# iterate over the queued items
|
52
|
+
def each (&block)
|
53
|
+
controller.send_command :get_queue
|
54
|
+
controller.wait_for :data
|
55
|
+
|
56
|
+
until (item = controller.read_item).nil?
|
57
|
+
block.call(item)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :controller
|
63
|
+
|
64
|
+
def initialize (controller)
|
65
|
+
@controller = controller
|
66
|
+
end
|
67
|
+
|
68
|
+
def play
|
69
|
+
controller.send_command :unpause
|
70
|
+
end
|
71
|
+
|
72
|
+
# pause the current song
|
73
|
+
def pause
|
74
|
+
controller.send_command :pause
|
75
|
+
end
|
76
|
+
|
77
|
+
# unpause the current song
|
78
|
+
def unpause
|
79
|
+
controller.send_command :unpause
|
80
|
+
end
|
81
|
+
|
82
|
+
# stop the current song
|
83
|
+
def stop
|
84
|
+
controller.send_command :stop
|
85
|
+
end
|
86
|
+
|
87
|
+
# go to the next song in the playlist
|
88
|
+
def next
|
89
|
+
controller.send_command :next
|
90
|
+
end
|
91
|
+
|
92
|
+
# go to the previous song in the playlist
|
93
|
+
def prev
|
94
|
+
controller.send_command :prev
|
95
|
+
end
|
96
|
+
|
97
|
+
# change the volume
|
98
|
+
def volume (volume)
|
99
|
+
controller.send_command :set_mixer
|
100
|
+
controller.send_integer volume
|
101
|
+
end
|
102
|
+
|
103
|
+
# seek to the passed second
|
104
|
+
def seek (second)
|
105
|
+
controller.send_command :seek
|
106
|
+
controller.send_integer second
|
107
|
+
end
|
108
|
+
|
109
|
+
# jump to the passed second
|
110
|
+
def jump_to (second)
|
111
|
+
controller.send_command :jump_to
|
112
|
+
controller.send_integer second
|
113
|
+
end
|
114
|
+
|
115
|
+
# return the queue
|
116
|
+
def queue
|
117
|
+
@queue ||= Queue.new(controller)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end; end
|
@@ -0,0 +1,42 @@
|
|
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 Moc; class Controller
|
12
|
+
|
13
|
+
class Playlist
|
14
|
+
class Item < Struct.new(:file, :title_tags, :tags, :mtime)
|
15
|
+
attr_reader :controller
|
16
|
+
|
17
|
+
def initialize (controller)
|
18
|
+
@controller = controller
|
19
|
+
|
20
|
+
if (file = controller.read_string).empty?
|
21
|
+
@nil = true
|
22
|
+
else
|
23
|
+
@nil = false
|
24
|
+
|
25
|
+
super(
|
26
|
+
file,
|
27
|
+
controller.read_string,
|
28
|
+
controller.read_tags,
|
29
|
+
controller.read_time
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def nil?
|
35
|
+
@nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Move = Struct.new(:from, :to)
|
41
|
+
|
42
|
+
end; end
|
@@ -0,0 +1,103 @@
|
|
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 Moc; class Controller
|
12
|
+
|
13
|
+
class Status
|
14
|
+
class Song
|
15
|
+
attr_reader :controller
|
16
|
+
|
17
|
+
def initialize (controller)
|
18
|
+
@controller = controller
|
19
|
+
end
|
20
|
+
|
21
|
+
def channels
|
22
|
+
controller.send_command :get_channels
|
23
|
+
controller.get_integer
|
24
|
+
end
|
25
|
+
|
26
|
+
def rate
|
27
|
+
controller.send_command :get_rate
|
28
|
+
controller.get_integer
|
29
|
+
end
|
30
|
+
|
31
|
+
def bitrate
|
32
|
+
controller.send_command :get_bitrate
|
33
|
+
controller.get_integer
|
34
|
+
end
|
35
|
+
|
36
|
+
def average_bitrate
|
37
|
+
controller.send_command :get_avg_bitrate
|
38
|
+
controller.get_integer
|
39
|
+
end
|
40
|
+
|
41
|
+
def time
|
42
|
+
controller.send_command :get_ctime
|
43
|
+
controller.get_integer
|
44
|
+
end
|
45
|
+
|
46
|
+
def file
|
47
|
+
controller.send_command :get_sname
|
48
|
+
controller.get_string
|
49
|
+
end
|
50
|
+
|
51
|
+
def tags
|
52
|
+
path = file
|
53
|
+
|
54
|
+
controller.send_command :get_file_tags
|
55
|
+
controller.send_string path
|
56
|
+
controller.send_integer 0x01 | 0x02
|
57
|
+
|
58
|
+
controller.wait_for(:file_tags).tags
|
59
|
+
end
|
60
|
+
|
61
|
+
%w[title artist album track].each {|name|
|
62
|
+
define_method name do
|
63
|
+
tags.send name
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
"#<#{self.class.name}: track=#{track} title=#{title} artist=#{artist} album=#{album} channels=#{channels} bitrate=#{bitrate}(#{average_bitrate}) position=#{time}>"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
attr_reader :controller
|
73
|
+
|
74
|
+
def initialize (controller)
|
75
|
+
@controller = controller
|
76
|
+
end
|
77
|
+
|
78
|
+
def == (other)
|
79
|
+
state == other
|
80
|
+
end
|
81
|
+
|
82
|
+
def state
|
83
|
+
controller.send_command :get_state
|
84
|
+
controller.get_state
|
85
|
+
end
|
86
|
+
|
87
|
+
def volume
|
88
|
+
controller.send_command :get_mixer
|
89
|
+
controller.get_integer
|
90
|
+
end
|
91
|
+
|
92
|
+
def song
|
93
|
+
return if self == :stop
|
94
|
+
|
95
|
+
Song.new(controller)
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_sym
|
99
|
+
state.to_sym
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end; end
|
@@ -0,0 +1,33 @@
|
|
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 Moc; class Controller
|
12
|
+
|
13
|
+
class Tags < Struct.new(:title, :artist, :album, :track, :time)
|
14
|
+
attr_reader :controller
|
15
|
+
|
16
|
+
def initialize (controller)
|
17
|
+
@controller = controller
|
18
|
+
|
19
|
+
super(
|
20
|
+
controller.read_string,
|
21
|
+
controller.read_string,
|
22
|
+
controller.read_string,
|
23
|
+
controller.read_integer,
|
24
|
+
controller.read_integer
|
25
|
+
)
|
26
|
+
|
27
|
+
controller.read_integer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
FileTags = Struct.new(:file, :tags)
|
32
|
+
|
33
|
+
end; end
|
@@ -0,0 +1,149 @@
|
|
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 Moc; class Controller
|
12
|
+
|
13
|
+
class Toggle
|
14
|
+
attr_reader :controller
|
15
|
+
|
16
|
+
def initialize (controller)
|
17
|
+
@controller = controller
|
18
|
+
end
|
19
|
+
|
20
|
+
# toggle the named item
|
21
|
+
def toggle (name)
|
22
|
+
controller.send_command :get_option
|
23
|
+
controller.send_string name
|
24
|
+
|
25
|
+
value = !controller.get_integer.zero?
|
26
|
+
|
27
|
+
controller.send_command :set_option
|
28
|
+
controller.send_string name
|
29
|
+
controller.send_integer value ? 0 : 1
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# activate the named item
|
35
|
+
def on (name)
|
36
|
+
controller.send_command :set_option
|
37
|
+
controller.send_string name
|
38
|
+
controller.send_integer 1
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# deactivate the named item
|
44
|
+
def off (name)
|
45
|
+
controller.send_command :set_option
|
46
|
+
controller.send_string name
|
47
|
+
controller.send_integer 0
|
48
|
+
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
# check if an item is active
|
53
|
+
def on? (name)
|
54
|
+
controller.send_command :get_option
|
55
|
+
controller.send_string name
|
56
|
+
|
57
|
+
!controller.get_integer.zero?
|
58
|
+
end
|
59
|
+
|
60
|
+
# toggle the repeat status
|
61
|
+
def repeat
|
62
|
+
toggle :Repeat
|
63
|
+
end
|
64
|
+
|
65
|
+
# enable repeat
|
66
|
+
def repeat!
|
67
|
+
on :Repeat
|
68
|
+
end
|
69
|
+
|
70
|
+
# disable repeat
|
71
|
+
def no_repeat!
|
72
|
+
off :Repeat
|
73
|
+
end
|
74
|
+
|
75
|
+
# check if repeat is enabled
|
76
|
+
def repeat?
|
77
|
+
on? :Repeat
|
78
|
+
end
|
79
|
+
|
80
|
+
# toggle the shuffle status
|
81
|
+
def shuffle
|
82
|
+
toggle :Shuffle
|
83
|
+
end
|
84
|
+
|
85
|
+
# enable shuffle
|
86
|
+
def shuffle!
|
87
|
+
on :Shuffle
|
88
|
+
end
|
89
|
+
|
90
|
+
# disable shuffle
|
91
|
+
def no_shuffle!
|
92
|
+
off :Shuffle
|
93
|
+
end
|
94
|
+
|
95
|
+
# check if shuffle is enabled
|
96
|
+
def shuffle?
|
97
|
+
on? :Shuffle
|
98
|
+
end
|
99
|
+
|
100
|
+
# toggle the auto next status
|
101
|
+
def auto_next
|
102
|
+
toggle :AutoNext
|
103
|
+
end
|
104
|
+
|
105
|
+
# enable auto next
|
106
|
+
def auto_next!
|
107
|
+
on :AutoNext
|
108
|
+
end
|
109
|
+
|
110
|
+
# disable auto next
|
111
|
+
def no_auto_next!
|
112
|
+
off :AutoNext
|
113
|
+
end
|
114
|
+
|
115
|
+
# check if auto next is enabled
|
116
|
+
def auto_next?
|
117
|
+
on? :AutoNext
|
118
|
+
end
|
119
|
+
|
120
|
+
# toggle the pause status
|
121
|
+
def pause
|
122
|
+
controller.send_command :get_state
|
123
|
+
controller.send_command controller.get_state == :pause ? :unpause : :pause
|
124
|
+
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
# toggle mixer channel
|
129
|
+
def mixer_channel
|
130
|
+
controller.send_command :toggle_mixer_channel
|
131
|
+
end
|
132
|
+
|
133
|
+
# toggle soft mixer
|
134
|
+
def soft_mixer
|
135
|
+
controller.send_command :toggle_softmixer
|
136
|
+
end
|
137
|
+
|
138
|
+
# toggle equalizer
|
139
|
+
def equalizer
|
140
|
+
controller.send_command :toggle_equalizer
|
141
|
+
end
|
142
|
+
|
143
|
+
# toggle mono
|
144
|
+
def mono
|
145
|
+
controller.send_command :toggle_mono
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end; end
|
@@ -0,0 +1,183 @@
|
|
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
|
+
require 'socket'
|
12
|
+
|
13
|
+
require 'moc/protocol'
|
14
|
+
|
15
|
+
require 'moc/controller/toggle'
|
16
|
+
require 'moc/controller/player'
|
17
|
+
require 'moc/controller/status'
|
18
|
+
require 'moc/controller/tags'
|
19
|
+
require 'moc/controller/playlist'
|
20
|
+
|
21
|
+
module Moc
|
22
|
+
|
23
|
+
# This is the main class to manage moc.
|
24
|
+
#
|
25
|
+
# The class also acts as a UNIXSocket if needed.
|
26
|
+
class Controller
|
27
|
+
def self.symbol_to_code (sym)
|
28
|
+
return Commands[sym.to_sym.upcase]
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :path
|
32
|
+
|
33
|
+
def initialize (path = '~/.moc/socket2')
|
34
|
+
@path = File.expand_path(path)
|
35
|
+
@socket = UNIXSocket.new(@path)
|
36
|
+
|
37
|
+
@events = Hash.new { |h, k| h[k] = [] }
|
38
|
+
end
|
39
|
+
|
40
|
+
def respond_to_missing? (id, include_private = false)
|
41
|
+
@socket.respond_to? id, include_private
|
42
|
+
end
|
43
|
+
|
44
|
+
def method_missing (id, *args, &block)
|
45
|
+
if @socket.respond_to? id
|
46
|
+
return @socket.__send__ id, *args, &block
|
47
|
+
end
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
def send (object)
|
53
|
+
write object.pack
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_command (command)
|
57
|
+
send(command.is_a?(Protocol::Command) ? command : Protocol::Command.new(command))
|
58
|
+
end
|
59
|
+
|
60
|
+
def send_integer (int)
|
61
|
+
send Protocol::Integer.new(int.to_i)
|
62
|
+
end
|
63
|
+
|
64
|
+
def send_time (time)
|
65
|
+
send Protocol::Time.at(time.to_i)
|
66
|
+
end
|
67
|
+
|
68
|
+
def send_string (string)
|
69
|
+
send Protocol::String.new(string.to_s)
|
70
|
+
end
|
71
|
+
|
72
|
+
def read_string
|
73
|
+
Protocol::String.read(@socket)
|
74
|
+
end
|
75
|
+
|
76
|
+
def read_integer
|
77
|
+
Protocol::Integer.read(@socket)
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_time
|
81
|
+
Protocol::Time.read(@socket)
|
82
|
+
end
|
83
|
+
|
84
|
+
def read_event
|
85
|
+
Protocol::Event.read(@socket).tap {|event|
|
86
|
+
event.data = case event.to_sym
|
87
|
+
when :PLIST_ADD, :QUEUE_ADD
|
88
|
+
get_item
|
89
|
+
|
90
|
+
when :PLIST_DEL, :QUEUE_DEL, :STATUS_MSG
|
91
|
+
get_string
|
92
|
+
|
93
|
+
when :FILE_TAGS
|
94
|
+
FileTags.new(read_string, read_tags)
|
95
|
+
|
96
|
+
when :PLIST_MOVE, :QUEUE_MOVE
|
97
|
+
Move.new(read_string, read_string)
|
98
|
+
end
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def read_state
|
103
|
+
Protocol::State.read(@socket)
|
104
|
+
end
|
105
|
+
|
106
|
+
def read_item
|
107
|
+
Playlist::Item.new(self)
|
108
|
+
end
|
109
|
+
|
110
|
+
def read_tags
|
111
|
+
Tags.new(self)
|
112
|
+
end
|
113
|
+
|
114
|
+
%w[string integer time event state].each {|name|
|
115
|
+
define_method "get_#{name}" do
|
116
|
+
wait_for :data
|
117
|
+
|
118
|
+
__send__ "read_#{name}"
|
119
|
+
end
|
120
|
+
}
|
121
|
+
|
122
|
+
def on (event = nil, &block)
|
123
|
+
@events[event ? nil : event.to_sym.upcase] << block
|
124
|
+
end
|
125
|
+
|
126
|
+
def fire (event)
|
127
|
+
name = event.to_sym
|
128
|
+
|
129
|
+
@events[nil].each {|block|
|
130
|
+
block.call(event)
|
131
|
+
}
|
132
|
+
|
133
|
+
@events[name].each {|block|
|
134
|
+
block.call(event)
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
private :fire
|
139
|
+
|
140
|
+
def loop
|
141
|
+
while event = read_event
|
142
|
+
fire event
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def wait_for (name)
|
147
|
+
while (event = read_event) != name
|
148
|
+
fire event
|
149
|
+
end
|
150
|
+
|
151
|
+
event
|
152
|
+
end
|
153
|
+
|
154
|
+
def active?
|
155
|
+
send_command :ping
|
156
|
+
|
157
|
+
read_event == :pong
|
158
|
+
rescue
|
159
|
+
false
|
160
|
+
end
|
161
|
+
|
162
|
+
def quit
|
163
|
+
send_command :quit
|
164
|
+
end
|
165
|
+
|
166
|
+
def toggle
|
167
|
+
@toggle ||= Toggle.new(self)
|
168
|
+
end
|
169
|
+
|
170
|
+
def player
|
171
|
+
@player ||= Player.new(self)
|
172
|
+
end
|
173
|
+
|
174
|
+
def status
|
175
|
+
@status ||= Status.new(self)
|
176
|
+
end
|
177
|
+
|
178
|
+
def inspect
|
179
|
+
"#<#{self.class.name}: #{@path}>"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
@@ -0,0 +1,76 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class Command < Symbol
|
14
|
+
def self.codes
|
15
|
+
@codes ||= {
|
16
|
+
PLAY: 0x00,
|
17
|
+
LIST_CLEAR: 0x01,
|
18
|
+
LIST_ADD: 0x02,
|
19
|
+
STOP: 0x04,
|
20
|
+
PAUSE: 0x05,
|
21
|
+
UNPAUSE: 0x06,
|
22
|
+
SET_OPTION: 0x07,
|
23
|
+
GET_OPTION: 0x08,
|
24
|
+
GET_CTIME: 0x0d,
|
25
|
+
GET_SNAME: 0x0f,
|
26
|
+
NEXT: 0x10,
|
27
|
+
QUIT: 0x11,
|
28
|
+
SEEK: 0x12,
|
29
|
+
GET_STATE: 0x13,
|
30
|
+
DISCONNECT: 0x15,
|
31
|
+
GET_BITRATE: 0x16,
|
32
|
+
GET_RATE: 0x17,
|
33
|
+
GET_CHANNELS: 0x18,
|
34
|
+
PING: 0x19,
|
35
|
+
GET_MIXER: 0x1a,
|
36
|
+
SET_MIXER: 0x1b,
|
37
|
+
DELETE: 0x1c,
|
38
|
+
SEND_EVENTS: 0x1d,
|
39
|
+
GET_ERROR: 0x1e,
|
40
|
+
PREV: 0x20,
|
41
|
+
SEND_PLIST: 0x21,
|
42
|
+
GET_PLIST: 0x22,
|
43
|
+
CAN_SEND_PLIST: 0x23,
|
44
|
+
CLI_PLIST_ADD: 0x24,
|
45
|
+
CLI_PLIST_DEL: 0x25,
|
46
|
+
CLI_PLIST_CLEAR: 0x26,
|
47
|
+
GET_SERIAL: 0x27,
|
48
|
+
PLIST_SET_SERIAL: 0x28,
|
49
|
+
LOCK: 0x29,
|
50
|
+
UNLOCK: 0x2a,
|
51
|
+
PLIST_GET_SERIAL: 0x2b,
|
52
|
+
GET_TAGS: 0x2c,
|
53
|
+
TOGGLE_MIXER_CHANNEL: 0x2d,
|
54
|
+
GET_MIXER_CHANNEL_NAME: 0x2e,
|
55
|
+
GET_FILE_TAGS: 0x2f,
|
56
|
+
ABORT_TAGS_REQUESTS: 0x30,
|
57
|
+
CLI_PLIST_MOVE: 0x31,
|
58
|
+
LIST_MOVE: 0x32,
|
59
|
+
GET_AVG_BITRATE: 0x33,
|
60
|
+
TOGGLE_SOFTMIXER: 0x34,
|
61
|
+
TOGGLE_EQUALIZER: 0x35,
|
62
|
+
EQUALIZER_REFRESH: 0x36,
|
63
|
+
EQUALIZER_PREV: 0x37,
|
64
|
+
EQUALIZER_NEXT: 0x38,
|
65
|
+
TOGGLE_MAKE_MONO: 0x39,
|
66
|
+
JUMP_TO: 0x3a,
|
67
|
+
QUEUE_ADD: 0x3b,
|
68
|
+
QUEUE_DEL: 0x3c,
|
69
|
+
QUEUE_MOVE: 0x3d,
|
70
|
+
QUEUE_CLEAR: 0x3e,
|
71
|
+
GET_QUEUE: 0x3f
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end; end
|
@@ -0,0 +1,63 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class Event < Symbol
|
14
|
+
def self.codes
|
15
|
+
@codes ||= {
|
16
|
+
STATE: 0x01,
|
17
|
+
CTIME: 0x02,
|
18
|
+
SRV_ERROR: 0x04,
|
19
|
+
BUSY: 0x05,
|
20
|
+
DATA: 0x06,
|
21
|
+
BITRATE: 0x07,
|
22
|
+
RATE: 0x08,
|
23
|
+
CHANNELS: 0x09,
|
24
|
+
EXIT: 0x0a,
|
25
|
+
PONG: 0x0b,
|
26
|
+
OPTIONS: 0x0c,
|
27
|
+
SEND_PLIST: 0x0d,
|
28
|
+
TAGS: 0x0e,
|
29
|
+
STATUS_MSG: 0x0f,
|
30
|
+
MIXER_CHANGE: 0x10,
|
31
|
+
FILE_TAGS: 0x11,
|
32
|
+
AVG_BITRATE: 0x12,
|
33
|
+
AUDIO_START: 0x13,
|
34
|
+
AUDIO_STOP: 0x14,
|
35
|
+
|
36
|
+
PLIST_ADD: 0x50,
|
37
|
+
PLIST_DEL: 0x51,
|
38
|
+
PLIST_MOVE: 0x52,
|
39
|
+
PLIST_CLEAR: 0x53,
|
40
|
+
|
41
|
+
QUEUE_ADD: 0x54,
|
42
|
+
QUEUE_DEL: 0x55,
|
43
|
+
QUEUE_MOVE: 0x56,
|
44
|
+
QUEUE_CLEAR: 0x57
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_accessor :data
|
49
|
+
|
50
|
+
def respond_to_missing? (id, include_private = false)
|
51
|
+
data.respond_to?(id, include_private)
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing (id, *args, &block)
|
55
|
+
if data.respond_to? id
|
56
|
+
return data.__send__ id, *args, &block
|
57
|
+
end
|
58
|
+
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end; end
|
@@ -0,0 +1,41 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class Integer < BasicObject
|
14
|
+
extend Type
|
15
|
+
|
16
|
+
def self.read (io)
|
17
|
+
new(io.read(4).unpack('l').first)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize (value)
|
21
|
+
@internal = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def respond_to_missing? (id, include_private = false)
|
25
|
+
@internal.respond_to? id, include_private
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing (id, *args, &block)
|
29
|
+
if @internal.respond_to? id
|
30
|
+
return @internal.__send__ id, *args, &block
|
31
|
+
end
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def pack
|
37
|
+
[self].pack('l')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end; end
|
@@ -0,0 +1,23 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class State < Symbol
|
14
|
+
def self.codes
|
15
|
+
@codes ||= {
|
16
|
+
PLAY: 0x01,
|
17
|
+
STOP: 0x02,
|
18
|
+
PAUSE: 0x03
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end; end
|
@@ -0,0 +1,28 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class String < ::String
|
14
|
+
extend Type
|
15
|
+
|
16
|
+
def self.read (io)
|
17
|
+
length = Integer.read(io)
|
18
|
+
string = io.read(length)
|
19
|
+
|
20
|
+
new(string)
|
21
|
+
end
|
22
|
+
|
23
|
+
def pack
|
24
|
+
Integer.new(length).pack << self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end; end
|
@@ -0,0 +1,63 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class Symbol
|
14
|
+
extend Type
|
15
|
+
|
16
|
+
def self.read (io)
|
17
|
+
new(Integer.read(io))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.codes
|
21
|
+
raise 'no code specification'
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize (value)
|
25
|
+
@internal = value.respond_to?(:to_i) ? self.class.codes.key(value.to_i) : value.to_sym.upcase
|
26
|
+
|
27
|
+
unless @internal && self.class.codes.member?(@internal)
|
28
|
+
raise ArgumentError, 'invalid symbol'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def == (value)
|
33
|
+
return true if super
|
34
|
+
|
35
|
+
return true if value.respond_to?(:to_i) && to_i == value.to_i
|
36
|
+
|
37
|
+
return true if value.respond_to?(:to_sym) && to_sym == value.to_sym.upcase
|
38
|
+
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_i
|
43
|
+
self.class.codes[to_sym]
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_sym
|
47
|
+
@internal
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
to_sym.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
"#<#{self.class.name}: #{to_s}>"
|
56
|
+
end
|
57
|
+
|
58
|
+
def pack
|
59
|
+
Integer.new(to_i).pack
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end; end
|
@@ -0,0 +1,21 @@
|
|
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 Moc; module Protocol
|
12
|
+
|
13
|
+
class Time < ::Time
|
14
|
+
extend Type
|
15
|
+
|
16
|
+
def self.read (io)
|
17
|
+
at Integer.read(io)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end; end
|
data/lib/moc/protocol.rb
ADDED
@@ -0,0 +1,33 @@
|
|
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
|
+
require 'stringio'
|
12
|
+
|
13
|
+
module Moc; module Protocol
|
14
|
+
|
15
|
+
module Type
|
16
|
+
def read (io)
|
17
|
+
raise 'no read has been implemented'
|
18
|
+
end
|
19
|
+
|
20
|
+
def unpack (text)
|
21
|
+
read(StringIO.new(text))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end; end
|
26
|
+
|
27
|
+
require 'moc/protocol/integer'
|
28
|
+
require 'moc/protocol/time'
|
29
|
+
require 'moc/protocol/string'
|
30
|
+
require 'moc/protocol/symbol'
|
31
|
+
require 'moc/protocol/command'
|
32
|
+
require 'moc/protocol/event'
|
33
|
+
require 'moc/protocol/state'
|
data/lib/moc/version.rb
ADDED
@@ -0,0 +1,15 @@
|
|
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 Moc
|
12
|
+
def self.version
|
13
|
+
'2.5.0'
|
14
|
+
end
|
15
|
+
end
|
data/lib/moc.rb
ADDED
@@ -0,0 +1,12 @@
|
|
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
|
+
require 'moc/controller'
|
12
|
+
require 'moc/version'
|
data/moc.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Kernel.load 'lib/moc/version.rb'
|
2
|
+
|
3
|
+
Gem::Specification.new {|s|
|
4
|
+
s.name = 'moc'
|
5
|
+
s.version = Moc.version
|
6
|
+
s.author = 'meh.'
|
7
|
+
s.email = 'meh@paranoici.org'
|
8
|
+
s.homepage = 'http://github.com/meh/ruby-moc'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'moc controller library.'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
}
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: moc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.5.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- meh.
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: meh@paranoici.org
|
16
|
+
executables:
|
17
|
+
- mocp.rb
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- bin/mocp.rb
|
23
|
+
- lib/moc.rb
|
24
|
+
- lib/moc/controller.rb
|
25
|
+
- lib/moc/controller/player.rb
|
26
|
+
- lib/moc/controller/playlist.rb
|
27
|
+
- lib/moc/controller/status.rb
|
28
|
+
- lib/moc/controller/tags.rb
|
29
|
+
- lib/moc/controller/toggle.rb
|
30
|
+
- lib/moc/protocol.rb
|
31
|
+
- lib/moc/protocol/command.rb
|
32
|
+
- lib/moc/protocol/event.rb
|
33
|
+
- lib/moc/protocol/integer.rb
|
34
|
+
- lib/moc/protocol/state.rb
|
35
|
+
- lib/moc/protocol/string.rb
|
36
|
+
- lib/moc/protocol/symbol.rb
|
37
|
+
- lib/moc/protocol/time.rb
|
38
|
+
- lib/moc/version.rb
|
39
|
+
- moc.gemspec
|
40
|
+
homepage: http://github.com/meh/ruby-moc
|
41
|
+
licenses: []
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.8.24
|
61
|
+
signing_key:
|
62
|
+
specification_version: 3
|
63
|
+
summary: moc controller library.
|
64
|
+
test_files: []
|