moc 2.5.0 → 2.5.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -50,7 +50,7 @@ class Controller
50
50
  end
51
51
 
52
52
  def send (object)
53
- write object.pack
53
+ @socket.write object.respond_to?(:pack) ? object.pack : object.to_s
54
54
  end
55
55
 
56
56
  def send_command (command)
@@ -69,6 +69,35 @@ class Controller
69
69
  send Protocol::String.new(string.to_s)
70
70
  end
71
71
 
72
+ def send_item (item)
73
+ if item
74
+ send_string item.file
75
+ send_string item.title_tags || ''
76
+ send_tags item.tags
77
+ send_time item.mtime
78
+ else
79
+ send_string ''
80
+ end
81
+ end
82
+
83
+ def send_tags (tags)
84
+ if tags
85
+ send_string tags.title
86
+ send_string tags.artist
87
+ send_string tags.album
88
+ send_integer tags.track
89
+ send_integer tags.time
90
+ send_integer 0x01 | 0x02
91
+ else
92
+ send_string ''
93
+ send_string ''
94
+ send_string ''
95
+ send_integer -1
96
+ send_integer -1
97
+ send_integer 0
98
+ end
99
+ end
100
+
72
101
  def read_string
73
102
  Protocol::String.read(@socket)
74
103
  end
