Class: Zmb

Inherits:
Object
  • Object
show all
Defined in:
lib/zmb.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config_dir) ⇒ Zmb

Returns a new instance of Zmb.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/zmb.rb', line 22

def initialize(config_dir)
  @debug = true
  
  @plugin_manager = PluginManager.new
  @settings_manager = Settings.new(config_dir)
  
  @instances = {'zmb' => self}
  @sockets = Hash.new
  
  @minimum_timeout = 0.5 # Half a second
  @maximum_timeout = 60.0 # Sixty seconds
  @timers = Array.new
  timer_add(Timer.new(self, :save, 120.0, true)) # Save every 2 minutes
  
  plugin_dir = File.join(@settings_manager.directory, 'plugins')
  if not File.exist?(plugin_dir) then
    FileUtils.makedirs(plugin_dir)
  end
  
  @plugin_sources = @settings_manager.get('zmb', 'plugin_sources', [])
  @plugin_sources.each{ |source| @plugin_manager.add_plugin_source source }
  @plugin_manager.add_plugin_source File.join(File.expand_path(File.dirname(File.dirname(__FILE__))), 'plugins')
  @plugin_manager.add_plugin_source plugin_dir
  
  @settings_manager.get('zmb', 'plugin_instances', []).each{|instance| load instance}
  
  @running = false
end

Instance Attribute Details

#instancesObject

Returns the value of attribute instances.



16
17
18
# File 'lib/zmb.rb', line 16

def instances
  @instances
end

#plugin_managerObject

Returns the value of attribute plugin_manager.



16
17
18
# File 'lib/zmb.rb', line 16

def plugin_manager
  @plugin_manager
end

#plugin_sourcesObject

Returns the value of attribute plugin_sources.



16
17
18
# File 'lib/zmb.rb', line 16

def plugin_sources
  @plugin_sources
end

#settings_managerObject

Returns the value of attribute settings_manager.



16
17
18
# File 'lib/zmb.rb', line 16

def settings_manager
  @settings_manager
end

Instance Method Details

#addsource_command(e, source) ⇒ Object



315
316
317
318
319
# File 'lib/zmb.rb', line 315

def addsource_command(e, source)
  @plugin_sources << source
  @plugin_manager.add_plugin_source source
  "#{source} added to plugin manager"
end

#clone_command(e, instance, new_instance) ⇒ Object



301
302
303
304
305
306
307
308
# File 'lib/zmb.rb', line 301

def clone_command(e, instance, new_instance)
  if (settings = @settings_manager.setting(instance)) != {} then
    @settings_manager.save(new_instance, settings)
    "The settings for #{instance} were copied to #{new_instance}"
  else
    "No settings for #{instance}"
  end
end

#commandsObject



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/zmb.rb', line 208

def commands
  {
    'reload' => [:reload_command, 1, { :permission => 'admin' }],
    'unload' => [:unload_command, 1, { :permission => 'admin' }],
    'load' => [:load_command, 1, { :permission => 'admin' }],
    'save' => [:save_command, 0, { :permission => 'admin' }],
    'loaded' => [:loaded_command, 0, { :permission => 'admin' }],
    'setup' => [:setup_command, 2, { :permission => 'admin' }],
    'set' => [:set_command, 3, { :permission => 'admin' }],
    'get' => [:get_command, 2, { :permission => 'admin' }],
    'clone' => [:clone_command, 2, { :permission => 'admin' }],
    'reset' => [:reset_command, 1, { :permission => 'admin' }],
    'addsource' => [:addource_command, 1, { :permission => 'admin' }],
    'refresh' => [:refresh_command, 1, { :permission => 'admin' }],
  }
end

#event(sender, e) ⇒ Object



199
200
201
202
203
204
205
206
# File 'lib/zmb.rb', line 199

def event(sender, e)
  puts e.line if @debug and e.respond_to?('line')
  
  Thread.new do
    post! :pre_event, sender, e
    post! :event, sender, e
  end
end

#get_command(e, instance, key) ⇒ Object



293
294
295
296
297
298
299
# File 'lib/zmb.rb', line 293

def get_command(e, instance, key)
  if value = @settings_manager.get(instance, key) then
    "#{key} is #{value} for #{instance}"
  else
    "#{instance} or #{instance}/#{key} not found."
  end
