dde 0.2.9 → 0.2.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,38 +1,38 @@
1
- # Quick and dirty DDE Library
2
-
3
- require 'ffi'
4
- require 'win/dde'
5
- require 'win/gui/message'
6
- require_relative 'exp_lib'
7
-
8
- module DDELib
9
- extend FFI::Library
10
- CP_WINANSI = 1004
11
- DNS_REGISTER = 1
12
- APPCLASS_STANDARD = 0
13
- CF_TEXT = 1
14
-
15
- XTYPF_NOBLOCK = 0x0002
16
- XCLASS_BOOL = 0x1000
17
- XCLASS_FLAGS = 0x4000
18
- XTYP_CONNECT = 0x0060 | XCLASS_BOOL | XTYPF_NOBLOCK
19
- XTYP_POKE = 0x0090 | XCLASS_FLAGS
20
- XTYP_EXECUTE = 0x0050 | XCLASS_FLAGS
21
- TIMEOUT_ASYNC = 0xFFFFFFFF
22
-
23
- DDE_FACK = 0x8000
24
-
25
- ffi_lib 'user32', 'kernel32' # Default library
26
- ffi_convention :stdcall
27
-
28
- callback :DdeCallback, [:uint, :uint, :ulong, :pointer, :pointer, :pointer, :pointer], :ulong
29
-
30
- attach_function(:DdeInitializeA, [:pointer, :DdeCallback, :uint32, :uint32], :uint)
31
- attach_function(:DdeCreateStringHandleA, [:uint32, :pointer, :int], :ulong)
32
- attach_function :DdeNameService, [:uint32, :ulong, :ulong, :uint], :ulong
33
- attach_function(:DdeConnect, [:uint32, :ulong, :ulong, :pointer], :ulong)
34
- attach_function :DdeDisconnect, [:ulong], :int
35
- attach_function(:DdeClientTransaction, [:pointer, :uint32, :ulong, :ulong, :uint, :uint, :uint32, :pointer], :pointer)
36
- attach_function :DdeGetLastError, [:uint32], :int
37
- end
38
-
1
+ # Quick and dirty DDE Library
2
+
3
+ require 'ffi'
4
+ require 'win/dde'
5
+ require 'win/gui/message'
6
+ require_relative 'exp_lib'
7
+
8
+ module DdeLib
9
+ extend FFI::Library
10
+ CP_WINANSI = 1004
11
+ DNS_REGISTER = 1
12
+ APPCLASS_STANDARD = 0
13
+ CF_TEXT = 1
14
+
15
+ XTYPF_NOBLOCK = 0x0002
16
+ XCLASS_BOOL = 0x1000
17
+ XCLASS_FLAGS = 0x4000
18
+ XTYP_CONNECT = 0x0060 | XCLASS_BOOL | XTYPF_NOBLOCK
19
+ XTYP_POKE = 0x0090 | XCLASS_FLAGS
20
+ XTYP_EXECUTE = 0x0050 | XCLASS_FLAGS
21
+ TIMEOUT_ASYNC = 0xFFFFFFFF
22
+
23
+ DDE_FACK = 0x8000
24
+
25
+ ffi_lib 'user32', 'kernel32' # Default library
26
+ ffi_convention :stdcall
27
+
28
+ callback :DdeCallback, [:uint, :uint, :ulong, :pointer, :pointer, :pointer, :pointer], :ulong
29
+
30
+ attach_function(:DdeInitializeA, [:pointer, :DdeCallback, :uint32, :uint32], :uint)
31
+ attach_function(:DdeCreateStringHandleA, [:uint32, :pointer, :int], :ulong)
32
+ attach_function :DdeNameService, [:uint32, :ulong, :ulong, :uint], :ulong
33
+ attach_function(:DdeConnect, [:uint32, :ulong, :ulong, :pointer], :ulong)
34
+ attach_function :DdeDisconnect, [:ulong], :int
35
+ attach_function(:DdeClientTransaction, [:pointer, :uint32, :ulong, :ulong, :uint, :uint, :uint32, :pointer], :pointer)
36
+ attach_function :DdeGetLastError, [:uint32], :int
37
+ end
38
+
@@ -1,44 +1,44 @@
1
- # Quick and dirty DDE Server (for experimentation)
2
-
3
- require 'win/gui/message'
4
- include Win::GUI::Message
5
-
6
- #require_relative 'exp_lib'
7
- #include DDELib
8
-
9
- require 'win/dde'
10
- include Win::DDE
11
-
12
- calls = []
13
- buffer = FFI::MemoryPointer.new(:long).write_long(0)
14
- buffer.address
15
-
16
- callback = lambda do |*args|
17
- calls << [*args]
18
- puts "#{Time.now.strftime('%T.%6N')} #{args.map{|e|e.respond_to?(:address) ? e.address : (Win::DDE::TYPES[e] || e)}}"
19
- args.first == XTYP_CONNECT ? 1 : DDE_FACK
20
- end
21
-
22
- status = DdeInitialize(buffer, callback, APPCLASS_STANDARD, 0)
23
- id = buffer.read_long
24
-
25
- service = FFI::MemoryPointer.from_string('test_service')
26
-
27
- p handle = DdeCreateStringHandle(id, service, CP_WINANSI)
28
-
29
- p DdeNameService(id, handle, 0, DNS_REGISTER)
30
-
31
- #p DdeDisconnect(conv_handle)
32
-
33
- msg = Msg.new # pointer to Msg FFI struct
34
-
35
- # Starting message loop (necessary for DDE processing)
36
- puts "Starting message loop\n"
37
- while msg = get_message()
38
- translate_message(msg)
39
- dispatch_message(msg)
40
- end
41
-
42
- p calls.map{|c| c.map{|e|e.respond_to?(:address) ? e.address : (Win::DDE::TYPES[e] || e)}}
43
-
44
- p Win::DDE::ERRORS[DdeGetLastError(id)]
1
+ # Quick and dirty DDE Server (for experimentation)
2
+
3
+ require 'win/gui/message'
4
+ include Win::GUI::Message
5
+
6
+ #require_relative 'exp_lib'
7
+ #include DdeLib
8
+
9
+ require 'win/dde'
10
+ include Win::Dde
11
+
12
+ calls = []
13
+ buffer = FFI::MemoryPointer.new(:long).write_long(0)
14
+ buffer.address
15
+
16
+ callback = lambda do |*args|
17
+ calls << [*args]
18
+ puts "#{Time.now.strftime('%T.%6N')} #{args.map{|e|e.respond_to?(:address) ? e.address : (Win::Dde::TYPES[e] || e)}}"
19
+ args.first == XTYP_CONNECT ? 1 : DDE_FACK
20
+ end
21
+
22
+ status = DdeInitialize(buffer, callback, APPCLASS_STANDARD, 0)
23
+ id = buffer.read_long
24
+
25
+ service = FFI::MemoryPointer.from_string('test_service')
26
+
27
+ p handle = DdeCreateStringHandle(id, service, CP_WINANSI)
28
+
29
+ p DdeNameService(id, handle, 0, DNS_REGISTER)
30
+
31
+ #p DdeDisconnect(conv_handle)
32
+
33
+ msg = Msg.new # pointer to Msg FFI struct
34
+
35
+ # Starting message loop (necessary for DDE processing)
36
+ puts "Starting message loop\n"
37
+ while msg = get_message()
38
+ translate_message(msg)
39
+ dispatch_message(msg)
40
+ end
41
+
42
+ p calls.map{|c| c.map{|e|e.respond_to?(:address) ? e.address : (Win::Dde::TYPES[e] || e)}}
43
+
44
+ p Win::Dde::ERRORS[DdeGetLastError(id)]
@@ -1,9 +1,9 @@
1
- Feature: something something
2
- In order to something something
3
- A user something something
4
- something something something
5
-
6
- Scenario: something something
7
- Given inspiration
8
- When I create a sweet new gem
9
- Then everyone should see how awesome I am
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
- require 'dde'
3
-
4
- require 'spec/expectations'
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'dde'
3
+
4
+ require 'spec/expectations'
data/lib/dde.rb CHANGED
@@ -1,9 +1,9 @@
1
- # console output redirection (may need to wrap it in synchronization code, etc)
2
- require 'rubygems'
3
- require 'win/dde'
4
- require 'dde/dde_string'
5
- require 'dde/app'
6
- require 'dde/server'
7
- require 'dde/client'
8
- require 'dde/monitor'
9
- require 'dde/xl_server'
1
+ # console output redirection (may need to wrap it in synchronization code, etc)
2
+ require 'rubygems'
3
+ require 'win/dde'
4
+ require 'dde/dde_string'
5
+ require 'dde/app'
6
+ require 'dde/server'
7
+ require 'dde/client'
8
+ require 'dde/monitor'
9
+ require 'dde/xl_server'
@@ -1,92 +1,92 @@
1
- module DDE
2
-
3
- module Errors # :nodoc:
4
- def self.[](error_code)
5
- Win::DDE::ERRORS[error_code]
6
- end
7
-
8
- class InitError < RuntimeError # :nodoc:
9
- end
10
- class FormatError < RuntimeError # :nodoc:
11
- end
12
- class StringError < RuntimeError # :nodoc:
13
- end
14
- class ServiceError < RuntimeError # :nodoc:
15
- end
16
- class ClientError < RuntimeError # :nodoc:
17
- end
18
- end
19
-
20
- # Class encapsulates DDE application. DDE::App serves as a base for more specific types,
21
- # such as DDE::Server or DDE:: Client.
22
- class App
23
- include Win::DDE
24
-
25
- attr_reader :id, :init_flags
26
-
27
- # Creates new DDE application (and starts DDE instance if dde_callback block is attached)
28
- def initialize( init_flags=nil, &dde_callback )
29
- @init_flags = init_flags
30
-
31
- start_dde init_flags, &dde_callback if dde_callback
32
-
33
- end
34
- # # todo: Destructor to ensure Dde instance is uninitialized and string handles freed...
35
- # ObjectSpace.define_finalizer( self, self.class.finalize))
36
- # end
37
- #
38
- # # need to have class method, otherwise proc traps reference to instance (self) and the object
39
- # # is never garbage-collected (http://www.mikeperham.com/2010/02/24/the-trouble-with-ruby-finalizers/)
40
- # def self.finalize()
41
- # proc { stop_dde } #does NOT work since stop_dde is instance method (depends on self)
42
- # end
43
-
44
- # (Re)Initialize application with DDEML library, providing attached dde callback
45
- # either preserved @init_flags or init_flags argument are used
46
- def start_dde( init_flags=nil, &dde_callback )
47
- @init_flags = init_flags || @init_flags || APPCLASS_STANDARD
48
-
49
- try "Starting DDE" do
50
- @id, status = dde_initialize @id, @init_flags, &dde_callback
51
- error(status) unless @id && status == DMLERR_NO_ERROR
52
- end
53
- end
54
-
55
- # (Re)Initialize application with DDEML library, providing attached dde callback
56
- def stop_dde
57
- try "Stopping DDE" do
58
- error "DDE not started" unless dde_active?
59
- error unless dde_uninitialize(@id) # Uninitialize app with DDEML library
60
- @id = nil # Clear instance id if uninitialization successful
61
- end
62
- end
63
-
64
- # Expects a block, yields to it inside a rescue block, raises given error_type with extended fail message.
65
- # Returns self in case of success (to enable method chaining).
66
- def try( action, error_type=DDE::Errors::InitError )
67
- begin
68
- yield
69
- rescue => e
70
- raise error_type, action + " failed with: #{e}"
71
- end
72
- self
73
- end
74
-
75
- # Raises Runtime error with message based on given message (DdeGetLastError message if no message given)
76
- def error( message = nil )
77
- raise case message
78
- when Integer
79
- DDE::Errors[message]
80
- when nil
81
- DDE::Errors[dde_get_last_error(@id)]
82
- else
83
- message
84
- end
85
- end
86
-
87
- def dde_active?
88
- !!@id
89
- end
90
-
91
- end
1
+ module Dde
2
+
3
+ module Errors # :nodoc:
4
+ def self.[](error_code)
5
+ Win::Dde::ERRORS[error_code]
6
+ end
7
+
8
+ class InitError < RuntimeError # :nodoc:
9
+ end
10
+ class FormatError < RuntimeError # :nodoc:
11
+ end
12
+ class StringError < RuntimeError # :nodoc:
13
+ end
14
+ class ServiceError < RuntimeError # :nodoc:
15
+ end
16
+ class ClientError < RuntimeError # :nodoc:
17
+ end
18
+ end
19
+
20
+ # Class encapsulates DDE application. Dde::App serves as a base for more specific types,
21
+ # such as Dde::Server or Dde:: Client.
22
+ class App
23
+ include Win::Dde
24
+
25
+ attr_reader :id, :init_flags
26
+
27
+ # Creates new DDE application (and starts DDE instance if dde_callback block is attached)
28
+ def initialize( init_flags=nil, &dde_callback )
29
+ @init_flags = init_flags
30
+
31
+ start_dde init_flags, &dde_callback if dde_callback
32
+
33
+ end
34
+ # # todo: Destructor to ensure Dde instance is uninitialized and string handles freed...
35
+ # ObjectSpace.define_finalizer( self, self.class.finalize))
36
+ # end
37
+ #
38
+ # # need to have class method, otherwise proc traps reference to instance (self) and the object
39
+ # # is never garbage-collected (http://www.mikeperham.com/2010/02/24/the-trouble-with-ruby-finalizers/)
40
+ # def self.finalize()
41
+ # proc { stop_dde } #does NOT work since stop_dde is instance method (depends on self)
42
+ # end
43
+
44
+ # (Re)Initialize application with DDEML library, providing attached dde callback
45
+ # either preserved @init_flags or init_flags argument are used
46
+ def start_dde( init_flags=nil, &dde_callback )
47
+ @init_flags = init_flags || @init_flags || APPCLASS_STANDARD
48
+
49
+ try "Starting DDE" do
50
+ @id, status = dde_initialize @id, @init_flags, &dde_callback
51
+ error(status) unless @id && status == DMLERR_NO_ERROR
52
+ end
53
+ end
54
+
55
+ # (Re)Initialize application with DDEML library, providing attached dde callback
56
+ def stop_dde
57
+ try "Stopping DDE" do
58
+ error "DDE not started" unless dde_active?
59
+ error unless dde_uninitialize(@id) # Uninitialize app with DDEML library
60
+ @id = nil # Clear instance id if uninitialization successful
61
+ end
62
+ end
63
+
64
+ # Expects a block, yields to it inside a rescue block, raises given error_type with extended fail message.
65
+ # Returns self in case of success (to enable method chaining).
66
+ def try( action, error_type=Dde::Errors::InitError )
67
+ begin
68
+ yield
69
+ rescue => e
70
+ raise error_type, action + " failed with: #{e}"
71
+ end
72
+ self
73
+ end
74
+
75
+ # Raises Runtime error with message based on given message (DdeGetLastError message if no message given)
76
+ def error( message = nil )
77
+ raise case message
78
+ when Integer
79
+ Dde::Errors[message]
80
+ when nil
81
+ Dde::Errors[dde_get_last_error(@id)]
82
+ else
83
+ message
84
+ end
85
+ end
86
+
87
+ def dde_active?
88
+ !!@id
89
+ end
90
+
91
+ end
92
92
  end
