File: device.rb

package info (click to toggle)
libfreenect 1%3A0.5.3-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,156 kB
  • sloc: ansic: 7,417; cpp: 7,265; cs: 2,062; python: 992; ruby: 873; java: 730; xml: 49; sh: 27; makefile: 23
file content (208 lines) | stat: -rw-r--r-- 6,249 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

require 'ffi/freenect'
require 'freenect/context'

module Freenect
  RawTiltState = FFI::Freenect::RawTiltState

  class DeviceError < StandardError
  end

  class Device
    # Returns a device object tracked by its ruby object reference ID stored
    # in user data.
    #
    # This method is intended for internal use.
    def self.by_reference(devp)
      unless devp.null? or (refp=FFI::Freenect.freenect_get_user(devp)).null?
        obj=ObjectSpace._id2ref(refp.read_long_long)
        return obj if obj.is_a?(Device)
      end
    end

    def initialize(ctx, idx)
      dev_p = ::FFI::MemoryPointer.new(:pointer)
      @ctx = ctx

      if ::FFI::Freenect.freenect_open_device(@ctx.context, dev_p, idx) != 0
        raise DeviceError, "unable to open device #{idx} from #{ctx.inspect}"
      end

      @dev = dev_p.read_pointer
      save_object_id!()
    end

    def closed?
      @ctx.closed? or (@dev_closed == true)
    end

    def close
      unless closed?
        if ::FFI::Freenect.freenect_close_device(@dev) == 0
          @dev_closed = true
        end
      end
    end

    def device
      if closed?
        raise DeviceError, "this device is closed and can no longer be used"
      else
        return @dev
      end
    end

    def context
      @ctx
    end

    def get_tilt_state
      unless (p=::FFI::Freenect.freenect_get_tilt_state(self.device)).null?
        return RawTiltState.new(p)
      else
        raise DeviceError, "freenect_get_tilt_state() returned a NULL tilt_state"
      end
    end

    alias tilt_state get_tilt_state

    # Returns the current tilt angle
    def get_tilt_degrees
      ::FFI::Freenect.freenect_get_tilt_degs(self.device)
    end

    alias tilt get_tilt_degrees

    # Sets the tilt angle.
    # Maximum tilt angle range is between +30 and -30
    def set_tilt_degrees(angle)
      ::FFI::Freenect.freenect_set_tilt_degs(self.device, angle)
      return(update_tilt_state() < 0) # based on libfreenect error cond. as of 12-21-10
    end

    alias tilt= set_tilt_degrees

    # Defines a handler for depth events.
    #
    # @yield [device, depth_buf, timestamp]
    # @yieldparam device     A pointer to the device that generated the event.
    # @yieldparam depth_buf  A pointer to the buffer containing the depth data.
    # @yieldparam timestamp  A timestamp for the event?
    def set_depth_callback(&block)
      @depth_callback = block
      ::FFI::Freenect.freenect_set_depth_callback(self.device, @depth_callback)
    end

    alias on_depth set_depth_callback

    # Defines a handler for video events.
    #
    # @yield [device, video_buf, timestamp]
    # @yieldparam device     A pointer to the device that generated the event.
    # @yieldparam video_buf  A pointer to the buffer containing the video data.
    # @yieldparam timestamp  A timestamp for the event?
    def set_video_callback(&block)
      @video_callback = block
      ::FFI::Freenect.freenect_set_video_callback(self.device, @video_callback)
    end

    alias on_video set_video_callback

    def start_depth
      unless(::FFI::Freenect.freenect_start_depth(self.device) == 0)
        raise DeviceError, "Error in freenect_start_depth()"
      end
    end

    def stop_depth
      unless(::FFI::Freenect.freenect_stop_depth(self.device) == 0)
        raise DeviceError, "Error in freenect_stop_depth()"
      end
    end

    def start_video
      unless(::FFI::Freenect.freenect_start_video(self.device) == 0)
        raise DeviceError, "Error in freenect_start_video()"
      end
    end

    def stop_video
      unless(::FFI::Freenect.freenect_stop_video(self.device) == 0)
        raise DeviceError, "Error in freenect_stop_video()"
      end
    end

    def set_depth_mode(mode)
      mode = Freenect.depth_mode(:medium, mode) unless mode.is_a?(Freenect::FrameMode)
      raise ArgumentError, "Unkown depth mode #{mode}" if mode.nil?    
      ret = ::FFI::Freenect.freenect_set_depth_mode(self.device, mode)
      raise DeviceError, "Error calling freenect_set_depth_mode(self, #{mode}) returned #{ret}" unless ret == 0
    end
    alias depth_mode= set_depth_mode
    
    # returns the symbolic constant for the current depth format
    def depth_mode
      x = ::FFI::Freenect.freenect_get_current_depth_mode(self.device)
      x = nil if x.height*x.width == 0 or x.framerate == 0
      x.frame_mode_type = :depth unless x.nil?
      x
    end

    # Sets the video format to one of the following accepted values:
    #
    def set_video_mode(mode)
      mode = Freenect.video_mode(:medium, mode) unless mode.is_a?(Freenect::FrameMode)
      raise ArgumentError, "Unkown video mode #{mode}" if mode.nil?    
      ret = ::FFI::Freenect.freenect_set_video_mode(self.device, mode)
      raise DeviceError, "Error calling freenect_set_video_mode(self, #{mode}) returned #{ret}" unless ret == 0
    end
    alias video_mode= set_video_mode

    def video_mode
      x = ::FFI::Freenect.freenect_get_current_video_mode(self.device)
      x = nil if x.height*x.width == 0 or x.framerate == 0
      x.frame_mode_type = :video unless x.nil?
      x
    end

    # Sets the led to one of the following accepted values:
    #   :off,               Freenect::LED_OFF
    #   :green,             Freenect::LED_GREEN
    #   :red,               Freenect::LED_RED
    #   :yellow,            Freenect::LED_YELLOW
    #   :blink_yellow,      Freenect::LED_BLINK_YELLOW
    #   :blink_green,       Freenect::LED_BLINK_GREEN
    #   :blink_red_yellow,  Freenect::LED_BLINK_RED_YELLOW
    #
    # Either the symbol or numeric constant can be specified.
    def set_led(mode)
      return(::FFI::Freenect.freenect_set_led(self.device, mode) == 0)
    end

    alias led= set_led

    def reference_id
      unless (p=::FFI::Freenect.freenect_get_user(device)).null?
        p.read_long_long
      end
    end

    private
    def set_depth_buffer(buf)
    end

    def set_video_buffer(buf)
    end

    def save_object_id!
      objid_p = FFI::MemoryPointer.new(:long_long)
      objid_p.write_long_long(self.object_id)
      ::FFI::Freenect.freenect_set_user(self.device, objid_p)
    end

    def update_tilt_state
      ::FFI::Freenect.freenect_update_tilt_state(self.device)
    end

  end
end