end

#load(key) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/zmb.rb', line 66

def load(key)
  return true if @instances.has_key?(key)
  
  if p = @settings_manager.get(key, 'plugin') then
    object = @plugin_manager.plugin(p)
    return false if not object
    @instances[key] = object.new(self, @settings_manager.setting(key))
    @instances[key].class.send(:define_method, :plugin) { p }
    @instances[key].class.send(:define_method, :instance) { key }
    post! :plugin_loaded, key, @instances[key]
    true
  else
    false
  end
end

#load_command(e, instance) ⇒ Object



251
252
253
254
255
256
257
# File 'lib/zmb.rb', line 251

def load_command(e, instance)
  if not @instances.has_key?(instance) then
    load(instance) ? "#{instance} loaded" : "#{instance} did not load correctly"
  else
    "Instance already loaded #{instance}"
  end
end

#loaded_command(e) ⇒ Object



264
265
266
# File 'lib/zmb.rb', line 264

def loaded_command(e)
  @instances.keys.join(', ')
end

#pluginObject



18
19
20
# File 'lib/zmb.rb', line 18

def plugin
  'zmb'
end

#post(signal, *args) ⇒ Object



166
167
168
169
170
171
172
173
174
# File 'lib/zmb.rb', line 166

def post(signal, *args)
  results = Array.new
  
  @instances.select{|name, instance| instance.respond_to?(signal)}.each do |name, instance|
    results << instance.send(signal, *args) rescue nil
  end
  
  results
end

#post!(signal, *args) ⇒ Object

This will exclude the plugin manager



176
177
178
179
180
# File 'lib/zmb.rb', line 176

def post!(signal, *args) # This will exclude the plugin manager
  @instances.select{|name, instance| instance.respond_to?(signal) and instance != self}.each do |name, instance|
    instance.send(signal, *args) rescue nil
  end
end

#refresh_command(e) ⇒ Object



321
322
323
324
# File 'lib/zmb.rb', line 321

def refresh_command(e)
  @plugin_manager.refresh_plugin_sources
  "Refreshed plugin sources"
end

#reload_command(e, instance) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/zmb.rb', line 225

def reload_command(e, instance)
  if @instances.has_key?(instance) then
    sockets = Array.new
    @sockets.each{ |sock,delegate| sockets << sock if delegate == @instances[instance] }
    unload(instance, false)
    reloaded = @plugin_manager.reload_plugin(@settings_manager.get(instance, 'plugin'))
    load(instance)
    
    sockets.each{ |socket| @sockets[socket] = @instances[instance] }
    @instances[instance].socket = sockets[0] if sockets.size == 1 and @instances[instance].respond_to?('socket=')
    
    reloaded ? "#{instance} reloaded" : "#{instance} refreshed"
  else
    "No such instance #{instance}"
  end
end

#reset_command(e, instance) ⇒ Object



310
311
312
313
# File 'lib/zmb.rb', line 310

def reset_command(e, instance)
  @settings_manager.save(instance, {})
  "Settings for #{instance} have been deleted."
end

#runObject



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/zmb.rb', line 92

def run
  post! :running, self
  
  @running = true
  begin
    while @running
      socket_run(timeout)
      timer_run
    end
  rescue Interrupt
    save
  end
end

#running?Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/zmb.rb', line 51

def running?
  @running
end

#saveObject



62
63
64
# File 'lib/zmb.rb', line 62

def save
  @instances.each{ |k,v| @settings_manager.save(k, v) }
end

#save_command(e) ⇒ Object



259
260
261
262
# File 'lib/zmb.rb', line 259

def save_command(e)
  save
  'settings saved'
end

#set_command(e, instance, key, value) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
# File 'lib/zmb.rb', line 281

def set_command(e, instance, key, value)
  settings = @settings_manager.setting(instance)
  settings[key] = value
  @settings_manager.save(instance, settings)
  
  if @instances.has_key?(instance) and @instances[instance].respond_to?('update') then
    @instances[instance].update(key, value)
  end
  
  "#{key} set to #{value} for #{instance}"
end

#settingsObject



55
56
57
58
59
60
# File 'lib/zmb.rb', line 55

