Panda3D
movieTypeRegistry.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file movieTypeRegistry.cxx
10 * @author rdb
11 * @date 2013-08-24
12 */
13
14#include "movieTypeRegistry.h"
15
16#include "string_utils.h"
17#include "config_movies.h"
18#include "config_putil.h"
19#include "load_dso.h"
20#include "reMutexHolder.h"
21
22using std::endl;
23using std::string;
24
25MovieTypeRegistry *MovieTypeRegistry::_global_ptr = nullptr;
26
27/**
28 * Obtains a MovieVideo that references a file.
29 */
30PT(MovieAudio) MovieTypeRegistry::
31make_audio(const Filename &name) {
32 string ext = downcase(name.get_extension());
33
34#ifdef HAVE_ZLIB
35 if (ext == "pz" || ext == "gz") {
37 }
38#endif
39
40 _audio_lock.lock();
41
42 // Make sure that the list of audio types has been read in.
44
45 // Maybe we need to load a module?
46 if (_deferred_audio_types.count(ext)) {
47 load_movie_library(_deferred_audio_types[ext]);
48 _deferred_audio_types.erase(ext);
49 }
50
51 // Explicit extension is preferred over catch-all.
52 if (_audio_type_registry.count(ext)) {
53 MakeAudioFunc func = _audio_type_registry[ext];
54 _audio_lock.unlock();
55 return (*func)(name);
56 }
57
58 // If we didn't find it, see if there was a type registered with '*' as
59 // extension. This is a catch-all loader.
60 if (_deferred_audio_types.count("*")) {
61 load_movie_library(_deferred_audio_types["*"]);
62 _deferred_audio_types.erase("*");
63 }
64
65 if (_audio_type_registry.count("*")) {
66 MakeAudioFunc func = _audio_type_registry["*"];
67 _audio_lock.unlock();
68 return (*func)(name);
69 }
70
71 movies_cat.error()
72 << "Support for audio files with extension ." << ext << " was not enabled.\n";
73
74 _audio_lock.unlock();
75 return new MovieAudio("Load-Failure Stub");
76}
77
78/**
79 * Registers a MovieAudio type, so that files with any of the given extensions
80 * will be loaded as this type. You may use * as a catch-all extension.
81 */
83register_audio_type(MakeAudioFunc func, const string &extensions) {
84 ReMutexHolder holder(_audio_lock);
85 vector_string words;
86 extract_words(downcase(extensions), words);
87
88 vector_string::const_iterator wi;
89 for (wi = words.begin(); wi != words.end(); ++wi) {
90 if (_audio_type_registry.count(*wi)) {
91 movies_cat->warning()
92 << "Attempt to register multiple audio types with extension " << (*wi) << "\n";
93 } else if (movies_cat->is_debug()) {
94 movies_cat->debug()
95 << "Registered audio type with extension " << (*wi) << "\n";
96 }
97 _audio_type_registry[*wi] = func;
98 }
99}
100
101/**
102 * Loads the list with audio types, if we haven't already.
103 */
106 ReMutexHolder holder(_audio_lock);
107 static bool audio_types_loaded = false;
108
109 if (!audio_types_loaded) {
110 int num_unique_values = load_audio_type.get_num_unique_values();
111
112 for (int i = 0; i < num_unique_values; i++) {
113 string param = load_audio_type.get_unique_value(i);
114
115 vector_string words;
116 extract_words(param, words);
117
118 if (words.size() == 1) {
119 // Exactly one word: load the named library immediately.
120 string name = words[0];
121 Filename dlname = Filename::dso_filename("lib" + name + ".so");
122 movies_cat.info()
123 << "loading audio type module: " << name << endl;
124 void *tmp = load_dso(get_plugin_path().get_value(), dlname);
125 if (tmp == nullptr) {
126 std::string error = load_dso_error();
127 movies_cat.warning()
128 << "Unable to load " << dlname.to_os_specific()
129 << ": " << error << endl;
130 } else if (movies_cat.is_debug()) {
131 movies_cat.debug()
132 << "done loading audio type module: " << name << endl;
133 }
134
135 } else if (words.size() > 1) {
136 // Multiple words: the first n words are filename extensions, and the
137 // last word is the name of the library to load should any of those
138 // filename extensions be encountered.
139 size_t num_extensions = words.size() - 1;
140 string library_name = words[num_extensions];
141
142 for (size_t i = 0; i < num_extensions; i++) {
143 string extension = downcase(words[i]);
144 if (extension[0] == '.') {
145 extension = extension.substr(1);
146 }
147
148 _deferred_audio_types[extension] = library_name;
149 }
150 }
151 }
152
153 audio_types_loaded = true;
154 }
155}
156
157/**
158 * Obtains a MovieVideo that references a file.
159 */
160PT(MovieVideo) MovieTypeRegistry::
161make_video(const Filename &name) {
162 string ext = downcase(name.get_extension());
163
164#ifdef HAVE_ZLIB
165 if (ext == "pz" || ext == "gz") {
167 }
168#endif
169
170 _video_lock.lock();
171
172 // Make sure that the list of video types has been read in.
174
175 // Maybe we need to load a module?
176 if (_deferred_video_types.count(ext)) {
177 load_movie_library(_deferred_video_types[ext]);
178 _deferred_video_types.erase(ext);
179 }
180
181 // Explicit extension is preferred over catch-all.
182 if (_video_type_registry.count(ext)) {
183 MakeVideoFunc func = _video_type_registry[ext];
184 _video_lock.unlock();
185 return (*func)(name);
186 }
187
188 // If we didn't find it, see if there was a type registered with '*' as
189 // extension. This is a catch-all loader.
190 if (_deferred_video_types.count("*")) {
191 load_movie_library(_deferred_video_types["*"]);
192 _deferred_video_types.erase("*");
193 }
194
195 if (_video_type_registry.count("*")) {
196 MakeVideoFunc func = _video_type_registry["*"];
197 _video_lock.unlock();
198 return (*func)(name);
199 }
200
201 movies_cat.error()
202 << "Support for video files with extension ." << ext << " was not enabled.\n";
203
204 _video_lock.unlock();
205 return new MovieVideo("Load-Failure Stub");
206}
207
208/**
209 * Registers a MovieVideo type, so that files with any of the given extensions
210 * will be loaded as this type. You may use * as a catch-all extension.
211 */
213register_video_type(MakeVideoFunc func, const string &extensions) {
214 ReMutexHolder holder(_video_lock);
215 vector_string words;
216 extract_words(downcase(extensions), words);
217
218 vector_string::const_iterator wi;
219 for (wi = words.begin(); wi != words.end(); ++wi) {
220 if (_video_type_registry.count(*wi)) {
221 movies_cat->warning()
222 << "Attempt to register multiple video types with extension " << (*wi) << "\n";
223 } else if (movies_cat->is_debug()) {
224 movies_cat->debug()
225 << "Registered video type with extension " << (*wi) << "\n";
226 }
227 _video_type_registry[*wi] = func;
228 }
229}
230
231/**
232 * Loads the list with video types, if we haven't already.
233 */
236 ReMutexHolder holder(_video_lock);
237 static bool video_types_loaded = false;
238
239 if (!video_types_loaded) {
240 int num_unique_values = load_video_type.get_num_unique_values();
241
242 for (int i = 0; i < num_unique_values; i++) {
243 string param = load_video_type.get_unique_value(i);
244
245 vector_string words;
246 extract_words(param, words);
247
248 if (words.size() == 1) {
249 // Exactly one word: load the named library immediately.
250 string name = words[0];
251 Filename dlname = Filename::dso_filename("lib" + name + ".so");
252 movies_cat.info()
253 << "loading video type module: " << name << endl;
254 void *tmp = load_dso(get_plugin_path().get_value(), dlname);
255 if (tmp == nullptr) {
256 std::string error = load_dso_error();
257 movies_cat.warning()
258 << "Unable to load " << dlname.to_os_specific()
259 << ": " << error << endl;
260 } else if (movies_cat.is_debug()) {
261 movies_cat.debug()
262 << "done loading video type module: " << name << endl;
263 }
264
265 } else if (words.size() > 1) {
266 // Multiple words: the first n words are filename extensions, and the
267 // last word is the name of the library to load should any of those
268 // filename extensions be encountered.
269 size_t num_extensions = words.size() - 1;
270 string library_name = words[num_extensions];
271
272 for (size_t i = 0; i < num_extensions; i++) {
273 string extension = downcase(words[i]);
274 if (extension[0] == '.') {
275 extension = extension.substr(1);
276 }
277
278 _deferred_video_types[extension] = library_name;
279 }
280 }
281 }
282
283 video_types_loaded = true;
284 }
285}
286
287/**
288 * Loads the module.
289 */
291load_movie_library(const string &name) {
292 ReMutexHolder holder(_video_lock);
293 Filename dlname = Filename::dso_filename("lib" + name + ".so");
294 movies_cat.info()
295 << "loading video type module: " << name << endl;
296 void *tmp = load_dso(get_plugin_path().get_value(), dlname);
297
298 if (tmp == nullptr) {
299 std::string error = load_dso_error();
300 movies_cat.warning()
301 << "Unable to load " << dlname.to_os_specific()
302 << ": " << error << endl;
303 } else if (movies_cat.is_debug()) {
304 movies_cat.debug()
305 << "done loading video type module: " << name << endl;
306 }
307}
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
Definition: filename.cxx:1123
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:386
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:44
This class records the different types of MovieAudio and MovieVideo that are available for loading.
void register_video_type(MakeVideoFunc func, const std::string &extensions)
Registers a MovieVideo type, so that files with any of the given extensions will be loaded as this ty...
void load_audio_types()
Loads the list with audio types, if we haven't already.
void register_audio_type(MakeAudioFunc func, const std::string &extensions)
Registers a MovieAudio type, so that files with any of the given extensions will be loaded as this ty...
void load_video_types()
Loads the list with video types, if we haven't already.
void load_movie_library(const std::string &name)
Loads the module.
A MovieVideo is actually any source that provides a sequence of video frames.
Definition: movieVideo.h:38
void unlock()
Alias for release() to match C++11 semantics.
Definition: reMutexDirect.I:62
void lock()
Alias for acquire() to match C++11 semantics.
Definition: reMutexDirect.I:34
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(MovieAudio) MovieTypeRegistry
Obtains a MovieVideo that references a file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int extract_words(const string &str, vector_string &words)
Divides the string into a number of words according to whitespace.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.