gyruby 0.1.1 → 0.1.3

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.
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'gyruby'
5
+
6
+ class RemoteRunner
7
+ @@class_to_run = MplayerController
8
+ def self.class_to_run=(c)
9
+ @@class_to_run = c
10
+ end
11
+ def self.gyration_pids
12
+ `pidof -x #{File.basename($0)}`.split.select do |pid|
13
+ pid.to_s != $$.to_s
14
+ end
15
+ end
16
+ def self.start
17
+ if gyration_pids.empty?
18
+ child_pid = fork do
19
+ grandchild_pid = fork do
20
+ c = @@class_to_run.new
21
+ c.listen
22
+ end
23
+ end
24
+ Process.wait(child_pid)
25
+ return 0
26
+ else
27
+ return 1
28
+ end
29
+ end
30
+ def self.stop
31
+ pids = gyration_pids
32
+ if pids.empty?
33
+ return 1
34
+ else
35
+ gyration_pids.each do |pid|
36
+ `kill #{pid}`
37
+ end
38
+ return 0
39
+ end
40
+ end
41
+ def self.go!
42
+ if ARGV.size != 1 || !["start", "stop"].include?(ARGV.first)
43
+ STDERR.puts("Usage: #{$0} start|stop")
44
+ exit 1
45
+ end
46
+ self.send(ARGV.first)
47
+ end
48
+ end
49
+
50
+ if File.basename($0) == File.basename(__FILE__)
51
+ exit RemoteRunner.go!
52
+ end
data/ext/gyruby_ext.c CHANGED
@@ -375,6 +375,73 @@ rb_remote_get_grabbed_mouse(VALUE self) {
375
375
  return Qtrue;
376
376
  }
377
377
 
378
+ static VALUE
379
+ rb_remote_send_key(VALUE self, VALUE state, VALUE keycode) {
380
+ c_remote *this;
381
+ gboolean grabbed_display = FALSE;
382
+ XEvent event;
383
+ Window focus;
384
+ int focus_return;
385
+
386
+ Check_Type(keycode, T_FIXNUM);
387
+ C_REMOTE(self, this);
388
+ if (this->display == NULL) {
389
+ this->display = XOpenDisplay(NULL);
390
+ grabbed_display = TRUE;
391
+ }
392
+ XGetInputFocus(this->display, &focus, &focus_return);
393
+
394
+ event.xkey.type = KeyPress;
395
+ event.xkey.root = XDefaultRootWindow(this->display);
396
+ event.xkey.window = focus;
397
+ event.xkey.subwindow = None;
398
+ event.xkey.keycode = NUM2INT(keycode);
399
+ event.xkey.same_screen = True;
400
+ event.xkey.time = CurrentTime;
401
+ event.xkey.x = 1;
402
+ event.xkey.y = 1;
403
+ event.xkey.x_root = 1;
404
+ event.xkey.y_root = 1;
405
+ event.xkey.state = NUM2INT(state);
406
+ XSendEvent(this->display, InputFocus, True, KeyPressMask, &event);
407
+ event.xkey.type = KeyRelease;
408
+ XSendEvent(this->display, InputFocus, True, KeyReleaseMask, &event);
409
+ if (grabbed_display) {
410
+ XCloseDisplay(this->display);
411
+ this->display = NULL;
412
+ }
413
+ return self;
414
+ }
415
+
416
+ static VALUE
417
+ rb_remote_close_active(VALUE self) {
418
+ c_remote *this;
419
+ Window active;
420
+ gint revert_to_return;
421
+ gboolean grabbed_display = FALSE;
422
+
423
+ C_REMOTE(self, this);
424
+
425
+ if (this->display == NULL) {
426
+ this->display = XOpenDisplay(NULL);
427
+ grabbed_display = TRUE;
428
+ }
429
+
430
+ XGetInputFocus(this->display, &active, &revert_to_return);
431
+ if (active != XDefaultRootWindow(this->display)) {
432
+ XSync(this->display, 0);
433
+ XDestroyWindow(this->display, active);
434
+ XSync(this->display, 0);
435
+ }
436
+
437
+ if (grabbed_display) {
438
+ XCloseDisplay(this->display);
439
+ this->display = NULL;
440
+ }
441
+
442
+ return self;
443
+ }
444
+
378
445
  #ifdef __cplusplus
