topherfangio-lcdproc-ruby 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +6 -0
- data/LICENSE +20 -0
- data/README.rdoc +9 -0
- data/Rakefile +70 -0
- data/TODO +18 -0
- data/VERSION +1 -0
- data/devices/crystalfontz/packet.rb +108 -0
- data/devices/devices.rb +41 -0
- data/examples/basic.rb +39 -0
- data/examples/clock.rb +78 -0
- data/examples/lights.rb +67 -0
- data/lcdproc.rb +43 -0
- data/lib/console.rb +39 -0
- data/lib/core_extensions/array.rb +37 -0
- data/lib/core_extensions/string.rb +37 -0
- data/lib/includes/lcdproc.rb +27 -0
- data/lib/lcdproc-ruby.rb +0 -0
- data/lib/lcdproc/client.rb +458 -0
- data/lib/lcdproc/command.rb +54 -0
- data/lib/lcdproc/errors.rb +41 -0
- data/lib/lcdproc/key_event.rb +59 -0
- data/lib/lcdproc/menu.rb +188 -0
- data/lib/lcdproc/menu_event.rb +49 -0
- data/lib/lcdproc/menu_item.rb +108 -0
- data/lib/lcdproc/menu_items/action.rb +72 -0
- data/lib/lcdproc/menu_items/alpha.rb +85 -0
- data/lib/lcdproc/menu_items/checkbox.rb +76 -0
- data/lib/lcdproc/menu_items/ip.rb +75 -0
- data/lib/lcdproc/menu_items/numeric.rb +75 -0
- data/lib/lcdproc/menu_items/ring.rb +75 -0
- data/lib/lcdproc/menu_items/slider.rb +83 -0
- data/lib/lcdproc/menu_items/submenu.rb +77 -0
- data/lib/lcdproc/response.rb +65 -0
- data/lib/lcdproc/screen.rb +283 -0
- data/lib/lcdproc/widget.rb +142 -0
- data/lib/lcdproc/widgets/graph.rb +185 -0
- data/lib/lcdproc/widgets/hbar.rb +101 -0
- data/lib/lcdproc/widgets/icon.rb +94 -0
- data/lib/lcdproc/widgets/num.rb +92 -0
- data/lib/lcdproc/widgets/scroller.rb +110 -0
- data/lib/lcdproc/widgets/string.rb +94 -0
- data/lib/lcdproc/widgets/title.rb +90 -0
- data/lib/lcdproc/widgets/vbar.rb +111 -0
- data/script/console.rb +28 -0
- data/script/telnet.rb +90 -0
- data/tasks/test/basic.rake +82 -0
- data/tasks/test/keys.rake +66 -0
- data/tasks/test/menus.rake +74 -0
- metadata +104 -0
data/lcdproc.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2008 Topher Fangio
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation
|
6
|
+
# files (the "Software"), to deal in the Software without
|
7
|
+
# restriction, including without limitation the rights to use,
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the
|
10
|
+
# Software is furnished to do so, subject to the following
|
11
|
+
# conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#-------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
require "socket"
|
28
|
+
require "find"
|
29
|
+
|
30
|
+
fileList = []
|
31
|
+
directories = [ "lib/lcdproc", "lib/core_extensions", "devices" ]
|
32
|
+
|
33
|
+
directories.each do |directory|
|
34
|
+
Find.find( directory ) do |file|
|
35
|
+
if File.basename( file ) =~ /.rb$/
|
36
|
+
fileList << file
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
fileList.sort { |a,b| a.scan(/\//).size <=> b.scan(/\//).size }.each do |file|
|
41
|
+
require file
|
42
|
+
end
|
43
|
+
end
|
data/lib/console.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2008 Topher Fangio
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation
|
6
|
+
# files (the "Software"), to deal in the Software without
|
7
|
+
# restriction, including without limitation the rights to use,
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the
|
10
|
+
# Software is furnished to do so, subject to the following
|
11
|
+
# conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#-------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
require 'optparse'
|
28
|
+
|
29
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
30
|
+
|
31
|
+
options = { :irb => irb }
|
32
|
+
|
33
|
+
libs = " -r irb/completion"
|
34
|
+
libs << " -r lcdproc"
|
35
|
+
libs << " -r lib/includes/lcdproc"
|
36
|
+
|
37
|
+
puts "Loading LCDProc Console Environment"
|
38
|
+
|
39
|
+
exec "#{options[:irb]} #{libs} --simple-prompt"
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2008 Topher Fangio
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation
|
6
|
+
# files (the "Software"), to deal in the Software without
|
7
|
+
# restriction, including without limitation the rights to use,
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the
|
10
|
+
# Software is furnished to do so, subject to the following
|
11
|
+
# conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#-------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
class Array
|
28
|
+
|
29
|
+
def sum
|
30
|
+
inject( nil ) { |sum,x| sum ? sum + x : x }
|
31
|
+
end
|
32
|
+
|
33
|
+
def mean
|
34
|
+
sum.to_f / size
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2008 Topher Fangio
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation
|
6
|
+
# files (the "Software"), to deal in the Software without
|
7
|
+
# restriction, including without limitation the rights to use,
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the
|
10
|
+
# Software is furnished to do so, subject to the following
|
11
|
+
# conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#-------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
class String
|
28
|
+
|
29
|
+
def quotify
|
30
|
+
"\"#{self}\""
|
31
|
+
end
|
32
|
+
|
33
|
+
def quotify!
|
34
|
+
self.replace self.quotify
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2008 Topher Fangio
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation
|
6
|
+
# files (the "Software"), to deal in the Software without
|
7
|
+
# restriction, including without limitation the rights to use,
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the
|
10
|
+
# Software is furnished to do so, subject to the following
|
11
|
+
# conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#-------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
include LCDProc
|
data/lib/lcdproc-ruby.rb
ADDED
File without changes
|
@@ -0,0 +1,458 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2008 Topher Fangio
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation
|
6
|
+
# files (the "Software"), to deal in the Software without
|
7
|
+
# restriction, including without limitation the rights to use,
|
8
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the
|
10
|
+
# Software is furnished to do so, subject to the following
|
11
|
+
# conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
18
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
20
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
21
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
23
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#-------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
|
27
|
+
module LCDProc
|
28
|
+
|
29
|
+
class Client
|
30
|
+
# The maximum number of messages allowed to stay in memory. This works much like a circular array with the
|
31
|
+
# oldest messages being overwritten.
|
32
|
+
MAX_MESSAGES = 512
|
33
|
+
|
34
|
+
# The number of milliseconds to wait before processing new responses.
|
35
|
+
RESPONSE_PROCESS_TIME = 25
|
36
|
+
|
37
|
+
# Whether or not debugging output should be displayed.
|
38
|
+
DEBUG = false
|
39
|
+
|
40
|
+
# The number of LCDProc-Ruby clients currently connected to the server.
|
41
|
+
@@client_count = 0
|
42
|
+
|
43
|
+
attr_reader :key_events, :commands, :name, :menu_events, :messages, :response_queue, :screens, :width, :height, :cell_width, :cell_height
|
44
|
+
attr_accessor :menu
|
45
|
+
|
46
|
+
# Create a new client.
|
47
|
+
#
|
48
|
+
# If <tt>:host</tt> is left blank, it will attempt to connect to "_localhost_" on port <i>13666</i>. You may also
|
49
|
+
# specify another port through <tt>:port</tt>.
|
50
|
+
#
|
51
|
+
# * <tt>:host</tt> - The host to which the client should attempt to connect. Defaults to "localhost".
|
52
|
+
# * <tt>:port</tt> - The port on which the client should attempt to connect. Defaults to 13666.
|
53
|
+
# * <tt>:name</tt> - The name that should be associated with this client. Defaults to "Client_" + a sequence number.
|
54
|
+
#
|
55
|
+
# Example:
|
56
|
+
#
|
57
|
+
# my_client = Client.new
|
58
|
+
#
|
59
|
+
# or
|
60
|
+
#
|
61
|
+
# my_client = Client.new( :host => "my.remote-host.com", :port => 13667, :name => 'MyGamingRig' )
|
62
|
+
def initialize( user_options = {} )
|
63
|
+
if self.respond_to?( :before_initialize ) then self.send( :before_initialize, user_options ) end
|
64
|
+
|
65
|
+
@messages = []
|
66
|
+
@commands = []
|
67
|
+
@response_queue = []
|
68
|
+
@screens = []
|
69
|
+
@menu_events = []
|
70
|
+
@global_key_events = []
|
71
|
+
@current_screen = nil
|
72
|
+
|
73
|
+
options = {}
|
74
|
+
|
75
|
+
options[:host] = "localhost"
|
76
|
+
options[:port] = 13666
|
77
|
+
options[:name] = "Client_#{@@client_count}"
|
78
|
+
|
79
|
+
# Update our defaults with anything that they passed in
|
80
|
+
options.update( user_options )
|
81
|
+
|
82
|
+
@daemon_socket = connect( options[:host], options[:port] )
|
83
|
+
|
84
|
+
if @daemon_socket.nil?
|
85
|
+
raise messages[0]
|
86
|
+
end
|
87
|
+
|
88
|
+
@thread = Thread.new do
|
89
|
+
while true do
|
90
|
+
sleep( RESPONSE_PROCESS_TIME.to_f / 1000.0 )
|
91
|
+
process_responses
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
response = send_command( Command.new( "hello" ) )
|
96
|
+
response = response.message.split(' ')
|
97
|
+
|
98
|
+
@version = response[2]
|
99
|
+
@protocol = response[4]
|
100
|
+
@width = response[7]
|
101
|
+
@height = response[9]
|
102
|
+
@cell_width = response[11]
|
103
|
+
@cell_height = response[13]
|
104
|
+
|
105
|
+
@menu = Menu.new( self )
|
106
|
+
|
107
|
+
response = send_command( Command.new( "info" ) )
|
108
|
+
driver_info = response.message
|
109
|
+
|
110
|
+
LCDProc::Devices.find_all_that_drive( driver_info ).each do |device|
|
111
|
+
LCDProc::Client.send( :include, device )
|
112
|
+
end
|
113
|
+
|
114
|
+
@name = options[:name]
|
115
|
+
|
116
|
+
response = send_command( Command.new( "client_set -name #{@name}" ) )
|
117
|
+
|
118
|
+
@@client_count += 1
|
119
|
+
|
120
|
+
if self.respond_to?( :after_initialize ) then self.send( :after_initialize, options ) end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
# Adds a message to the client's message list. Used seperately from the responses returned by
|
125
|
+
# the LCDd server. If there are more than MAX_MESSAGES, the oldest message will be removed from
|
126
|
+
# the stack.
|
127
|
+
#
|
128
|
+
# * msg - The message to be added.
|
129
|
+
#
|
130
|
+
# Example:
|
131
|
+
#
|
132
|
+
# client.add_message( "Woah Man!!! Something is wrong!!!" )
|
133
|
+
def add_message( msg )
|
134
|
+
@messages.unshift( msg )
|
135
|
+
|
136
|
+
if @messages.length > MAX_MESSAGES
|
137
|
+
@messages.pop
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# Attaches a screen to this client.
|
143
|
+
#
|
144
|
+
# * screen - Any screen which contains any number of widgets.
|
145
|
+
#
|
146
|
+
# Example:
|
147
|
+
#
|
148
|
+
# s = Screen.new( 'MyTestScreen' )
|
149
|
+
# client.attach( s )
|
150
|
+
#
|
151
|
+
# or
|
152
|
+
#
|
153
|
+
# client.attach( Screen.new( 'MyTestScreen' ) )
|
154
|
+
def attach( screen )
|
155
|
+
|
156
|
+
if @screens.select{ |s| s.id == screen.id }.empty?
|
157
|
+
if screen.attach_to( self )
|
158
|
+
@screens << screen
|
159
|
+
screen.update
|
160
|
+
return true
|
161
|
+
else
|
162
|
+
return false
|
163
|
+
end
|
164
|
+
else
|
165
|
+
return false
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
# Detaches a screen from the client but leaves it in memory so that it may later be attached to another
|
172
|
+
# client or re-attached to this client.
|
173
|
+
#
|
174
|
+
# * <tt>screen</tt> - Any screen currently attached to this client.
|
175
|
+
#
|
176
|
+
# Example:
|
177
|
+
#
|
178
|
+
# client.detach( 'TestScreen' )
|
179
|
+
def detach( screen )
|
180
|
+
if @screens.include? screen
|
181
|
+
|
182
|
+
if screen.detach
|
183
|
+
@screens.delete( screen )
|
184
|
+
return true
|
185
|
+
else
|
186
|
+
return false
|
187
|
+
end
|
188
|
+
|
189
|
+
else
|
190
|
+
add_message "Error: Screen '#{screen.id}' is not attached to client '#{self.name}'"
|
191
|
+
return false
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
# Returns the last received message from the @messages array (internally more like a circular array).
|
197
|
+
#
|
198
|
+
# Example:
|
199
|
+
#
|
200
|
+
# puts client.message
|
201
|
+
def message
|
202
|
+
@messages.first
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
# Sets the name of the client
|
207
|
+
#
|
208
|
+
# * <tt>name</tt> - The new name of the client
|
209
|
+
#
|
210
|
+
# Example:
|
211
|
+
#
|
212
|
+
# client.name = 'MyGreatClient'
|
213
|
+
def name= name
|
214
|
+
response = send_command( Command.new( "client_set -name #{name}" ) )
|
215
|
+
|
216
|
+
if response.successful?
|
217
|
+
@name = name
|
218
|
+
|
219
|
+
return @name
|
220
|
+
else
|
221
|
+
error = "Error: Failed to set client's name to '#{name}'\n\n#{response.message}".gsub( /\n/, "\n " )
|
222
|
+
add_message error
|
223
|
+
|
224
|
+
raise InvalidCommand, error
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
# Register a new button event for the client to process and reserves the key.
|
230
|
+
def register_key_event( key_event )
|
231
|
+
|
232
|
+
if key_event and valid_keys.include? key_event.key
|
233
|
+
response = send_command( Command.new( "client_add_key -exclusively #{key_event.key}" ) )
|
234
|
+
|
235
|
+
if response.successful?
|
236
|
+
@global_key_events << key_event
|
237
|
+
return key_event
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
return nil
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
# Register a new menu event for the client to process
|
246
|
+
def register_menu_event( menu_event )
|
247
|
+
|
248
|
+
if menu_event
|
249
|
+
@menu_events << menu_event
|
250
|
+
return menu_event
|
251
|
+
else
|
252
|
+
return nil
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
# Sends a command to the server and returns a Response object. This is generally used for internal
|
259
|
+
# purposes, but has been opened to the public API in case LCDProc changes it's behaviour or adds new
|
260
|
+
# features. You should *NOT* use this to bypass the default behaviour such as setting a client's name.
|
261
|
+
#
|
262
|
+
# * <tt>command</tt> - The Command object that you wish to send to the server.
|
263
|
+
#
|
264
|
+
# Example:
|
265
|
+
#
|
266
|
+
# client.send_command( Command.new( 'info' ) )
|
267
|
+
def send_command( command )
|
268
|
+
|
269
|
+
puts "Command: " + command.message unless not DEBUG
|
270
|
+
if command.message.kind_of? String
|
271
|
+
|
272
|
+
@daemon_socket.write( command.message )
|
273
|
+
@commands << command
|
274
|
+
|
275
|
+
# NOTE: This extra get_response is here because LCDd will get confused if sent two messages very
|
276
|
+
# quickly when trying to add menu items to a menu. Hopefully it will be removed when they have their
|
277
|
+
# commands queued properly.
|
278
|
+
if command.message =~ /^menu_add_item/
|
279
|
+
r1 = get_response
|
280
|
+
|
281
|
+
if r1.message =~ /^success/
|
282
|
+
get_response
|
283
|
+
end
|
284
|
+
|
285
|
+
return r1
|
286
|
+
else
|
287
|
+
return get_response
|
288
|
+
end
|
289
|
+
|
290
|
+
elsif command.message.kind_of? Array
|
291
|
+
|
292
|
+
@daemon_socket.write( command.message.join("\n") )
|
293
|
+
@commands << command
|
294
|
+
return get_response( command.message.length )
|
295
|
+
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
# Unregisters a button event from the client
|
301
|
+
def unregister_key_event( key_event )
|
302
|
+
if @global_key_events.include? key_event
|
303
|
+
@global_key_events.delete key_event
|
304
|
+
return key_event
|
305
|
+
else
|
306
|
+
return nil
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
# Register a new menu event for the client to process
|
312
|
+
def unregister_menu_event( menu_event )
|
313
|
+
|
314
|
+
if @menu_events.include? menu_event
|
315
|
+
@menu_events.delete( menu_event )
|
316
|
+
return menu_event
|
317
|
+
else
|
318
|
+
return nil
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
|
323
|
+
# Returns the keys that may be registered for the client
|
324
|
+
def valid_keys
|
325
|
+
if VALID_KEYS
|
326
|
+
VALID_KEYS
|
327
|
+
else
|
328
|
+
[]
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
|
333
|
+
private
|
334
|
+
# Connects this client to a remote (or local) LCDd server.
|
335
|
+
#
|
336
|
+
# * <tt>:host</tt> - The remote host to which you wish to connect. Defaults to <i>"localhost"</i>.
|
337
|
+
# * <tt>:port</tt> - The port on which the TCP socket should be opened. Defaults to <i>13666</i>.
|
338
|
+
def connect( host, port )
|
339
|
+
daemon_socket = nil
|
340
|
+
|
341
|
+
begin
|
342
|
+
daemon_socket = TCPSocket.new( host, port )
|
343
|
+
rescue Errno::ECONNREFUSED
|
344
|
+
add_message "Connection to '#{host}':#{port} was refused"
|
345
|
+
end
|
346
|
+
|
347
|
+
return daemon_socket
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
# Blocks until a message is entered into the response queue, creates a new Response object
|
352
|
+
# and returns it to the requester.
|
353
|
+
def get_response( number_of_responses = 1 )
|
354
|
+
|
355
|
+
responses = []
|
356
|
+
|
357
|
+
1.upto( number_of_responses ) do |i|
|
358
|
+
response = @response_queue.pop
|
359
|
+
|
360
|
+
while response.nil?
|
361
|
+
Thread.pass
|
362
|
+
|
363
|
+
response = @response_queue.pop
|
364
|
+
end
|
365
|
+
|
366
|
+
puts "Q: #{@response_queue}, #{response}" unless not DEBUG
|
367
|
+
|
368
|
+
responses << response
|
369
|
+
end
|
370
|
+
|
371
|
+
if responses.length == 1
|
372
|
+
puts "returning one response" unless not DEBUG
|
373
|
+
|
374
|
+
return Response.new( responses[0] )
|
375
|
+
else
|
376
|
+
puts "returning multiple response: #{responses.length}" unless not DEBUG
|
377
|
+
|
378
|
+
return Response.new( responses )
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
|
383
|
+
# Controls processing the responses received from the LCDd server. This includes
|
384
|
+
# <tt>listen</tt> and <tt>ignore</tt> messages as well as button presses and responses to
|
385
|
+
# commands. Takes no arguments.
|
386
|
+
#
|
387
|
+
# This should be called via a thread in the client at least twice every second (currently
|
388
|
+
# set to fifty (50) times a second).
|
389
|
+
def process_responses
|
390
|
+
data = @daemon_socket.recv( 1024 )
|
391
|
+
|
392
|
+
puts "Data: " + data unless not DEBUG
|
393
|
+
array = data.split( "\n" )
|
394
|
+
|
395
|
+
puts "Array: #{array.inspect}" unless not DEBUG
|
396
|
+
|
397
|
+
array.each do |response|
|
398
|
+
puts "response: #{response} about to be processed" unless not DEBUG
|
399
|
+
|
400
|
+
# Process the listen event
|
401
|
+
if response =~ /^listen .*$/
|
402
|
+
|
403
|
+
@current_screen = @screens.find{ |s| s.id == response.split(' ').last }
|
404
|
+
puts " ! processing listen..." unless not DEBUG
|
405
|
+
|
406
|
+
|
407
|
+
|
408
|
+
# Process the ignore event
|
409
|
+
elsif response =~ /^ignore .*$/
|
410
|
+
|
411
|
+
puts " ! processing ignore..." unless not DEBUG
|
412
|
+
|
413
|
+
|
414
|
+
|
415
|
+
# Process menu events
|
416
|
+
elsif response =~ /^menuevent .*$/
|
417
|
+
|
418
|
+
puts " ! processing a menu event: #{response}" unless not DEBUG
|
419
|
+
|
420
|
+
@menu_events.each do |me|
|
421
|
+
if response =~ /^menuevent #{me.menu_item.lcdproc_event_type} #{me.menu_item.id}/
|
422
|
+
if me.block
|
423
|
+
me.block.call( response )
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
|
429
|
+
|
430
|
+
# Process key events
|
431
|
+
elsif response =~ /^key .*$/
|
432
|
+
key = response.split(' ').last
|
433
|
+
|
434
|
+
puts "Processing key #{key} in Client" unless not DEBUG
|
435
|
+
|
436
|
+
@global_key_events.each do |gbe|
|
437
|
+
if ( key == gbe.key ) and ( gbe.block )
|
438
|
+
gbe.block.call
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
@current_screen.process_key( key )
|
443
|
+
|
444
|
+
|
445
|
+
|
446
|
+
# Otherwise stick it in the queue
|
447
|
+
else
|
448
|
+
# If we don't know how to process it, assume that it is a response to a command
|
449
|
+
@response_queue << response
|
450
|
+
puts "response: #{response} added to queue" unless not DEBUG
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
end
|
455
|
+
|
456
|
+
end
|
457
|
+
|
458
|
+
end
|