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 
22 using std::endl;
23 using std::string;
24 
25 MovieTypeRegistry *MovieTypeRegistry::_global_ptr = nullptr;
26 
27 /**
28  * Obtains a MovieVideo that references a file.
29  */
30 PT(MovieAudio) MovieTypeRegistry::
31 make_audio(const Filename &name) {
32  string ext = downcase(name.get_extension());
33 
34 #ifdef HAVE_ZLIB
35  if (ext == "pz" || ext == "gz") {
36  ext = Filename(name.get_basename_wo_extension()).get_extension();
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  */
83 register_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 {
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  movies_cat.warning()
127  << "Unable to load " << dlname.to_os_specific()
128  << ": " << load_dso_error() << endl;
129  } else if (movies_cat.is_debug()) {
130  movies_cat.debug()
131  << "done loading audio type module: " << name << endl;
132  }
133 
134  } else if (words.size() > 1) {
135  // Multiple words: the first n words are filename extensions, and the
136  // last word is the name of the library to load should any of those
137  // filename extensions be encountered.
138  size_t num_extensions = words.size() - 1;
139  string library_name = words[num_extensions];
140 
141  for (size_t i = 0; i < num_extensions; i++) {
142  string extension = downcase(words[i]);
143  if (extension[0] == '.') {
144  extension = extension.substr(1);
145  }
146 
147  _deferred_audio_types[extension] = library_name;
148  }
149  }
150  }
151 
152  audio_types_loaded = true;
153  }
154 }
155 
156 /**
157  * Obtains a MovieVideo that references a file.
158  */
159 PT(MovieVideo) MovieTypeRegistry::
160 make_video(const Filename &name) {
161  string ext = downcase(name.get_extension());
162 
163 #ifdef HAVE_ZLIB
164  if (ext == "pz" || ext == "gz") {
165  ext = Filename(name.get_basename_wo_extension()).get_extension();
166  }
167 #endif
168 
169  _video_lock.lock();
170 
171  // Make sure that the list of video types has been read in.
173 
174  // Maybe we need to load a module?
175  if (_deferred_video_types.count(ext)) {
176  load_movie_library(_deferred_video_types[ext]);
177  _deferred_video_types.erase(ext);
178  }
179 
180  // Explicit extension is preferred over catch-all.
181  if (_video_type_registry.count(ext)) {
182  MakeVideoFunc func = _video_type_registry[ext];
183  _video_lock.unlock();
184  return (*func)(name);
185  }
186 
187  // If we didn't find it, see if there was a type registered with '*' as
188  // extension. This is a catch-all loader.
189  if (_deferred_video_types.count("*")) {
190  load_movie_library(_deferred_video_types["*"]);
191  _deferred_video_types.erase("*");
192  }
193 
194  if (_video_type_registry.count("*")) {
195  MakeVideoFunc func = _video_type_registry["*"];
196  _video_lock.unlock();
197  return (*func)(name);
198  }
199 
200  movies_cat.error()
201  << "Support for video files with extension ." << ext << " was not enabled.\n";
202 
203  _video_lock.unlock();
204  return new MovieVideo("Load-Failure Stub");
205 }
206 
207 /**
208  * Registers a MovieVideo type, so that files with any of the given extensions
209  * will be loaded as this type. You may use * as a catch-all extension.
210  */
212 register_video_type(MakeVideoFunc func, const string &extensions) {
213  ReMutexHolder holder(_video_lock);
214  vector_string words;
215  extract_words(downcase(extensions), words);
216 
217  vector_string::const_iterator wi;
218  for (wi = words.begin(); wi != words.end(); ++wi) {
219  if (_video_type_registry.count(*wi)) {
220  movies_cat->warning()
221  << "Attempt to register multiple video types with extension " << (*wi) << "\n";
222  } else {
223  movies_cat->debug()
224  << "Registered video type with extension " << (*wi) << "\n";
225  }
226  _video_type_registry[*wi] = func;
227  }
228 }
229 
230 /**
231  * Loads the list with video types, if we haven't already.
232  */
235  ReMutexHolder holder(_video_lock);
236  static bool video_types_loaded = false;
237 
238  if (!video_types_loaded) {
239  int num_unique_values = load_video_type.get_num_unique_values();
240 
241  for (int i = 0; i < num_unique_values; i++) {
242  string param = load_video_type.get_unique_value(i);
243 
244  vector_string words;
245  extract_words(param, words);
246 
247  if (words.size() == 1) {
248  // Exactly one word: load the named library immediately.
249  string name = words[0];
250  Filename dlname = Filename::dso_filename("lib" + name + ".so");
251  movies_cat.info()
252  << "loading video type module: " << name << endl;
253  void *tmp = load_dso(get_plugin_path().get_value(), dlname);
254  if (tmp == nullptr) {
255  movies_cat.warning()
256  << "Unable to load " << dlname.to_os_specific()
257  << ": " << load_dso_error() << endl;
258  } else if (movies_cat.is_debug()) {
259  movies_cat.debug()
260  << "done loading video type module: " << name << endl;
261  }
262 
263  } else if (words.size() > 1) {
264  // Multiple words: the first n words are filename extensions, and the
265  // last word is the name of the library to load should any of those
266  // filename extensions be encountered.
267  size_t num_extensions = words.size() - 1;
268  string library_name = words[num_extensions];
269 
270  for (size_t i = 0; i < num_extensions; i++) {
271  string extension = downcase(words[i]);
272  if (extension[0] == '.') {
273  extension = extension.substr(1);
274  }
275 
276  _deferred_video_types[extension] = library_name;
277  }
278  }
279  }
280 
281  video_types_loaded = true;
282  }
283 }
284 
285 /**
286  * Loads the module.
287  */
289 load_movie_library(const string &name) {
290  ReMutexHolder holder(_video_lock);
291  Filename dlname = Filename::dso_filename("lib" + name + ".so");
292  movies_cat.info()
293  << "loading video type module: " << name << endl;
294  void *tmp = load_dso(get_plugin_path().get_value(), dlname);
295 
296  if (tmp == nullptr) {
297  movies_cat.warning()
298  << "Unable to load " << dlname.to_os_specific()
299  << ": " << load_dso_error() << endl;
300  } else if (movies_cat.is_debug()) {
301  movies_cat.debug()
302  << "done loading video type module: " << name << endl;
303  }
304 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
void load_audio_types()
Loads the list with audio types, if we haven't already.
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:386
This class records the different types of MovieAudio and MovieVideo that are available for loading.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
void lock()
Alias for acquire() to match C++11 semantics.
Definition: reMutexDirect.I:34
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.
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.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
void load_movie_library(const std::string &name)
Loads the module.
void unlock()
Alias for release() to match C++11 semantics.
Definition: reMutexDirect.I:62
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
A MovieVideo is actually any source that provides a sequence of video frames.
Definition: movieVideo.h:38
void load_video_types()
Loads the list with video types, if we haven't already.
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...
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:44
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...
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.