379
446
  extern "C" {
380
447
  #endif
@@ -401,6 +468,8 @@ extern "C" {
401
468
  rb_define_private_method(rb_remote, "fetch_mouse_event", rb_remote_fetch_mouse_event, 0);
402
469
  rb_define_private_method(rb_remote, "claimed_device?", rb_remote_get_claimed_device, 0);
403
470
  rb_define_private_method(rb_remote, "grabbed_mouse?", rb_remote_get_grabbed_mouse, 0);
471
+ rb_define_private_method(rb_remote, "send_key", rb_remote_send_key, 2);
472
+ rb_define_private_method(rb_remote, "close_active", rb_remote_close_active, 0);
404
473
  }
405
474
  #ifdef __cplusplus
406
475
  }
@@ -18,8 +18,10 @@
18
18
  require 'pathname'
19
19
 
20
20
  class MplayerController < Gyruby::Remote
21
+
22
+ MAX_SKIP = 16.0
21
23
 
22
- def initialize(user)
24
+ def initialize
23
25
  super()
24
26
  subscribe("\b%\377\351\000\000") do |s|
25
27
  volume_up
@@ -34,26 +36,67 @@ class MplayerController < Gyruby::Remote
34
36
  osd_down
35
37
  end
36
38
  subscribe("\b%\377\313\000\000", "\b%\377\000\000\000") do |key, options|
37
- seek(options[:x].to_f/ options[:xmax].to_f)
39
+ seek(options[:x].to_f / options[:xmax].to_f)
40
+ end
41
+ subscribe("\b%\377\314\000\000") do |s|
42
+ start_skip
43
+ end
44
+ subscribe("\b%\377\000\000\000") do |s|
45
+ stop_skip
46
+ end
47
+ subscribe("\b%\377\314\000\000", "\b%\377\000\000\000") do |key, options|
48
+ @skip_speed = (((options[:x] * 2.0) / options[:xmax]) - 1.0) * MAX_SKIP
49
+ end
50
+ subscribe("\b%\377\315\000\000", "\b%\377\000\000\000") do |key, options|
51
+ volume(options[:x].to_f / options[:xmax].to_f)
38
52
  end
39
53
  @osd = 0
40
- @user = user
54
+ @skip_thread = nil
55
+ @skip_speed = 0.0
41
56
  end
42
57
 
43
58
  private
44
59
 
60
+ def start_skip
61
+ @skip_thread ||= Thread.new do
62
+ begin
63
+ sleep_started = Time.now
64
+ loop do
65
+ if @skip_speed != 0
66
+ if Time.now - sleep_started > (1.0 / @skip_speed.abs)
67
+ send_command("seek #{@skip_speed > 0 ? 1 : -1}")
68
+ sleep_started = Time.now
69
+ end
70
+ end
71
+ sleep 0.01
72
+ end
73
+ rescue Exception => e
74
+ STDERR.puts e
75
+ STDERR.puts e.backtrace.join("\n")
76
+ end
77
+ end
78
+ end
79
+
80
+ def stop_skip
81
+ @skip_thread.kill if @skip_thread.respond_to?(:alive?) && @skip_thread.alive?
82
+ @skip_thread = nil
83
+ end
84
+
45
85
  def send_command(cmd)
46
- ctrl_path = Pathname.new(File.join("/home", @user, ".mplayer", "fifo"))
86
+ ctrl_path = Pathname.new(File.join(ENV["HOME"], ".mplayer", "fifo"))
47
87
  ctrl_path.open("a") do |ctrl|
48
88
  ctrl.puts(cmd)
49
89
  end if ctrl_path.exist? && mplayer_running?
50
90
  end
51
91
 
52
92
  def seek(f)
53
- puts f.inspect
54
93
  send_command("seek #{f * 100} 1")
55
94
  end
56
95
 
96
+ def volume(f)
97
+ send_command("volume #{f * 100} 1")
98
+ end
99
+
57
100
  def osd_up
58
101
  @osd += 1 if @osd < 3
59
102
  send_command("osd #{@osd}")
@@ -77,7 +120,7 @@ class MplayerController < Gyruby::Remote
77
120
  STDOUT.reopen(open("/dev/null", "w"))
78
121
  args = ["/usr/bin/env",
79
122
  "pgrep",
80
- "-U", @user,
123
+ "-U", ENV["USER"],
81
124
  "mplayer"]
82
125
  exec(*args)
83
126
  end
data/lib/gyruby/remote.rb CHANGED
@@ -15,10 +15,28 @@
15
15
  # along with this program; if not, write to the Free Software
16
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
+ require 'set'
19
+
18
20
  module Gyruby
19
21
 
20
22
  class Remote
21
23
 
24
+ class MouseButton
25
+ attr_accessor :action, :block, :frequency, :last, :event, :press
26
+ def initialize(options)
27
+ @event, @block, @frequency = options.delete(:event), options.delete(:block), options.delete(:frequency)
28
+ @last = nil
29
+ @action = :press
30
+ @press = self
31
+ end
32
+ def release(event)
33
+ rval = self.clone
34
+ rval.action = :release
35
+ rval.event = event
36
+ return rval
37
+ end
38
+ end
39
+
22
40
  def initialize
