musicbeeipc 2.0.0.1
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.
- 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
|