@@ -85,10 +114,10 @@ class Controller
85
114
  Protocol::Event.read(@socket).tap {|event|
86
115
  event.data = case event.to_sym
87
116
  when :PLIST_ADD, :QUEUE_ADD
88
- get_item
117
+ read_item
89
118
 
90
119
  when :PLIST_DEL, :QUEUE_DEL, :STATUS_MSG
91
- get_string
120
+ read_string
92
121
 
93
122
  when :FILE_TAGS
94
123
  FileTags.new(read_string, read_tags)
@@ -104,14 +133,34 @@ class Controller
104
133
  end
105
134
 
106
135
  def read_item
107
- Playlist::Item.new(self)
136
+ return if (file = read_string.to_s).empty?
137
+
138
+ title_tags = read_string.to_s
139
+
140
+ Playlist::Item.new(file, title_tags.empty? ? nil : title_tags, read_tags, read_time)
108
141
  end
109
142
 
110
143
  def read_tags
111
- Tags.new(self)
144
+ title = read_string.to_s
145
+ artist = read_string.to_s
146
+ album = read_string.to_s
147
+ track = read_integer.to_i
148
+ time = read_integer.to_i
149
+ filled = read_integer.to_i
150
+
151
+ title = nil if title.empty?
152
+ artist = nil if artist.empty?
153
+ album = nil if album.empty?
154
+ track = nil if track == -1
155
+
156
+ if title.nil? && artist.nil? && album.nil? && track.nil? && time == -1 && filled == 0
157
+ return nil
158
+ end
159
+
160
+ Tags.new(title, artist, album, track, time)
112
161
  end
113
162
 
114
- %w[string integer time event state].each {|name|
163
+ %w[string integer time state tags].each {|name|
115
164
  define_method "get_#{name}" do
116
165
  wait_for :data
117
166
 
@@ -135,8 +184,6 @@ class Controller
135
184
  }
136
185
  end
137
186
 
138
- private :fire
139
-
140
187
  def loop
141
188
  while event = read_event
142
189
  fire event
@@ -171,8 +218,8 @@ class Controller
171
218
  @player ||= Player.new(self)
172
219
  end
173
220
 
174
- def status
175
- @status ||= Status.new(self)
221
+ def status (live = false)
222
+ live ? (@status ||= Status::Live.new(self)) : Status.new(self)
176
223
  end
177
224
 
178
225
  def inspect
@@ -53,7 +53,7 @@ class Player
53
53
  controller.send_command :get_queue
54
54
  controller.wait_for :data
55
55
 
56
- until (item = controller.read_item).nil?
56
+ while item = controller.read_item
57
57
  block.call(item)
58
58
  end
59
59
  end
@@ -11,30 +11,7 @@
11
11
  module Moc; class Controller
12
12
 
13
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
14
+ Item = Struct.new(:file, :title_tags, :tags, :mtime)
38
15
  end
39
16
 
40
17
  Move = Struct.new(:from, :to)
@@ -11,51 +11,119 @@
11
11
  module Moc; class Controller
12
12
 
13
13
  class Status
14
- class Song
14
+ class Live
15
+ class Song
16
+ attr_reader :controller
17
+
18
+ def initialize (controller)
19
+ @controller = controller
20
+ end
21
+
22
+ def channels
23
+ controller.send_command :get_channels
24
+ controller.get_integer.to_i
25
+ end
26
+
27
+ def rate
28
+ controller.send_command :get_rate
29
+ controller.get_integer.to_i
30
+ end
31
+
32
+ def bitrate
33
+ controller.send_command :get_bitrate
34
+ controller.get_integer.to_i
35
+ end
36
+
37
+ def average_bitrate
38
+ controller.send_command :get_avg_bitrate
39
+ controller.get_integer.to_i
40
+ end
41
+
42
+ def position
43
+ controller.send_command :get_ctime
44
+ controller.get_integer.to_i
45
+ end
46
+
47
+ def file
48
+ controller.send_command :get_sname
49
+ controller.get_string.to_s
50
+ end
51
+
52
+ def tags
53
+ path = file
54
+
55
+ if path.start_with?('http://') || path.start_with?('ftp://')
56
+ controller.send_command :get_tags
57
+ controller.get_tags
58
+ else
59
+ controller.send_command :get_file_tags
60
+ controller.send_string path
61
+ controller.send_integer 0x01 | 0x02
62
+
63
+ controller.wait_for(:file_tags).tags
64
+ end
65
+ end
66
+
67
+ %w[title artist album track].each {|name|
68
+ define_method name do
69
+ tags.send name
70
+ end
71
+ }
72
+
73
+ def duration
74
+ tags.time
75
+ end
76
+
77
+ def inspect
78
+ "#<#{self.class.name}: track=#{track} title=#{title.inspect} artist=#{artist.inspect} album=#{album.inspect} channels=#{channels} bitrate=#{bitrate}(#{average_bitrate}) position=#{position}/#{duration}>"
79
+ end
80
+ end
81
+
15
82
  attr_reader :controller
16
83
 
17
84
  def initialize (controller)
18
85
  @controller = controller
19
86
  end
20
87
 
21
- def channels
22
- controller.send_command :get_channels
23
- controller.get_integer
88
+ def == (other)
89
+ super || state == other
24
90
  end
25
91
 
26
- def rate
27
- controller.send_command :get_rate
28
- controller.get_integer
92
+ def state
93
+ controller.send_command :get_state
94
+ controller.get_state
29
95
  end
30
96
 
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
97
+ def volume
98
+ controller.send_command :get_mixer
99
+ controller.get_integer.to_i
39
100
  end
40
101
 
41
- def time
42
- controller.send_command :get_ctime
43
- controller.get_integer
44
- end
102
+ def song
103
+ return if self == :stop
45
104
 
46
- def file
47
- controller.send_command :get_sname
48
- controller.get_string
105
+ Song.new(controller)
49
106
  end
50
107
 
51
- def tags
52
- path = file
108
+ def to_sym
109
+ state.to_sym
110
+ end
111
+ end
53
112
 
54
- controller.send_command :get_file_tags
55
- controller.send_string path
56
- controller.send_integer 0x01 | 0x02
113
+ class Song
114
+ attr_reader :controller, :channels, :rate, :bitrate, :average_bitrate, :position, :file, :tags
57
115
 
58
- controller.wait_for(:file_tags).tags
116
+ def initialize (controller)
117
+ @controller = controller
118
+ @internal = Live::Song.new(controller)
119
+
120
+ @channels = @internal.channels
121
+ @rate = @internal.rate
122
+ @bitrate = @internal.bitrate
123
+ @average_bitrate = @internal.average_bitrate
124
+ @position = @internal.position
125
+ @file = @internal.file
126
+ @tags = @internal.tags
59
127
  end
60
128
 
61
129
  %w[title artist album track].each {|name|
@@ -64,35 +132,31 @@ class Status
64
132
  end
65
133
  }
66
134
 
135
+ def duration
136
+ tags.time
137
+ end
138
+
67
139
  def inspect
68
- "#<#{self.class.name}: track=#{track} title=#{title} artist=#{artist} album=#{album} channels=#{channels} bitrate=#{bitrate}(#{average_bitrate}) position=#{time}>"
140
+ "#<#{self.class.name}: track=#{track} title=#{title.inspect} artist=#{artist.inspect} album=#{album.inspect} channels=#{channels} bitrate=#{bitrate}(#{average_bitrate}) position=#{position}/#{duration}>"
69
141
  end
70
142
  end
71
143
 
72
- attr_reader :controller
144
+ attr_reader :controller, :state, :volume, :song
73
145
 
74
146
  def initialize (controller)
75
147
  @controller = controller
76
- end
77
-
78
- def == (other)
79
- state == other
80
- end
148
+ @internal = Live.new(controller)
81
149
 
82
- def state
83
- controller.send_command :get_state
84
- controller.get_state
85
- end
150
+ @state = @internal.state
151
+ @volume = @internal.volume
86
152
 
87
- def volume
88
- controller.send_command :get_mixer
89
- controller.get_integer
153
+ if state != :stop
154
+ @song = Song.new(controller)
155
+ end
90
156
  end
91
157
 
92
- def song
93
- return if self == :stop
94
-
95
- Song.new(controller)
158
+ def == (other)
159
+ super || state == other
96
160
  end
97
161
 
98
162
  def to_sym
@@ -10,24 +10,7 @@
10
10
 
11
11
  module Moc; class Controller
12
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
-
13
+ Tags = Struct.new(:title, :artist, :album, :track, :time)
31
14
  FileTags = Struct.new(:file, :tags)
32
15
 
33
16
  end; end
@@ -57,65 +57,25 @@ class Toggle
57
57
  !controller.get_integer.zero?
58
58
  end
59
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
60
+ %w[repeat shuffle auto_next].each {|name|
61
+ option_name = name.capitalize.gsub(/_(\w)/) { $1.upcase }
74
62
 
75
- # check if repeat is enabled
76
- def repeat?
77
- on? :Repeat
78
- end
63
+ define_method name do
64
+ toggle option_name
65
+ end
79
66
 
80
- # toggle the shuffle status
81
- def shuffle
82
- toggle :Shuffle
83
- end
67
+ define_method "#{name}!" do
68
+ on option_name
69
+ end
84
70
 
85
- # enable shuffle
86
- def shuffle!
87
- on :Shuffle
88
- end
89
-
90
- # disable shuffle
91
- def no_shuffle!
92
- off :Shuffle
93
- end
71
+ define_method "no_#{name}!" do
72
+ off option_name
73
+ end
94
74
 
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
75
+ define_method "#{name}?" do
76
+ on? option_name
77
+ end
78
+ }
119
79
 
120
80
  # toggle the pause status
121
81
  def pause
data/lib/moc/protocol.rb CHANGED
@@ -17,8 +17,12 @@ module Type
17
17
  raise 'no read has been implemented'
18
18
  end
19
19
 
20
- def unpack (text)
21
- read(StringIO.new(text))
20
+ def unpack (text, eat = false)
21
+ io = StringIO.new(text)
22
+
23
+ read(io).tap {
24
+ text[0, io.tell] = '' if eat
25
+ }
22
26
  end
23
27
  end
24
28
 
@@ -14,15 +14,15 @@ class Integer < BasicObject
14
14
  extend Type
15
15
 
16
16
  def self.read (io)
17
- new(io.read(4).unpack('l').first)
17
+ new(io.read(4).unpack('i').first)
18
18
  end
19
19
 
20
20
  def initialize (value)
21
21
  @internal = value
22
22
  end
23
23
 
24
- def respond_to_missing? (id, include_private = false)
25
- @internal.respond_to? id, include_private
24
+ def respond_to? (id, include_private = false)
25
+ return true if id == :pack || @internal.respond_to?(id, include_private)
26
26
  end
27
27
 
28
28
  def method_missing (id, *args, &block)
@@ -34,7 +34,7 @@ class Integer < BasicObject
34
34
  end
35
35
 
36
36
  def pack
37
- [self].pack('l')
37
+ [self].pack('i')
38
38
  end
39
39
  end
40
40
 
@@ -16,6 +16,10 @@ class Time < ::Time
16
16
  def self.read (io)
17
17
  at Integer.read(io)
18
18
  end
19
+
20
+ def pack
21
+ Integer.new(to_i).pack
22
+ end
19
23
  end
20
24
 
21
25
  end; end
data/lib/moc/version.rb CHANGED
@@ -10,6 +10,6 @@
10
10
 
11
11
  module Moc
12
12
  def self.version
13
- '2.5.0'
13
+ '2.5.0.1'
14
14
  end
15
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.5.0.1
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-20 00:00:00.000000000 Z
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: meh@paranoici.org