def settings
  {
    'plugin_sources' => @plugin_sources,
    'plugin_instances' => @instances.keys,
  }
end

#setup(plugin, instance) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/zmb.rb', line 182

def setup(plugin, instance)
  object = @plugin_manager.plugin plugin
  return false if not object
  
  s = Hash.new
  s['plugin'] = plugin
  
  if object.respond_to? 'wizard' then
    d = object.wizard
    d.each{ |k,v| s[k] = v['default'] if v.has_key?('default') and v['default'] }
  end
  
  @settings_manager.save instance, s
  
  true
end

#setup_command(e, plugin, instance = nil) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/zmb.rb', line 268

def setup_command(e, plugin, instance=nil)
  instance = plugin if not instance
  
  if setup(plugin, instance) then
    object = @plugin_manager.plugin plugin
    result = ["Instance saved, please use the set command to override the default configuration for this instance."]
    result += object.wizard.map{ |k,v| "#{k} - #{v['help']} (default=#{v['default']})" } if object.respond_to? 'wizard'
    result.join("\n")
  else
    "plugin not found"
  end
end

#socket_add(delegate, socket) ⇒ Object



120
121
122
# File 'lib/zmb.rb', line 120

def socket_add(delegate, socket)
  @sockets[socket] = delegate
end

#socket_delete(item) ⇒ Object



124
125
126
127
128
129
130
131
132
# File 'lib/zmb.rb', line 124

def socket_delete(item)
  if @sockets.has_value?(item) then
    @sockets.select{ |sock, delegate| delegate == item }.each{ |sock, delegate| @sockets.delete(sock) }
  end
  
  if @sockets.has_key?(item) then
    @sockets.delete(item)
  end
end

#socket_run(timeout) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/zmb.rb', line 134

def socket_run(timeout)
  result = select(@sockets.keys, nil, nil, timeout)
  
  if result != nil then
    result[0].select{|sock| @sockets.has_key?(sock)}.each do |sock|
      if sock.eof? then
        @sockets[sock].disconnected(self, sock) if @sockets[sock].respond_to?('disconnected')
        socket_delete sock
      else
        @sockets[sock].received(self, sock, sock.gets()) if @sockets[sock].respond_to?('received')
      end
    end
  end
end

#timeoutObject



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/zmb.rb', line 106

def timeout
  if timer_timeout > @maximum_timeout
    if @sockets.size < 1 then
      5
    else
      @maximum_timeout
    end
  elsif timer_timeout > @minimum_timeout
    timer_timeout
  else
    @minimum_timeout
  end
end

#timer_add(timer) ⇒ Object



149
150
151
# File 'lib/zmb.rb', line 149

def timer_add(timer)
  @timers << timer
end

#timer_delete(search) ⇒ Object



153
154
155
156
# File 'lib/zmb.rb', line 153

def timer_delete(search)
  @timers.each{ |timer| @timers.delete(timer) if timer.delegate == search }
  @timers.delete(search)
end

#timer_runObject



162
163
164
# File 'lib/zmb.rb', line 162

def timer_run
  @timers.select{|timer| timer.timeout <= 0.0 and timer.respond_to?("fire") }.each{|timer| timer.fire(self)}
end

#timer_timeoutObject

When will the next timer run?



158
159
160
# File 'lib/zmb.rb', line 158

def timer_timeout # When will the next timer run?
  @timers.map{|timer| timer.timeout}.sort.fetch(0, @maximum_timeout)
end

#unload(key, tell = true) ⇒ Object



82
83
84
85
86
87
88
89
90
# File 'lib/zmb.rb', line 82

def unload(key, tell=true)
  return false if not @instances.has_key?(key)
  instance = @instances.delete(key)
  @settings_manager.save key, instance
  socket_delete instance
  timer_delete instance
  instance.unloaded if instance.respond_to?('unloaded') and tell
  post! :plugin_unloaded, key, instance
end

#unload_command(e, instance) ⇒ Object



242
243
244
245
246
247
248
249
# File 'lib/zmb.rb', line 242

def unload_command(e, instance)
  if @instances.has_key?(instance) then
    unload(instance)
    "#{instance} unloaded"
  else
    "No such instance #{instance}"
  end
end