react-native-alpha-video-gpu 0.0.0-stage → 1.0.0

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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +949 -2
  3. package/THIRD_PARTY_NOTICES.md +14 -0
  4. package/android/src/main/AndroidManifest.xml +9 -0
  5. package/android/src/main/cpp/CMakeLists.txt +41 -0
  6. package/android/src/main/cpp/alphavideogpu_jni.cpp +1168 -0
  7. package/android/src/main/cpp/astc_decomp.cpp +1550 -0
  8. package/android/src/main/cpp/astc_decomp.h +41 -0
  9. package/android/src/main/cpp/source_jni.cpp +242 -0
  10. package/android/src/main/cpp/source_jni.h +13 -0
  11. package/android/src/main/java/dev/mediacache/alphavideo/gpu/AlphaVideoGpuNative.java +43 -0
  12. package/android/src/main/java/dev/mediacache/alphavideo/gpu/AlphaVideoGpuReader.java +209 -0
  13. package/android/src/main/java/dev/mediacache/alphavideo/gpu/AlphaVideoGpuSource.java +328 -0
  14. package/android/src/main/java/dev/mediacache/alphavideo/gpu/AlphaVideoGpuView.java +2126 -0
  15. package/android/src/main/java/dev/mediacache/alphavideo/gpu/Fetcher.java +37 -0
  16. package/android/src/main/java/dev/mediacache/alphavideo/gpu/HttpFetcher.java +156 -0
  17. package/android/src/main/java/dev/mediacache/alphavideo/gpu/Ktx2Metadata.java +78 -0
  18. package/android/src/main/java/dev/mediacache/alphavideo/gpu/RangeSourceLink.java +54 -0
  19. package/android/src/main/java/dev/mediacache/alphavideo/gpu/ZstdSeekTable.java +120 -0
  20. package/android/src/rangesource/java/dev/mediacache/alphavideo/gpu/AppDataSource.java +50 -0
  21. package/ios/Sources/AlphaVideoGPU/AlphaVideoGpuSource.h +63 -0
  22. package/ios/Sources/AlphaVideoGPU/AlphaVideoGpuSource.mm +522 -0
  23. package/ios/Sources/AlphaVideoGPU/AlphaVideoGpuView.mm +2722 -0
  24. package/ios/Sources/AlphaVideoGPU/astc_decomp.cpp +1550 -0
  25. package/ios/Sources/AlphaVideoGPU/astc_decomp.h +41 -0
  26. package/ios/Sources/AlphaVideoGPU/include/AlphaVideoGPU.h +110 -0
  27. package/ios/Sources/AlphaVideoGPU/zstd_seek.h +250 -0
  28. package/package.json +77 -4
  29. package/react-native/android/build.gradle +92 -0
  30. package/react-native/android/src/main/AndroidManifest.xml +9 -0
  31. package/react-native/android/src/main/java/dev/mediacache/alphavideo/gpu/reactnative/AlphaVideoGpuPackage.java +26 -0
  32. package/react-native/android/src/main/java/dev/mediacache/alphavideo/gpu/reactnative/AlphaVideoGpuViewManager.java +187 -0
  33. package/react-native/android/src/main/java/dev/mediacache/alphavideo/gpu/reactnative/PlayerEventForwarder.java +107 -0
  34. package/react-native/android/src/newarch/java/dev/mediacache/alphavideo/gpu/reactnative/AlphaVideoGpuViewManagerSpec.java +23 -0
  35. package/react-native/android/src/norangesource/java/dev/mediacache/alphavideo/gpu/AppDataSource.java +15 -0
  36. package/react-native/android/src/oldarch/java/dev/mediacache/alphavideo/gpu/reactnative/AlphaVideoGpuViewManagerSpec.java +56 -0
  37. package/react-native/ios/RNAlphaVideoGpuViewComponentView.mm +176 -0
  38. package/react-native/ios/RNAlphaVideoGpuViewManager.mm +175 -0
  39. package/react-native/src/AlphaVideoGpuView.js +2 -0
  40. package/react-native/src/AlphaVideoGpuView.web.tsx +264 -0
  41. package/react-native/src/AlphaVideoGpuViewNativeComponent.ts +128 -0
  42. package/react-native/src/AlphaVideoGpuViewNativeComponent.web.ts +2 -0
  43. package/react-native/src/index.d.ts +95 -0
  44. package/react-native/src/index.js +162 -0
  45. package/react-native-alpha-video-gpu.podspec +37 -0
  46. package/react-native.config.js +12 -0
  47. package/third_party/licenses/Apache-2.0.txt +208 -0
  48. package/third_party/range-source/LICENSE +21 -0
  49. package/third_party/range-source/README.md +10 -0
  50. package/third_party/range-source/include/range_source.h +395 -0
  51. package/third_party/range-source/include/range_source_download.h +309 -0
  52. package/third_party/zstd/LICENSE +30 -0
  53. package/third_party/zstd/zstd.c +38717 -0
  54. package/third_party/zstd/zstd.h +2450 -0
