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") {
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 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  */
160 PT(MovieVideo) MovieTypeRegistry::
161 make_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  */
213 register_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  */
291 load_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.