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  _audio_lock.lock();
35 
36  // Make sure that the list of audio types has been read in.
38 
39  // Maybe we need to load a module?
40  if (_deferred_audio_types.count(ext)) {
41  load_movie_library(_deferred_audio_types[ext]);
42  _deferred_audio_types.erase(ext);
43  }
44 
45  // Explicit extension is preferred over catch-all.
46  if (_audio_type_registry.count(ext)) {
47  MakeAudioFunc func = _audio_type_registry[ext];
48  _audio_lock.unlock();
49  return (*func)(name);
50  }
51 
52  // If we didn't find it, see if there was a type registered with '*' as
53  // extension. This is a catch-all loader.
54  if (_deferred_audio_types.count("*")) {
55  load_movie_library(_deferred_audio_types["*"]);
56  _deferred_audio_types.erase("*");
57  }
58 
59  if (_audio_type_registry.count("*")) {
60  MakeAudioFunc func = _audio_type_registry["*"];
61  _audio_lock.unlock();
62  return (*func)(name);
63  }
64 
65  movies_cat.error()
66  << "Support for audio files with extension ." << ext << " was not enabled.\n";
67 
68  _audio_lock.unlock();
69  return new MovieAudio("Load-Failure Stub");
70 }
71 
72 /**
73  * Registers a MovieAudio type, so that files with any of the given extensions
74  * will be loaded as this type. You may use * as a catch-all extension.
75  */
77 register_audio_type(MakeAudioFunc func, const string &extensions) {
78  ReMutexHolder holder(_audio_lock);
79  vector_string words;
80  extract_words(downcase(extensions), words);
81 
82  vector_string::const_iterator wi;
83  for (wi = words.begin(); wi != words.end(); ++wi) {
84  if (_audio_type_registry.count(*wi)) {
85  movies_cat->warning()
86  << "Attempt to register multiple audio types with extension " << (*wi) << "\n";
87  } else {
88  movies_cat->debug()
89  << "Registered audio type with extension " << (*wi) << "\n";
90  }
91  _audio_type_registry[*wi] = func;
92  }
93 }
94 
95 /**
96  * Loads the list with audio types, if we haven't already.
97  */
100  ReMutexHolder holder(_audio_lock);
101  static bool audio_types_loaded = false;
102 
103  if (!audio_types_loaded) {
104  int num_unique_values = load_audio_type.get_num_unique_values();
105 
106  for (int i = 0; i < num_unique_values; i++) {
107  string param = load_audio_type.get_unique_value(i);
108 
109  vector_string words;
110  extract_words(param, words);
111 
112  if (words.size() == 1) {
113  // Exactly one word: load the named library immediately.
114  string name = words[0];
115  Filename dlname = Filename::dso_filename("lib" + name + ".so");
116  movies_cat.info()
117  << "loading audio type module: " << name << endl;
118  void *tmp = load_dso(get_plugin_path().get_value(), dlname);
119  if (tmp == nullptr) {
120  movies_cat.warning()
121  << "Unable to load " << dlname.to_os_specific()
122  << ": " << load_dso_error() << endl;
123  } else if (movies_cat.is_debug()) {
124  movies_cat.debug()
125  << "done loading audio type module: " << name << endl;
126  }
127 
128  } else if (words.size() > 1) {
129  // Multiple words: the first n words are filename extensions, and the
130  // last word is the name of the library to load should any of those
131  // filename extensions be encountered.
132  size_t num_extensions = words.size() - 1;
133  string library_name = words[num_extensions];
134 
135  for (size_t i = 0; i < num_extensions; i++) {
136  string extension = downcase(words[i]);
137  if (extension[0] == '.') {
138  extension = extension.substr(1);
139  }
140 
141  _deferred_audio_types[extension] = library_name;
142  }
143  }
144  }
145 
146  audio_types_loaded = true;
147  }
148 }
149 
150 /**
151  * Obtains a MovieVideo that references a file.
152  */
153 PT(MovieVideo) MovieTypeRegistry::
154 make_video(const Filename &name) {
155  string ext = downcase(name.get_extension());
156 
157  _video_lock.lock();
158 
159  // Make sure that the list of video types has been read in.
161 
162  // Maybe we need to load a module?
163  if (_deferred_video_types.count(ext)) {
164  load_movie_library(_deferred_video_types[ext]);
165  _deferred_video_types.erase(ext);
166  }
167 
168  // Explicit extension is preferred over catch-all.
169  if (_video_type_registry.count(ext)) {
170  MakeVideoFunc func = _video_type_registry[ext];
171  _video_lock.unlock();
172  return (*func)(name);
173  }
174 
175  // If we didn't find it, see if there was a type registered with '*' as
176  // extension. This is a catch-all loader.
177  if (_deferred_video_types.count("*")) {
178  load_movie_library(_deferred_video_types["*"]);
179  _deferred_video_types.erase("*");
180  }
181 
182  if (_video_type_registry.count("*")) {
183  MakeVideoFunc func = _video_type_registry["*"];
184  _video_lock.unlock();
185  return (*func)(name);
186  }
187 
188  movies_cat.error()
189  << "Support for video files with extension ." << ext << " was not enabled.\n";
190 
191  _video_lock.unlock();
192  return new MovieVideo("Load-Failure Stub");
193 }
194 
195 /**
196  * Registers a MovieVideo type, so that files with any of the given extensions
197  * will be loaded as this type. You may use * as a catch-all extension.
198  */
200 register_video_type(MakeVideoFunc func, const string &extensions) {
201  ReMutexHolder holder(_video_lock);
202  vector_string words;
203  extract_words(downcase(extensions), words);
204 
205  vector_string::const_iterator wi;
206  for (wi = words.begin(); wi != words.end(); ++wi) {
207  if (_video_type_registry.count(*wi)) {
208  movies_cat->warning()
209  << "Attempt to register multiple video types with extension " << (*wi) << "\n";
210  } else {
211  movies_cat->debug()
212  << "Registered video type with extension " << (*wi) << "\n";
213  }
214  _video_type_registry[*wi] = func;
215  }
216 }
217 
218 /**
219  * Loads the list with video types, if we haven't already.
220  */
223  ReMutexHolder holder(_video_lock);
224  static bool video_types_loaded = false;
225 
226  if (!video_types_loaded) {
227  int num_unique_values = load_video_type.get_num_unique_values();
228 
229  for (int i = 0; i < num_unique_values; i++) {
230  string param = load_video_type.get_unique_value(i);
231 
232  vector_string words;
233  extract_words(param, words);
234 
235  if (words.size() == 1) {
236  // Exactly one word: load the named library immediately.
237  string name = words[0];
238  Filename dlname = Filename::dso_filename("lib" + name + ".so");
239  movies_cat.info()
240  << "loading video type module: " << name << endl;
241  void *tmp = load_dso(get_plugin_path().get_value(), dlname);
242  if (tmp == nullptr) {
243  movies_cat.warning()
244  << "Unable to load " << dlname.to_os_specific()
245  << ": " << load_dso_error() << endl;
246  } else if (movies_cat.is_debug()) {
247  movies_cat.debug()
248  << "done loading video type module: " << name << endl;
249  }
250 
251  } else if (words.size() > 1) {
252  // Multiple words: the first n words are filename extensions, and the
253  // last word is the name of the library to load should any of those
254  // filename extensions be encountered.
255  size_t num_extensions = words.size() - 1;
256  string library_name = words[num_extensions];
257 
258  for (size_t i = 0; i < num_extensions; i++) {
259  string extension = downcase(words[i]);
260  if (extension[0] == '.') {
261  extension = extension.substr(1);
262  }
263 
264  _deferred_video_types[extension] = library_name;
265  }
266  }
267  }
268 
269  video_types_loaded = true;
270  }
271 }
272 
273 /**
274  * Loads the module.
275  */
277 load_movie_library(const string &name) {
278  ReMutexHolder holder(_video_lock);
279  Filename dlname = Filename::dso_filename("lib" + name + ".so");
280  movies_cat.info()
281  << "loading video type module: " << name << endl;
282  void *tmp = load_dso(get_plugin_path().get_value(), dlname);
283 
284  if (tmp == nullptr) {
285  movies_cat.warning()
286  << "Unable to load " << dlname.to_os_specific()
287  << ": " << load_dso_error() << endl;
288  } else if (movies_cat.is_debug()) {
289  movies_cat.debug()
290  << "done loading video type module: " << name << endl;
291  }
292 }
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.
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.