23
41
  @subscribed_buttons = {}
24
42
  @pressed_buttons = {}
@@ -26,17 +44,16 @@ module Gyruby
26
44
  @listening = false
27
45
  end
28
46
 
29
- def subscribe(button, release = false, frequency = 10, &block)
47
+ def subscribe(press, release = false, frequency = 10, &block)
30
48
  if release
31
- @mouse_buttons[button] = {
32
- :action => :press,
33
- :block => block,
34
- :frequency => frequency,
35
- :last => nil
36
- }
37
- @mouse_buttons[release] = {:action => :release, :press => button}
49
+ button = MouseButton.new(:block => block, :frequency => frequency, :event => press)
50
+ @mouse_buttons[press] ||= []
51
+ @mouse_buttons[press] << button
52
+ @mouse_buttons[release] ||= []
53
+ @mouse_buttons[release] << button.release(release)
38
54
  else
39
- @subscribed_buttons[button] = block
55
+ @subscribed_buttons[press] ||= []
56
+ @subscribed_buttons[press] << block
40
57
  end
41
58
  end
42
59
 
@@ -62,27 +79,39 @@ module Gyruby
62
79
 
63
80
  def handle_usb_event
64
81
  event = fetch_usb_event
65
- if block = @subscribed_buttons[event]
66
- block.call(event)
82
+ if blocks = @subscribed_buttons[event]
83
+ blocks.each do |block|
84
+ block.call(event)
85
+ end
67
86
  end
68
- if button_status = @mouse_buttons[event]
69
- if button_status[:action] == :press
70
- @pressed_buttons[event] = button_status
71
- grab_mouse unless grabbed_mouse?
72
- elsif button_status[:action] == :release
73
- @pressed_buttons.delete(button_status[:press])
74
- ungrab_mouse if grabbed_mouse? && @pressed_buttons.empty?
87
+ if mouse_buttons = @mouse_buttons[event]
88
+ mouse_buttons.each do |button|
89
+ if button.action == :press
90
+ @pressed_buttons[button.event] ||= Set.new
91
+ @pressed_buttons[button.event] << button
92
+ grab_mouse unless grabbed_mouse?
93
+ elsif button.action == :release
94
+ if buttons = @pressed_buttons[button.press.event]
95
+ buttons.delete(button.press)
96
+ if buttons.empty?
97
+ @pressed_buttons.delete(button.press.event)
98
+ end
99
+ end
100
+ ungrab_mouse if grabbed_mouse? && @pressed_buttons.empty?
101
+ end
75
102
  end
76
103
  end
77
104
  end
78
105
 
79
106
  def handle_mouse_event
80
107
  mouse_event = fetch_mouse_event
81
- @pressed_buttons.each do |key_event, button_status|
82
- button_status[:last] ||= Time.now
83
- if (Time.now - button_status[:last]) > 1.0 / button_status[:frequency]
84
- @mouse_buttons[key_event][:block].call(key_event, mouse_event)
85
- button_status[:last] = Time.now
108
+ @pressed_buttons.each do |key_event, buttons|
109
+ buttons.each do |button|
110
+ button.last ||= Time.now
111
+ if (Time.now - button.last) > 1.0 / button.frequency
112
+ button.block.call(key_event, mouse_event)
113
+ button.last = Time.now
114
+ end
86
115
  end
87
116
  end unless mouse_event.nil?
88
117
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gyruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Kihlgren
@@ -9,22 +9,23 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-26 00:00:00 +02:00
12
+ date: 2008-06-06 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
16
  description:
17
17
  email: gyruby at troja dot ath dot cx
18
- executables: []
19
-
18
+ executables:
19
+ - gyration_remote
20
20
  extensions:
21
21
  - ext/extconf.rb
22
22
  extra_rdoc_files: []
23
23
 
24
24
  files:
25
- - lib/gyruby.rb
26
- - lib/gyruby/remote.rb
27
25
  - lib/gyruby/mplayer_controller.rb
26
+ - lib/gyruby/remote.rb
27
+ - lib/gyruby.rb
28
+ - bin/gyration_remote
28
29
  - ext/extconf.rb
29
30
  - ext/gyruby_ext.c
30
31
  has_rdoc: true
@@ -50,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
51
  requirements: []
51
52
 
52
53
  rubyforge_project:
53
- rubygems_version: 1.1.1
54
+ rubygems_version: 1.0.1
54
55
  signing_key:
55
56
  specification_version: 2
56
57
  summary: A ruby binding for the Gyration FiireChief remote control for LinuxMCE.