moc 2.5.0
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.
- 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: []
|