musicbeeipc 2.0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +5 -0
- data/LICENSE_MusicBeeIPCSDK.txt +23 -0
- data/README.md +16 -0
- data/README.txt +16 -0
- data/enums.html +318 -0
- data/lib/constants.rb +12 -0
- data/lib/enums.rb +316 -0
- data/lib/musicbeeipc.rb +1477 -0
- data/lib/pack.rb +282 -0
- data/lib/structs.rb +40 -0
- data/lib/unpack.rb +204 -0
- data/lib/winapi.rb +39 -0
- data/musicbeeipc.gemspec +14 -0
- metadata +71 -0
data/lib/pack.rb
ADDED
@@ -0,0 +1,282 @@
|
|
1
|
+
#----------------------------------------------------------#
|
2
|
+
#- MusicBeeIPCSDK Rb v2.0.0 -#
|
3
|
+
#- Copyright © Kerli Low 2014 -#
|
4
|
+
#- This file is licensed under the -#
|
5
|
+
#- BSD 2-Clause License -#
|
6
|
+
#- See LICENSE_MusicBeeIPCSDK for more information. -#
|
7
|
+
#----------------------------------------------------------#
|
8
|
+
|
9
|
+
require_relative "constants.rb"
|
10
|
+
require_relative "structs.rb"
|
11
|
+
|
12
|
+
|
13
|
+
class MusicBeeIPC
|
14
|
+
private
|
15
|
+
|
16
|
+
# ----------------------------------------------------------------------------
|
17
|
+
# All strings are encoded in UTF-16 little endian
|
18
|
+
# ----------------------------------------------------------------------------
|
19
|
+
|
20
|
+
# -Int32: 32 bit integer
|
21
|
+
# -Int32: 32 bit integer
|
22
|
+
# -...
|
23
|
+
def pack_i(*int32s)
|
24
|
+
cds = COPYDATASTRUCT.new
|
25
|
+
cds[:dwData] = 0
|
26
|
+
|
27
|
+
num = int32s.length
|
28
|
+
|
29
|
+
cds[:cbData] = MBIPC_SIZEOFINT * num
|
30
|
+
|
31
|
+
data = int32s.pack("l" + num.to_s)
|
32
|
+
|
33
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
34
|
+
|
35
|
+
return cds.to_ptr.address
|
36
|
+
end
|
37
|
+
|
38
|
+
# -Int32: Byte count of string
|
39
|
+
# -byte[]: String data
|
40
|
+
# -Int32: Byte count of string
|
41
|
+
# -byte[]: String data
|
42
|
+
# -...
|
43
|
+
def pack_s(*strings)
|
44
|
+
cds = COPYDATASTRUCT.new
|
45
|
+
cds[:dwData] = 0
|
46
|
+
|
47
|
+
num = strings.length
|
48
|
+
|
49
|
+
cds[:cbData] = MBIPC_SIZEOFINT * num
|
50
|
+
|
51
|
+
encoded = strings.map do |s|
|
52
|
+
e = s.encode("UTF-16LE").force_encoding("BINARY")
|
53
|
+
cds[:cbData] += e.length
|
54
|
+
e
|
55
|
+
end
|
56
|
+
|
57
|
+
data = ""
|
58
|
+
encoded.each { |e| data += [e.length].pack("l") + e }
|
59
|
+
|
60
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
61
|
+
|
62
|
+
return cds.to_ptr.address
|
63
|
+
end
|
64
|
+
|
65
|
+
# -Int32: Byte count of string
|
66
|
+
# -byte[]: String data
|
67
|
+
# -Int32: 32 bit integer
|
68
|
+
# -Int32: 32 bit integer
|
69
|
+
# -...
|
70
|
+
def pack_si(string_1, *int32s)
|
71
|
+
cds = COPYDATASTRUCT.new
|
72
|
+
cds[:dwData] = 0
|
73
|
+
|
74
|
+
encoded = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
75
|
+
byte_count = encoded.length
|
76
|
+
|
77
|
+
num = int32s.length
|
78
|
+
|
79
|
+
cds[:cbData] = MBIPC_SIZEOFINT * (num + 1) + byte_count
|
80
|
+
|
81
|
+
data = [byte_count].pack("l") + encoded +
|
82
|
+
int32s.pack("l" + int32s.length.to_s)
|
83
|
+
|
84
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
85
|
+
|
86
|
+
return cds.to_ptr.address
|
87
|
+
end
|
88
|
+
|
89
|
+
# -Int32: Byte count of string
|
90
|
+
# -byte[]: String data
|
91
|
+
# -Int32: bool
|
92
|
+
# -Int32: bool
|
93
|
+
# -...
|
94
|
+
def pack_sb(string_1, *bools)
|
95
|
+
cds = COPYDATASTRUCT.new
|
96
|
+
cds[:dwData] = 0
|
97
|
+
|
98
|
+
encoded = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
99
|
+
byte_count = encoded.length
|
100
|
+
|
101
|
+
bools_i = bools.map { |b| b ? 1 : 0 }
|
102
|
+
|
103
|
+
num = bools_i.length
|
104
|
+
|
105
|
+
cds[:cbData] = MBIPC_SIZEOFINT * (num + 1) + byte_count
|
106
|
+
|
107
|
+
data = [byte_count].pack("l") + encoded +
|
108
|
+
bools_i.pack("l" + bools_i.length.to_s)
|
109
|
+
|
110
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
111
|
+
|
112
|
+
return cds.to_ptr.address
|
113
|
+
end
|
114
|
+
|
115
|
+
# -Int32: Byte count of string
|
116
|
+
# -byte[]: String data
|
117
|
+
# -double: 64-bit floating-point value
|
118
|
+
# -double: 64-bit floating-point value
|
119
|
+
# -...
|
120
|
+
def pack_sd(string_1, *doubles)
|
121
|
+
cds = COPYDATASTRUCT.new
|
122
|
+
cds[:dwData] = 0
|
123
|
+
|
124
|
+
encoded = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
125
|
+
byte_count = encoded.length
|
126
|
+
|
127
|
+
num = doubles.length
|
128
|
+
|
129
|
+
cds[:cbData] = MBIPC_SIZEOFDOUBLE * num + MBIPC_SIZEOFINT + byte_count
|
130
|
+
|
131
|
+
data = [byte_count].pack("l") + encoded +
|
132
|
+
doubles.pack("d" + doubles.length.to_s)
|
133
|
+
|
134
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
135
|
+
|
136
|
+
return cds.to_ptr.address
|
137
|
+
end
|
138
|
+
|
139
|
+
# -Int32: Byte count of string
|
140
|
+
# -byte[]: String data
|
141
|
+
# -Int32: Number of strings in string array
|
142
|
+
# -Int32: Byte count of string in string array
|
143
|
+
# -byte[]: String data in string array
|
144
|
+
# -Int32: Byte count of string in string array
|
145
|
+
# -byte[]: String data in string array
|
146
|
+
# -...
|
147
|
+
def pack_ssa(string_1, strings)
|
148
|
+
cds = COPYDATASTRUCT.new
|
149
|
+
cds[:dwData] = 0
|
150
|
+
|
151
|
+
encoded_1 = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
152
|
+
byte_count_1 = encoded_1.length
|
153
|
+
|
154
|
+
num = strings.length
|
155
|
+
|
156
|
+
cds[:cbData] = MBIPC_SIZEOFINT * (num + 2) + byte_count_1
|
157
|
+
|
158
|
+
encoded = strings.map do |s|
|
159
|
+
e = s.encode("UTF-16LE").force_encoding("BINARY")
|
160
|
+
cds[:cbData] += e.length
|
161
|
+
e
|
162
|
+
end
|
163
|
+
|
164
|
+
data = [byte_count_1].pack("l") + encoded_1 + [num].pack("l")
|
165
|
+
encoded.each { |e| data += [e.length].pack("l") + e }
|
166
|
+
|
167
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
168
|
+
|
169
|
+
return cds.to_ptr.address
|
170
|
+
end
|
171
|
+
|
172
|
+
# -Int32: Byte count of string
|
173
|
+
# -byte[]: String data
|
174
|
+
# -Int32: Byte count of string
|
175
|
+
# -byte[]: String data
|
176
|
+
# -Int32: Number of strings in string array
|
177
|
+
# -Int32: Byte count of string in string array
|
178
|
+
# -byte[]: String data in string array
|
179
|
+
# -Int32: Byte count of string in string array
|
180
|
+
# -byte[]: String data in string array
|
181
|
+
# -...
|
182
|
+
def pack_sssa(string_1, string_2, strings)
|
183
|
+
cds = COPYDATASTRUCT.new
|
184
|
+
cds[:dwData] = 0
|
185
|
+
|
186
|
+
encoded_1 = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
187
|
+
byte_count_1 = encoded_1.length
|
188
|
+
|
189
|
+
encoded_2 = string_2.encode("UTF-16LE").force_encoding("BINARY")
|
190
|
+
byte_count_2 = encoded_2.length
|
191
|
+
|
192
|
+
num = strings.length
|
193
|
+
|
194
|
+
cds[:cbData] = MBIPC_SIZEOFINT * (num + 3) + byte_count_1 + byte_count_2
|
195
|
+
|
196
|
+
encoded = strings.map do |s|
|
197
|
+
e = s.encode("UTF-16LE").force_encoding("BINARY")
|
198
|
+
cds[:cbData] += e.length
|
199
|
+
e
|
200
|
+
end
|
201
|
+
|
202
|
+
data = [byte_count_1].pack("l") + encoded_1 +
|
203
|
+
[byte_count_2].pack("l") + encoded_2 + [num].pack("l")
|
204
|
+
encoded.each { |e| data += [e.length].pack("l") + e }
|
205
|
+
|
206
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
207
|
+
|
208
|
+
return cds.to_ptr.address
|
209
|
+
end
|
210
|
+
|
211
|
+
# -Int32: Byte count of string
|
212
|
+
# -byte[]: String data
|
213
|
+
# -Int32: 32 bit integer
|
214
|
+
# -Int32: Byte count of string
|
215
|
+
# -byte[]: String data
|
216
|
+
# -...
|
217
|
+
def pack_sis(string_1, int32_1, string_2)
|
218
|
+
cds = COPYDATASTRUCT.new
|
219
|
+
cds[:dwData] = 0
|
220
|
+
|
221
|
+
encoded_1 = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
222
|
+
byte_count_1 = encoded_1.length
|
223
|
+
|
224
|
+
encoded_2 = string_2.encode("UTF-16LE").force_encoding("BINARY")
|
225
|
+
byte_count_2 = encoded_2.length
|
226
|
+
|
227
|
+
cds[:cbData] = MBIPC_SIZEOFINT * 3 + byte_count_1 + byte_count_2
|
228
|
+
|
229
|
+
data = [byte_count_1].pack("l") + encoded_1 +
|
230
|
+
[int32_1, byte_count_2].pack("ll") + encoded_2
|
231
|
+
|
232
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
233
|
+
|
234
|
+
return cds.to_ptr.address
|
235
|
+
end
|
236
|
+
|
237
|
+
# -Int32: Number of integers in integer array
|
238
|
+
# -Int32: 32 bit integer
|
239
|
+
# -Int32: 32 bit integer
|
240
|
+
# -...
|
241
|
+
# -Int32: 32 bit integer
|
242
|
+
def pack_iai(int32s, int32_1)
|
243
|
+
cds = COPYDATASTRUCT.new
|
244
|
+
cds[:dwData] = 0
|
245
|
+
|
246
|
+
num = int32s.length
|
247
|
+
|
248
|
+
cds[:cbData] = MBIPC_SIZEOFINT * (num + 2)
|
249
|
+
|
250
|
+
data = ([num] + int32s + [int32_1]).pack("l" + (num + 2).to_s)
|
251
|
+
|
252
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
253
|
+
|
254
|
+
return cds.to_ptr.address
|
255
|
+
end
|
256
|
+
|
257
|
+
# -Int32: Byte count of string
|
258
|
+
# -byte[]: String data
|
259
|
+
# -Int32: Number of integers in integer array
|
260
|
+
# -Int32: 32 bit integer
|
261
|
+
# -Int32: 32 bit integer
|
262
|
+
# -...
|
263
|
+
# -Int32: 32 bit integer
|
264
|
+
def pack_siai(string_1, int32s, int32_1)
|
265
|
+
cds = COPYDATASTRUCT.new
|
266
|
+
cds[:dwData] = 0
|
267
|
+
|
268
|
+
encoded = string_1.encode("UTF-16LE").force_encoding("BINARY")
|
269
|
+
byte_count = encoded.length
|
270
|
+
|
271
|
+
num = int32s.length
|
272
|
+
|
273
|
+
cds[:cbData] = MBIPC_SIZEOFINT * (num + 3) + byte_count
|
274
|
+
|
275
|
+
data = [byte_count].pack("l") + encoded +
|
276
|
+
([num] + int32s + [int32_1]).pack("l" + (num + 2).to_s)
|
277
|
+
|
278
|
+
cds[:lpData] = FFI::MemoryPointer.from_string(data)
|
279
|
+
|
280
|
+
return cds.to_ptr.address
|
281
|
+
end
|
282
|
+
end
|
data/lib/structs.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#----------------------------------------------------------#
|
2
|
+
#- MusicBeeIPCSDK Rb v2.0.0 -#
|
3
|
+
#- Copyright © Kerli Low 2014 -#
|
4
|
+
#- This file is licensed under the -#
|
5
|
+
#- BSD 2-Clause License -#
|
6
|
+
#- See LICENSE_MusicBeeIPCSDK for more information. -#
|
7
|
+
#----------------------------------------------------------#
|
8
|
+
|
9
|
+
require "ffi"
|
10
|
+
|
11
|
+
|
12
|
+
class FloatInt < FFI::Union
|
13
|
+
layout :f, :float,
|
14
|
+
:i, :int
|
15
|
+
|
16
|
+
def initialize(opts={}, *args)
|
17
|
+
self[:f] = opts[:f] if opts[:f]
|
18
|
+
self[:i] = opts[:i] if opts[:i]
|
19
|
+
super(*args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
class LRUShort < FFI::Union
|
25
|
+
layout :lr, :long,
|
26
|
+
:low, :ushort,
|
27
|
+
:high, :ushort, 2
|
28
|
+
|
29
|
+
def initialize(lr=0, *args)
|
30
|
+
self[:lr] = lr
|
31
|
+
super(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
class COPYDATASTRUCT < FFI::Struct
|
37
|
+
layout :dwData, :pointer,
|
38
|
+
:cbData, :uint32,
|
39
|
+
:lpData, :pointer
|
40
|
+
end
|
data/lib/unpack.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
#----------------------------------------------------------#
|
2
|
+
#- MusicBeeIPCSDK Rb v2.0.0 -#
|
3
|
+
#- Copyright © Kerli Low 2014 -#
|
4
|
+
#- This file is licensed under the -#
|
5
|
+
#- BSD 2-Clause License -#
|
6
|
+
#- See LICENSE_MusicBeeIPCSDK for more information. -#
|
7
|
+
#----------------------------------------------------------#
|
8
|
+
|
9
|
+
require_relative "constants.rb"
|
10
|
+
require_relative "structs.rb"
|
11
|
+
|
12
|
+
|
13
|
+
class MusicBeeIPC
|
14
|
+
private
|
15
|
+
|
16
|
+
# ----------------------------------------------------------------------------
|
17
|
+
# All strings are encoded in UTF-16 little endian
|
18
|
+
# ----------------------------------------------------------------------------
|
19
|
+
|
20
|
+
# -Int32: Byte count of the string
|
21
|
+
# -byte[]: String data
|
22
|
+
# Free lr after use
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def unpack_s(lr)
|
26
|
+
string_1 = ""
|
27
|
+
|
28
|
+
begin
|
29
|
+
mmf = open_mmf(lr)
|
30
|
+
raise "Failed to open MMF." if !mmf
|
31
|
+
|
32
|
+
view, ptr = map_mmf_view(mmf, lr)
|
33
|
+
raise "Failed to map MMF view." if !view
|
34
|
+
rescue
|
35
|
+
return ""
|
36
|
+
ensure
|
37
|
+
close_mmf(mmf) if mmf
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
byte_count = ptr.read_string(MBIPC_SIZEOFINT).unpack("l")[0]
|
42
|
+
ptr += MBIPC_SIZEOFINT
|
43
|
+
|
44
|
+
if byte_count > 0
|
45
|
+
string_1 = ptr.read_string(byte_count).force_encoding("UTF-16LE").
|
46
|
+
encode(__ENCODING__)
|
47
|
+
end
|
48
|
+
rescue
|
49
|
+
return ""
|
50
|
+
ensure
|
51
|
+
unmap_mmf_view(view)
|
52
|
+
close_mmf(mmf)
|
53
|
+
end
|
54
|
+
|
55
|
+
return string_1
|
56
|
+
end
|
57
|
+
|
58
|
+
# -Int32: Number of strings
|
59
|
+
# -Int32: Byte count of 1st string
|
60
|
+
# -byte[]: 1st string data
|
61
|
+
# -Int32: Byte count of 2nd string
|
62
|
+
# -byte[]: 2nd string data
|
63
|
+
# -...
|
64
|
+
# Free lr after use
|
65
|
+
#
|
66
|
+
# @return [Array<String>]
|
67
|
+
def unpack_sa(lr)
|
68
|
+
begin
|
69
|
+
mmf = open_mmf(lr)
|
70
|
+
raise "Failed to open MMF." if !mmf
|
71
|
+
|
72
|
+
view, ptr = map_mmf_view(mmf, lr)
|
73
|
+
raise "Failed to map MMF view." if !view
|
74
|
+
rescue
|
75
|
+
return []
|
76
|
+
ensure
|
77
|
+
close_mmf(mmf) if mmf
|
78
|
+
end
|
79
|
+
|
80
|
+
begin
|
81
|
+
str_count = ptr.read_string(MBIPC_SIZEOFINT).unpack("l")[0]
|
82
|
+
ptr += MBIPC_SIZEOFINT
|
83
|
+
|
84
|
+
strings = Array.new(str_count)
|
85
|
+
|
86
|
+
strings.map! do |s|
|
87
|
+
byte_count = ptr.read_string(MBIPC_SIZEOFINT).unpack("l")[0]
|
88
|
+
ptr += MBIPC_SIZEOFINT
|
89
|
+
|
90
|
+
if byte_count > 0
|
91
|
+
s = ptr.read_string(byte_count).force_encoding("UTF-16LE").
|
92
|
+
encode(__ENCODING__)
|
93
|
+
ptr += byte_count
|
94
|
+
s
|
95
|
+
end
|
96
|
+
end
|
97
|
+
rescue
|
98
|
+
return []
|
99
|
+
ensure
|
100
|
+
unmap_mmf_view(view)
|
101
|
+
close_mmf(mmf)
|
102
|
+
end
|
103
|
+
|
104
|
+
return strings
|
105
|
+
end
|
106
|
+
|
107
|
+
# -Int32: 1st 32 bit integer
|
108
|
+
# -Int32: 2nd 32 bit integer
|
109
|
+
# Free lr after use
|
110
|
+
#
|
111
|
+
# @return [Array<int>]
|
112
|
+
def unpack_ii(lr)
|
113
|
+
begin
|
114
|
+
mmf = open_mmf(lr)
|
115
|
+
raise "Failed to open MMF." if !mmf
|
116
|
+
|
117
|
+
view, ptr = map_mmf_view(mmf, lr)
|
118
|
+
raise "Failed to map MMF view." if !view
|
119
|
+
rescue
|
120
|
+
return [-1, -1]
|
121
|
+
ensure
|
122
|
+
close_mmf(mmf) if mmf
|
123
|
+
end
|
124
|
+
|
125
|
+
begin
|
126
|
+
ints = ptr.read_string(MBIPC_SIZEOFINT * 2).unpack("ll")
|
127
|
+
rescue
|
128
|
+
return [-1, -1]
|
129
|
+
ensure
|
130
|
+
unmap_mmf_view(view)
|
131
|
+
close_mmf(mmf)
|
132
|
+
end
|
133
|
+
|
134
|
+
return ints
|
135
|
+
end
|
136
|
+
|
137
|
+
# -Int32: Number of integers
|
138
|
+
# -Int32: 1st 32 bit integer
|
139
|
+
# -Int32: 2nd 32 bit integer
|
140
|
+
# -...
|
141
|
+
# Free lr after use
|
142
|
+
#
|
143
|
+
# @return [Array<int>]
|
144
|
+
def unpack_ia(lr)
|
145
|
+
begin
|
146
|
+
mmf = open_mmf(lr)
|
147
|
+
raise "Failed to open MMF." if !mmf
|
148
|
+
|
149
|
+
view, ptr = map_mmf_view(mmf, lr)
|
150
|
+
raise "Failed to map MMF view." if !view
|
151
|
+
rescue
|
152
|
+
return []
|
153
|
+
ensure
|
154
|
+
close_mmf(mmf) if mmf
|
155
|
+
end
|
156
|
+
|
157
|
+
begin
|
158
|
+
int_count = ptr.read_string(MBIPC_SIZEOFINT).unpack("l")[0]
|
159
|
+
ptr += MBIPC_SIZEOFINT
|
160
|
+
|
161
|
+
ints = ptr.read_string(MBIPC_SIZEOFINT * int_count).
|
162
|
+
unpack("l" + int_count.to_s)
|
163
|
+
rescue
|
164
|
+
return []
|
165
|
+
ensure
|
166
|
+
unmap_mmf_view(view)
|
167
|
+
close_mmf(mmf)
|
168
|
+
end
|
169
|
+
|
170
|
+
return ints
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def open_mmf(lr)
|
175
|
+
return nil if !lr || lr == 0
|
176
|
+
|
177
|
+
ls = LRUShort.new(lr)
|
178
|
+
|
179
|
+
name = ("mbipc_mmf_" + ls[:low].to_s + "\0").encode("UTF-16LE")
|
180
|
+
|
181
|
+
# FILE_MAP_READ = 0x0004 = 4
|
182
|
+
# FALSE = 0
|
183
|
+
open_file_mapping(4, 0, name)
|
184
|
+
end
|
185
|
+
|
186
|
+
def close_mmf(mmf)
|
187
|
+
close_handle(mmf)
|
188
|
+
end
|
189
|
+
|
190
|
+
def map_mmf_view(mmf, lr)
|
191
|
+
ls = LRUShort.new(lr)
|
192
|
+
|
193
|
+
# FILE_MAP_READ = 0x0004 = 4
|
194
|
+
view = map_view_of_file(mmf, 4, 0, 0, 0)
|
195
|
+
|
196
|
+
ptr = FFI::Pointer.new(:char, view + ls[:high] + MBIPC_SIZEOFLONG)
|
197
|
+
|
198
|
+
return [view, ptr]
|
199
|
+
end
|
200
|
+
|
201
|
+
def unmap_mmf_view(view)
|
202
|
+
unmap_view_of_file(view)
|
203
|
+
end
|
204
|
+
end
|