@@ -0,0 +1,395 @@
1
+ /*
2
+ * range-source's native reader and stores, as a C interface: a versioned table of functions.
3
+ *
4
+ * A player doesn't link the add-on. It gets the table at runtime (range_source_plugin(), found
5
+ * through the add-on's Java or Objective-C class) and carries a copy of this header only, so the
6
+ * two never pass C++ objects, and each can keep its own C++ runtime.
7
+ *
8
+ * The table only grows: a new function goes at the end, and structSize says which are there. A
9
+ * table with another `abi` is incompatible.
10
+ *
11
+ * Defining RANGE_SOURCE_CLIENT_NAMESPACE before including this header adds a C++ wrapper over the
12
+ * table, in that namespace. Each binary names its own, so two copies of this header never clash.
13
+ */
14
+ #ifndef RANGE_SOURCE_H
15
+ #define RANGE_SOURCE_H
16
+
17
+ #include <stddef.h>
18
+ #include <stdint.h>
19
+
20
+ #ifdef __cplusplus
21
+ extern "C" {
22
+ #endif
23
+
24
+ #define RANGE_SOURCE_ABI 1
25
+
26
+ /* What tryRead returns while the bytes are on their way. */
27
+ #define RANGE_SOURCE_PENDING (-2)
28
+
29
+ /* storeHolds */
30
+ #define RANGE_SOURCE_HOLDS_NONE 0
31
+ #define RANGE_SOURCE_HOLDS_PART 1
32
+ #define RANGE_SOURCE_HOLDS_WHOLE 2
33
+
34
+ typedef struct RangeSourceStore RangeSourceStore;
35
+ typedef struct RangeSourceReader RangeSourceReader;
36
+
37
+ /* What a source tells about the file when a read opens. Strings are cut to fit; empty if none. */
38
+ typedef struct RangeSourceInfo {
39
+ /* Total size in bytes, or -1 while it isn't known (a response without a length) */
40
+ int64_t size;
41
+ /* ETag, or any string that changes when the content does */
42
+ char etag[256];
43
+ /* Last-Modified, for sources without an ETag */
44
+ char lastModified[64];
45
+ } RangeSourceInfo;
46
+
47
+ /*
48
+ * Where a reader's bytes come from: the player's HTTP fetcher, or an app's data source. Open a read
49
+ * at a position, read on in order, close. One read is open at a time. open, read and close are
50
+ * called on the reader's fetch thread only; cancel may be called from any thread.
51
+ *
52
+ * Errors are written to `error`, `errorSize` bytes with the terminating NUL.
53
+ */
54
+ typedef struct RangeSourceUpstream {
55
+ /* sizeof(RangeSourceUpstream) */
56
+ uint32_t structSize;
57
+ void* context;
58
+ /*
59
+ * Opens a read of the bytes from `position` to the end, closing any read still open, and fills
60
+ * `info`. Opening at or past the end gives a read that ends at once. Returns 0, or -1.
61
+ */
62
+ int (*open)(void* context, int64_t position, RangeSourceInfo* info, char* error, size_t errorSize);
63
+ /* Reads up to `size` bytes, waiting for at least one. Returns how many, 0 at the end, or -1. */
64
+ int64_t (*read)(void* context, uint8_t* out, int64_t size, char* error, size_t errorSize);
65
+ void (*close)(void* context);
66
+ /* Makes an open or read in progress return soon, failing. May be NULL. */
67
+ void (*cancel)(void* context);
68
+ /* Called once, when the reader is done with the upstream, perhaps on another thread. May be NULL. */
69
+ void (*release)(void* context);
70
+ } RangeSourceUpstream;
71
+
72
+ /* A negative field takes the add-on's default; readAheadBytes 0 turns read-ahead off. */
73
+ typedef struct RangeSourceReaderOptions {
74
+ /* sizeof(RangeSourceReaderOptions) */
75
+ uint32_t structSize;
76
+ /* Block size in bytes. A stored copy keeps the block size it was written with. */
77
+ int64_t blockSize;
78
+ /* Bytes of blocks kept in memory, least recently used out */
79
+ int64_t memoryBytes;
80
+ /* After each read, fetch this many bytes past it in the background */
81
+ int64_t readAheadBytes;
82
+ /* A fetch this far past the open read's position reads on through it rather than reconnect */
83
+ int64_t reconnectGap;
84
+ /* Attempts after a failed open or read, each after twice the delay of the one before */
85
+ int32_t retries;
86
+ int64_t retryDelayMs;
87
+ } RangeSourceReaderOptions;
88
+
89
+ typedef struct RangeSourceStats {
90
+ /* Reads opened on the upstream, the first included */
91
+ int64_t opens;
92
+ /* Bytes read from the upstream */
93
+ int64_t bytesFetched;
94
+ } RangeSourceStats;
95
+
96
+ /*
97
+ * Every function is thread-safe. A handle is released once, by its release function; a store's
98
+ * handle may be released while readers opened with it are still reading.
99
+ */
100
+ typedef struct RangeSourcePlugin {
101
+ /* RANGE_SOURCE_ABI */
102
+ uint32_t abi;
103
+ /* sizeof(RangeSourcePlugin) when the add-on was built */
104
+ uint32_t structSize;
105
+ /* The add-on's version, such as "1.0.0" */
106
+ const char* version;
107
+
108
+ /*
109
+ * Keeps sources' bytes between plays, under a byte cap shared by every key in it; the least
110
+ * recently used keys go first. One store per folder (or name, in memory) in the process: a
111
+ * later call gets the same store, with its `maxBytes`. NULL if the folder can't be created.
112
+ */
113
+ RangeSourceStore* (*diskStore)(const char* dir, int64_t maxBytes);
114
+ RangeSourceStore* (*memoryStore)(const char* name, int64_t maxBytes);
115
+ int64_t (*storeBytesUsed)(RangeSourceStore* store);
116
+ void (*storeSetMaxBytes)(RangeSourceStore* store, int64_t maxBytes);
117
+ /* RANGE_SOURCE_HOLDS_NONE, _PART or _WHOLE */
118
+ int (*storeHolds)(RangeSourceStore* store, const char* key);
119
+ void (*storeRemove)(RangeSourceStore* store, const char* key);
120
+ void (*storeClear)(RangeSourceStore* store);
121
+ void (*releaseStore)(RangeSourceStore* store);
122
+
123
+ /*
124
+ * Opens a reader over `upstream`, which it owns from here on, even when opening fails: it calls
125
+ * upstream->release when done. With a `store` (may be NULL) and a `key`, blocks are kept there,
126
+ * and read from there before the upstream. Opens the upstream at 0 to learn the file's size and
127
+ * version, unless the store holds the file whole, and blocks for that. `options` may be NULL.
128
+ * Returns NULL, with `error` set, if it fails.
129
+ */
130
+ RangeSourceReader* (*openReader)(const RangeSourceUpstream* upstream, RangeSourceStore* store, const char* key,
131
+ const RangeSourceReaderOptions* options, char* error, size_t errorSize);
132
+ /* The file's size, or -1 while it isn't known */
133
+ int64_t (*size)(RangeSourceReader* reader);
134
+ /*
135
+ * Reads up to `size` bytes at `position`, waiting for them if they're being fetched. Returns
136
+ * how many: fewer at a block's end, 0 at or past the end of the file, -1 if they can't be
137
+ * fetched (lastError says why), once the reader is closed, or once `*abort` (may be NULL)
138
+ * becomes nonzero. `*abort` is read atomically.
139
+ */
140
+ int64_t (*read)(RangeSourceReader* reader, int64_t position, uint8_t* out, int64_t size,
141
+ const volatile int32_t* abort);
142
+ /*
143
+ * read without waiting, for a caller that must not block, such as a render loop. Returns
144
+ * RANGE_SOURCE_PENDING when the bytes aren't held yet: it asks for them, so a later call finds
145
+ * them. A later call returns -1, once, if fetching them failed; the call after that asks again.
146
+ */
147
+ int64_t (*tryRead)(RangeSourceReader* reader, int64_t position, uint8_t* out, int64_t size);
148
+ /* Reads the whole file, so that it's held in the store. Returns 1, or 0 on an error or abort. */
149
+ int (*fetchAll)(RangeSourceReader* reader, const volatile int32_t* abort);
150
+ /* Writes the last error into `out`, cut to fit, and returns its full length, like snprintf. */
151
+ size_t (*lastError)(RangeSourceReader* reader, char* out, size_t outSize);
152
+ void (*info)(RangeSourceReader* reader, RangeSourceInfo* info);
153
+ void (*stats)(RangeSourceReader* reader, RangeSourceStats* stats);
154
+ /* Fails reads in progress and later ones. A fetch still waiting on the upstream finishes in the background. */
155
+ void (*closeReader)(RangeSourceReader* reader);
156
+ /* Closes the reader if needed, and frees the handle. */
157
+ void (*releaseReader)(RangeSourceReader* reader);
158
+ } RangeSourcePlugin;
159
+
160
+ /* The add-on's table, for the add-on's own Java and Objective-C classes to hand to players. */
161
+ const RangeSourcePlugin* range_source_plugin(void);
162
+
163
+ #ifdef __cplusplus
164
+ } /* extern "C" */
165
+ #endif
166
+
167
+ #if defined(__cplusplus) && defined(RANGE_SOURCE_CLIENT_NAMESPACE)
168
+
169
+ #include <atomic>
170
+ #include <cstring>
171
+ #include <memory>
172
+ #include <string>
173
+ #include <utility>
174
+
175
+ namespace RANGE_SOURCE_CLIENT_NAMESPACE {
176
+
177
+ struct SourceInfo {
178
+ int64_t size = -1;
179
+ std::string etag;
180
+ std::string lastModified;
181
+ };
182
+
183
+ /** An upstream in C++, which RangeReader::open hands to the add-on as a RangeSourceUpstream. */
184
+ class Upstream {
185
+ public:
186
+ virtual ~Upstream() = default;
187
+ virtual bool open(int64_t position, SourceInfo& info, std::string& error) = 0;
188
+ virtual int64_t read(uint8_t* out, int64_t size, std::string& error) = 0;
189
+ virtual void close() = 0;
190
+ virtual void cancel() {}
191
+
192
+ /** `upstream` as a RangeSourceUpstream that owns it. */
193
+ static RangeSourceUpstream toC(std::unique_ptr<Upstream> upstream) {
194
+ RangeSourceUpstream c{};
195
+ c.structSize = sizeof(RangeSourceUpstream);
196
+ c.context = upstream.release();
197
+ c.open = [](void* context, int64_t position, RangeSourceInfo* info, char* error, size_t errorSize) {
198
+ SourceInfo got;
199
+ std::string message;
200
+ if (!static_cast<Upstream*>(context)->open(position, got, message)) {
201
+ copy(message, error, errorSize);
202
+ return -1;
203
+ }
204
+ info->size = got.size;
205
+ copy(got.etag, info->etag, sizeof(info->etag));
206
+ copy(got.lastModified, info->lastModified, sizeof(info->lastModified));
207
+ return 0;
208
+ };
209
+ c.read = [](void* context, uint8_t* out, int64_t size, char* error, size_t errorSize) {
210
+ std::string message;
211
+ const int64_t n = static_cast<Upstream*>(context)->read(out, size, message);
212
+ if (n < 0) copy(message, error, errorSize);
213
+ return n;
214
+ };
215
+ c.close = [](void* context) { static_cast<Upstream*>(context)->close(); };
216
+ c.cancel = [](void* context) { static_cast<Upstream*>(context)->cancel(); };
217
+ c.release = [](void* context) { delete static_cast<Upstream*>(context); };
218
+ return c;
219
+ }
220
+
221
+ static void copy(const std::string& from, char* to, size_t toSize) {
222
+ if (!to || toSize == 0) return;
223
+ const size_t n = from.size() < toSize - 1 ? from.size() : toSize - 1;
224
+ std::memcpy(to, from.data(), n);
225
+ to[n] = '\0';
226
+ }
227
+ };
228
+
229
+ /** A negative field takes the add-on's default. */
230
+ struct ReaderOptions {
231
+ int64_t blockSize = -1;
232
+ int64_t memoryBytes = -1;
233
+ int64_t readAheadBytes = -1;
234
+ int64_t reconnectGap = -1;
235
+ int retries = -1;
236
+ int64_t retryDelayMs = -1;
237
+ };
238
+
239
+ class Store {
240
+ public:
241
+ static std::shared_ptr<Store> disk(const RangeSourcePlugin* plugin, const std::string& dir, int64_t maxBytes) {
242
+ return wrap(plugin, plugin->diskStore(dir.c_str(), maxBytes));
243
+ }
244
+ static std::shared_ptr<Store> memory(const RangeSourcePlugin* plugin, const std::string& name, int64_t maxBytes) {
245
+ return wrap(plugin, plugin->memoryStore(name.c_str(), maxBytes));
246
+ }
247
+
248
+ ~Store() { plugin_->releaseStore(store_); }
249
+ Store(const Store&) = delete;
250
+ Store& operator=(const Store&) = delete;
251
+
252
+ int64_t bytesUsed() const { return plugin_->storeBytesUsed(store_); }
253
+ void setMaxBytes(int64_t maxBytes) { plugin_->storeSetMaxBytes(store_, maxBytes); }
254
+ /** RANGE_SOURCE_HOLDS_NONE, _PART or _WHOLE */
255
+ int holds(const std::string& key) const { return plugin_->storeHolds(store_, key.c_str()); }
256
+ void remove(const std::string& key) { plugin_->storeRemove(store_, key.c_str()); }
257
+ void clear() { plugin_->storeClear(store_); }
258
+ RangeSourceStore* handle() const { return store_; }
259
+
260
+ private:
261
+ Store(const RangeSourcePlugin* plugin, RangeSourceStore* store) : plugin_(plugin), store_(store) {}
262
+ static std::shared_ptr<Store> wrap(const RangeSourcePlugin* plugin, RangeSourceStore* store) {
263
+ return store ? std::shared_ptr<Store>(new Store(plugin, store)) : nullptr;
264
+ }
265
+
266
+ const RangeSourcePlugin* const plugin_;
267
+ RangeSourceStore* const store_;
268
+ };
269
+
270
+ /**
271
+ * What a player reads a file through: the add-on's RangeReader, or, without the add-on, a
272
+ * DownloadReader (range_source_download.h). Thread-safe.
273
+ */
274
+ class Reader {
275
+ public:
276
+ static constexpr int64_t kPending = RANGE_SOURCE_PENDING;
277
+
278
+ virtual ~Reader() = default;
279
+ /**
280
+ * Reads up to `size` bytes at `pos`, waiting for them. Returns how many, 0 at or past the end,
281
+ * or -1 if they can't be had (lastError() says why), once closed, or once `*abort` is nonzero.
282
+ */
283
+ virtual int64_t read(int64_t pos, uint8_t* out, int64_t size, const std::atomic<int32_t>* abort = nullptr) = 0;
284
+ /** read() without waiting: kPending while the bytes are on their way. */
285
+ virtual int64_t tryRead(int64_t pos, uint8_t* out, int64_t size) = 0;
286
+ /** Waits until the whole file is held. False on an error, once closed, or on an abort. */
287
+ virtual bool fetchAll(const std::atomic<int32_t>* abort = nullptr) = 0;
288
+ /** The file's size, or -1 while it isn't known. */
289
+ virtual int64_t size() const = 0;
290
+ virtual std::string lastError() const = 0;
291
+ /** Fails reads in progress and later ones, and stops fetching. */
292
+ virtual void close() = 0;
293
+ };
294
+
295
+ /** The add-on's reader, with the C++ reader's methods. */
296
+ class RangeReader : public Reader {
297
+ public:
298
+ struct Stats {
299
+ int64_t opens = 0;
300
+ int64_t bytesFetched = 0;
301
+ };
302
+
303
+ static std::shared_ptr<RangeReader> open(const RangeSourcePlugin* plugin, std::unique_ptr<Upstream> upstream,
304
+ const std::shared_ptr<Store>& store, const std::string& key,
305
+ const ReaderOptions& options, std::string& error) {
306
+ return open(plugin, Upstream::toC(std::move(upstream)), store, key, options, error);
307
+ }
308
+
309
+ /** Over an upstream already in C, such as the add-on's for an app's data source; owns it from here on. */
310
+ static std::shared_ptr<RangeReader> open(const RangeSourcePlugin* plugin, const RangeSourceUpstream& c,
311
+ const std::shared_ptr<Store>& store, const std::string& key,
312
+ const ReaderOptions& options, std::string& error) {
313
+ RangeSourceReaderOptions o{};
314
+ o.structSize = sizeof(o);
315
+ o.blockSize = options.blockSize;
316
+ o.memoryBytes = options.memoryBytes;
317
+ o.readAheadBytes = options.readAheadBytes;
318
+ o.reconnectGap = options.reconnectGap;
319
+ o.retries = options.retries;
320
+ o.retryDelayMs = options.retryDelayMs;
321
+ char message[512] = "";
322
+ RangeSourceReader* reader =
323
+ plugin->openReader(&c, store ? store->handle() : nullptr, key.c_str(), &o, message, sizeof(message));
324
+ if (!reader) {
325
+ error = message;
326
+ return nullptr;
327
+ }
328
+ return std::shared_ptr<RangeReader>(new RangeReader(plugin, reader));
329
+ }
330
+
331
+ ~RangeReader() override { plugin_->releaseReader(reader_); }
332
+ RangeReader(const RangeReader&) = delete;
333
+ RangeReader& operator=(const RangeReader&) = delete;
334
+
335
+ int64_t read(int64_t pos, uint8_t* out, int64_t size, const std::atomic<int32_t>* abort = nullptr) override {
336
+ return plugin_->read(reader_, pos, out, size, cFlag(abort));
337
+ }
338
+ int64_t tryRead(int64_t pos, uint8_t* out, int64_t size) override {
339
+ return plugin_->tryRead(reader_, pos, out, size);
340
+ }
341
+ bool fetchAll(const std::atomic<int32_t>* abort = nullptr) override {
342
+ return plugin_->fetchAll(reader_, cFlag(abort)) != 0;
343
+ }
344
+ int64_t size() const override { return plugin_->size(reader_); }
345
+
346
+ SourceInfo info() const {
347
+ RangeSourceInfo c{};
348
+ plugin_->info(reader_, &c);
349
+ SourceInfo info;
350
+ info.size = c.size;
351
+ info.etag = c.etag;
352
+ info.lastModified = c.lastModified;
353
+ return info;
354
+ }
355
+
356
+ std::string lastError() const override {
357
+ char message[512];
358
+ const size_t n = plugin_->lastError(reader_, message, sizeof(message));
359
+ if (n < sizeof(message)) return std::string(message, n);
360
+ std::string whole(n + 1, '\0');
361
+ plugin_->lastError(reader_, &whole[0], whole.size());
362
+ whole.resize(n);
363
+ return whole;
364
+ }
365
+
366
+ Stats stats() const {
367
+ RangeSourceStats c{};
368
+ plugin_->stats(reader_, &c);
369
+ Stats stats;
370
+ stats.opens = c.opens;
371
+ stats.bytesFetched = c.bytesFetched;
372
+ return stats;
373
+ }
374
+
375
+ void close() override { plugin_->closeReader(reader_); }
376
+
377
+ private:
378
+ RangeReader(const RangeSourcePlugin* plugin, RangeSourceReader* reader) : plugin_(plugin), reader_(reader) {}
379
+
380
+ // std::atomic<int32_t> is an int32_t on every compiler the players build with
381
+ static const volatile int32_t* cFlag(const std::atomic<int32_t>* abort) {
382
+ static_assert(sizeof(std::atomic<int32_t>) == sizeof(int32_t) && std::atomic<int32_t>::is_always_lock_free,
383
+ "std::atomic<int32_t> must be a plain int32_t");
384
+ return reinterpret_cast<const volatile int32_t*>(abort);
385
+ }
386
+
387
+ const RangeSourcePlugin* const plugin_;
388
+ RangeSourceReader* const reader_;
389
+ };
390
+
391
+ } // namespace RANGE_SOURCE_CLIENT_NAMESPACE
392
+
393
+ #endif /* __cplusplus && RANGE_SOURCE_CLIENT_NAMESPACE */
394
+
395
+ #endif /* RANGE_SOURCE_H */