@@ -1,103 +1,103 @@
1
- module DDE
2
-
3
- # Class encapsulates DDE Client that requests connection with DDE server and exchanges data with it via DDE
4
- class Client < App
5
-
6
- attr_reader :conversation, # active DDE conversation that client is engaged in
7
- :service, #service that the client is connected to
8
- :topic, # active DDE conversation topic
9
- :item # active DDE conversation item
10
-
11
- # # Creates new DDE client instance
12
- # def initialize(init_flags = nil, &dde_callback )
13
- # super init_flags, &dde_callback
14
- # end
15
-
16
- # Establish a conversation with a server application that supports the specified service
17
- # name and topic name pair.
18
- def start_conversation( service=nil, topic=nil )
19
- try "Starting conversation #{service} #{topic}", DDE::Errors::ClientError do
20
- error "DDE is not initialized" unless dde_active?
21
- error "Another conversation already established" if conversation_active?
22
-
23
- # Create DDE strings for service and topic unless they are omitted
24
- @service = DDE::DdeString.new(@id, service) if service
25
- @topic = DDE::DdeString.new(@id, topic) if topic
26
-
27
- # Initiate new DDE conversation, returns conversation handle or nil
28
- error unless @conversation = dde_connect(@id, @service.handle, @topic.handle)
29
- end
30
- end
31
-
32
- # Stops active conversation, raises error if no conversations active
33
- def stop_conversation
34
- try "Stopping conversation", DDE::Errors::ClientError do
35
- error "DDE not started" unless dde_active?
36
- error "Conversation not started" unless conversation_active?
37
-
38
- error unless dde_disconnect(@conversation) && # Stop DDE conversation
39
- dde_free_string_handle(@id, @service.handle) && # Free string handles for service name
40
- dde_free_string_handle(@id, @topic.handle) # Free string handles for topic name
41
-
42
- # Unset attributes for conversation, service and topic
43
- @conversation = nil
44
- @service = nil
45
- @topic = nil
46
- end
47
- end
48
-
49
- # Sends XTYP_POKE transaction to server if conversation was already established.
50
- # data:: data being sent (will be coerced to String unless is already a (packed) String)
51
- # format:: standard clipboard format of submitted data item (default CF_TEXT)
52
- def send_data( data, format = CF_TEXT, item = "" )
53
- data_pointer = FFI::MemoryPointer.from_string(data.to_s)
54
- result, trans_id = start_transaction(XTYP_POKE, data_pointer, data_pointer.size, format, item)
55
- result
56
- end
57
-
58
- # Initiates transaction to server if conversation was already established.
59
- # transaction_type:: XTYP_ADVSTART, XTYP_ADVSTOP, XTYP_EXECUTE, XTYP_POKE, XTYP_REQUEST
60
- # data_pointer:: pointer to data being sent (either FFI::MemoryPointer or DDE data_handle)
61
- # cb:: data set size (or -1 to indicate that data_pointer is in fact DDE data_handle)
62
- # format:: standard clipboard format of submitted data item (default CF_TEXT)
63
- # item:: item to which transaction is related (String, DdeString or DDE string handle)
64
- # timeout:: timeout in milliseconds or TIMEOUT_ASYNC to indicate async transaction
65
- #
66
- # *Returns*:: A pair of [result, trans_id]. Result is nil for failed transactions,
67
- # DDE data handle for synchronous transactions in which the client expects data from the server,
68
- # nonzero for successful transactions where clients does not expect data from server.
69
- # Trans_id: for asynchronous transactions, a unique transaction identifier for use with the
70
- # DdeAbandonTransaction function and the XTYP_XACT_COMPLETE transaction. For synchronous transactions,
71
- # the low-order word of this variable contains any applicable DDE_ flags resulting from the transaction.
72
- #
73
- def start_transaction( transaction_type, data_pointer=nil, cb = data_pointer ? data_pointer.size : 0,
74
- format=CF_TEXT, item=0, timeout=1000)
75
-
76
- result = nil
77
- trans_id = FFI::MemoryPointer.new(:uint32).put_uint32(0,0)
78
-
79
- try "Sending data to server", DDE::Errors::ClientError do
80
- error "DDE not started" unless dde_active?
81
- error "Conversation not started" unless conversation_active?
82
-
83
- item_handle = case item
84
- when String
85
- DDE::DdeString.new(@id, service).handle
86
- when DdeString
87
- item.handle
88
- else
89
- item
90
- end
91
-
92
- error unless result = dde_client_transaction(data_pointer, cb, @conversation, item_handle,
93
- format, transaction_type, timeout, trans_id)
94
- end
95
- [result, trans_id.get_uint32(0)]
96
- end
97
-
98
- def conversation_active?
99
- !!@conversation
100
- end
101
-
102
- end
1
+ module Dde
2
+
3
+ # Class encapsulates DDE Client that requests connection with DDE server and exchanges data with it via DDE
4
+ class Client < App
5
+
6
+ attr_reader :conversation, # active DDE conversation that client is engaged in
7
+ :service, #service that the client is connected to
8
+ :topic, # active DDE conversation topic
9
+ :item # active DDE conversation item
10
+
11
+ # # Creates new DDE client instance
12
+ # def initialize(init_flags = nil, &dde_callback )
13
+ # super init_flags, &dde_callback
14
+ # end
15
+
16
+ # Establish a conversation with a server application that supports the specified service
17
+ # name and topic name pair.
18
+ def start_conversation( service=nil, topic=nil )
19
+ try "Starting conversation #{service} #{topic}", Dde::Errors::ClientError do
20
+ error "DDE is not initialized" unless dde_active?
21
+ error "Another conversation already established" if conversation_active?
22
+
23
+ # Create DDE strings for service and topic unless they are omitted
24
+ @service = Dde::DdeString.new(@id, service) if service
25
+ @topic = Dde::DdeString.new(@id, topic) if topic
26
+
27
+ # Initiate new DDE conversation, returns conversation handle or nil
28
+ error unless @conversation = dde_connect(@id, @service.handle, @topic.handle)
29
+ end
30
+ end
31
+
32
+ # Stops active conversation, raises error if no conversations active
33
+ def stop_conversation
34
+ try "Stopping conversation", Dde::Errors::ClientError do
35
+ error "DDE not started" unless dde_active?
36
+ error "Conversation not started" unless conversation_active?
37
+
38
+ error unless dde_disconnect(@conversation) && # Stop DDE conversation
39
+ dde_free_string_handle(@id, @service.handle) && # Free string handles for service name
40
+ dde_free_string_handle(@id, @topic.handle) # Free string handles for topic name
41
+
42
+ # Unset attributes for conversation, service and topic
43
+ @conversation = nil
44
+ @service = nil
45
+ @topic = nil
46
+ end
47
+ end
48
+
49
+ # Sends XTYP_POKE transaction to server if conversation was already established.
50
+ # data:: data being sent (will be coerced to String unless is already a (packed) String)
51
+ # format:: standard clipboard format of submitted data item (default CF_TEXT)
52
+ def send_data( data, format = CF_TEXT, item = "" )
53
+ data_pointer = FFI::MemoryPointer.from_string(data.to_s)
54
+ result, trans_id = start_transaction(XTYP_POKE, data_pointer, data_pointer.size, format, item)
55
+ result
56
+ end
57
+
58
+ # Initiates transaction to server if conversation was already established.
59
+ # transaction_type:: XTYP_ADVSTART, XTYP_ADVSTOP, XTYP_EXECUTE, XTYP_POKE, XTYP_REQUEST
60
+ # data_pointer:: pointer to data being sent (either FFI::MemoryPointer or DDE data_handle)
61
+ # cb:: data set size (or -1 to indicate that data_pointer is in fact DDE data_handle)
62
+ # format:: standard clipboard format of submitted data item (default CF_TEXT)
63
+ # item:: item to which transaction is related (String, DdeString or DDE string handle)
64
+ # timeout:: timeout in milliseconds or TIMEOUT_ASYNC to indicate async transaction
65
+ #
66
+ # *Returns*:: A pair of [result, trans_id]. Result is nil for failed transactions,
67
+ # DDE data handle for synchronous transactions in which the client expects data from the server,
68
+ # nonzero for successful transactions where clients does not expect data from server.
69
+ # Trans_id: for asynchronous transactions, a unique transaction identifier for use with the
70
+ # DdeAbandonTransaction function and the XTYP_XACT_COMPLETE transaction. For synchronous transactions,
71
+ # the low-order word of this variable contains any applicable DDE_ flags resulting from the transaction.
72
+ #
73
+ def start_transaction( transaction_type, data_pointer=nil, cb = data_pointer ? data_pointer.size : 0,
74
+ format=CF_TEXT, item=0, timeout=1000)
75
+
76
+ result = nil
77
+ trans_id = FFI::MemoryPointer.new(:uint32).put_uint32(0,0)
78
+
79
+ try "Sending data to server", Dde::Errors::ClientError do
80
+ error "DDE not started" unless dde_active?
81
+ error "Conversation not started" unless conversation_active?
82
+
83
+ item_handle = case item
84
+ when String
85
+ Dde::DdeString.new(@id, service).handle
86
+ when DdeString
87
+ item.handle
88
+ else
89
+ item
90
+ end
91
+
92
+ error unless result = dde_client_transaction(data_pointer, cb, @conversation, item_handle,
93
+ format, transaction_type, timeout, trans_id)
94
+ end
95
+ [result, trans_id.get_uint32(0)]
96
+ end
97
+
98
+ def conversation_active?
99
+ !!@conversation
100
+ end
101
+
102
+ end
103
103
  end