libvisual  0.5.0
lv_param.cpp
1 /* Libvisual - The audio visualisation framework.
2  *
3  * Copyright (C) 2012-2013 Libvisual team
4  *
5  * Authors: Chong Kai Xiong <kaixiong@codeleft.sg>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #include "config.h"
23 #include "lv_param.h"
24 #include "lv_common.h"
25 #include "lv_util.hpp"
26 #include <map>
27 #include <list>
28 #include <stdexcept>
29 #include <cstdarg>
30 
31 namespace LV
32 {
33  class Closure
34  {
35  public:
36 
37  void (*func) ();
38  void* data;
39  VisDestroyFunc destroy_func;
40 
41  Closure (void* func, void* data, VisDestroyFunc destroy_func);
42 
43  ~Closure ();
44 
45  // Non-copyable
46  Closure (Closure const&) = delete;
47  Closure& operator= (Closure const&) = delete;
48  };
49 
50  class Param
51  {
52  public:
53 
54  typedef std::list<std::unique_ptr<Closure> > HandlerList;
55 
56  ParamList* parent;
57  std::string name;
58  std::string description;
59  VisParamValue* value;
60  VisParamValue* default_value;
61  HandlerList changed_handlers;
62 
63  std::unique_ptr<Closure> validator;
64 
65  Param (std::string const& name,
66  std::string const& description,
67  VisParamType type,
68  void* default_value,
69  Closure* validator);
70 
71  ~Param ();
72 
73  // Non-copyable
74  Param (Param const&) = delete;
75  Param& operator= (Param const&) = delete;
76 
77  Closure* add_callback (VisParamChangedFunc func,
78  void* priv,
79  VisDestroyFunc destroy_func);
80 
81  bool remove_callback (Closure* to_remove);
82 
83  void changed ();
84 
85  void notify_callbacks ();
86  };
87 
88  class ParamList::Impl
89  {
90  public:
91 
92  typedef std::map<std::string, std::unique_ptr<Param>> Entries;
93 
94  Entries entries;
95  EventQueue* event_queue;
96 
97  Impl ();
98 
99  ~Impl ();
100  };
101 
102  namespace {
103 
104  int validate_param_value (VisParamValue *value, Closure *validator)
105  {
106  return (* (VisParamValidateFunc) validator->func) (value, validator->data);
107  }
108 
109  } // anonymous namespace
110 
111  // LV::Closure implementation
112 
113  Closure::Closure (void *func_, void *data_, VisDestroyFunc destroy_func_)
114  : func {reinterpret_cast<void(*)()> (func_)}
115  , data {data_}
116  , destroy_func {destroy_func_}
117  {
118  // nothing
119  }
120 
121  Closure::~Closure ()
122  {
123  if (data && destroy_func) {
124  destroy_func (data);
125  }
126  }
127 
128  // LV::ParamList implementation
129 
130  ParamList::Impl::Impl ()
131  : event_queue {nullptr}
132  {
133  // nothing
134  }
135 
136  ParamList::Impl::~Impl ()
137  {
138  // nothing
139  }
140 
142  : m_impl {new Impl}
143  {
144  // nothing
145  }
146 
148  {
149  // nothing
150  }
151 
152  ParamList::ParamList (std::initializer_list<Param*> params)
153  : m_impl {new Impl}
154  {
155  for (auto param : params) {
156  add (param);
157  }
158  }
159 
161  : m_impl {std::move (list.m_impl)}
162  {
163  // nothing
164  }
165 
167  {
168  m_impl->event_queue = &event_queue;
169  }
170 
172  {
173  return m_impl->event_queue;
174  }
175 
176  void ParamList::add (Param&& param)
177  {
178  add (&param);
179  }
180 
181  void ParamList::add (Param* param)
182  {
183  visual_return_if_fail (param != nullptr);
184 
185  param->parent = this;
186 
187  // libstdc++ 4.6/4.7 still does not have std::map<T>::emplace()
188  m_impl->entries[param->name] = std::unique_ptr<Param> {param};
189  }
190 
191  bool ParamList::remove (std::string const& name)
192  {
193  auto entry = m_impl->entries.find (name);
194  if (entry != m_impl->entries.end ()) {
195  m_impl->entries.erase (entry);
196  return true;
197  }
198 
199  return false;
200  }
201 
202  Param* ParamList::get (std::string const& name) const
203  {
204  auto entry = m_impl->entries.find (name);
205  if (entry != m_impl->entries.end ()) {
206  return entry->second.get ();
207  }
208 
209  return nullptr;
210  }
211 
212  // LV::Param Implementation
213 
214  Param::Param (std::string const& name_,
215  std::string const& description_,
216  VisParamType type_,
217  void* default_value_,
218  Closure* validator_)
219  : parent (nullptr)
220  , name (name_)
221  , description (description_)
222  , validator (validator_)
223  {
224  if (validator) {
225  VisParamValue test_value;
226  visual_param_value_init (&test_value, type_, default_value_);
227 
228  if (!validate_param_value (&test_value, validator.get ())) {
229  throw std::runtime_error {"Default value failed to validate"};
230  }
231  }
232 
233  value = visual_param_value_new (type_, default_value_);
234  default_value = visual_param_value_new (type_, default_value_);
235  }
236 
237  Param::~Param ()
238  {
239  visual_param_value_free (value);
240  visual_param_value_free (default_value);
241  }
242 
243  Closure* Param::add_callback (VisParamChangedFunc func,
244  void* priv,
245  VisDestroyFunc destroy_func)
246  {
247  visual_return_val_if_fail (func != nullptr, nullptr);
248 
249  auto closure = new Closure {reinterpret_cast<void*> (func), priv, destroy_func};
250  changed_handlers.emplace_back (closure);
251 
252  return closure;
253  }
254 
255  bool Param::remove_callback (Closure* to_remove)
256  {
257  visual_return_val_if_fail (to_remove != nullptr, false);
258 
259  auto entry = std::find_if (changed_handlers.begin (),
260  changed_handlers.end (),
261  [&] (std::unique_ptr<Closure> const& handler) {
262  return handler.get () == to_remove;
263  });
264 
265  if (entry != changed_handlers.end ()) {
266  changed_handlers.erase (entry);
267  return true;
268  }
269 
270  return false;
271  }
272 
273  void Param::changed ()
274  {
275  if (!parent)
276  return;
277 
278  auto event_queue = parent->get_event_queue ();
279  if (event_queue) {
280  visual_event_queue_add (event_queue, visual_event_new_param (this));
281  }
282 
283  notify_callbacks ();
284  }
285 
286  void Param::notify_callbacks ()
287  {
288  for (auto const& handler : changed_handlers) {
289  (*(VisParamChangedFunc) (handler->func)) (this, handler->data);
290  }
291  }
292 
293 } // LV namespace
294 
295 
296 // C API
297 
298 // VisClosure implementation
299 
300 VisClosure *visual_closure_new (void *func, void *data, VisDestroyFunc destroy_func)
301 {
302  return new LV::Closure {func, data, destroy_func};
303 }
304 
305 void visual_closure_free (VisClosure *self)
306 {
307  delete self;
308 }
309 
310 // VisParamList implementation
311 
312 VisParamList *visual_param_list_new (void)
313 {
314  return new LV::ParamList;
315 }
316 
317 void visual_param_list_free (VisParamList *self)
318 {
319  delete self;
320 }
321 
322 void visual_param_list_set_event_queue (VisParamList *self, VisEventQueue* event_queue)
323 {
324  visual_return_if_fail (self != nullptr);
325  visual_return_if_fail (event_queue != nullptr);
326 
327  self->set_event_queue (*event_queue);
328 }
329 
330 VisEventQueue* visual_param_list_get_event_queue (VisParamList *self)
331 {
332  visual_return_val_if_fail (self != nullptr, nullptr);
333 
334  return self->get_event_queue ();
335 }
336 
337 void visual_param_list_add (VisParamList *self, VisParam *param)
338 {
339  visual_return_if_fail (self != nullptr);
340  visual_return_if_fail (param != nullptr);
341 
342  self->add (param);
343  delete param;
344 }
345 
346 void visual_param_list_add_array (VisParamList *self, VisParam **params, unsigned int nparams)
347 {
348  visual_return_if_fail (self != nullptr);
349 
350  for (unsigned int i = 0; i < nparams; i++) {
351  self->add (params[i]);
352  }
353 }
354 
355 void visual_param_list_add_many (VisParamList *self, ...)
356 {
357  visual_return_if_fail (self != nullptr);
358 
359  va_list args;
360 
361  va_start (args, self);
362 
363  auto param = va_arg (args, VisParam *);
364 
365  while (param) {
366  self->add (param);
367  param = va_arg (args, VisParam *);
368  }
369 
370  va_end (args);
371 }
372 
373 VisParam **visual_param_list_get_entries (VisParamList *self)
374 {
375  visual_return_val_if_fail (self != nullptr, nullptr);
376 
377  // FIXME: Implement
378 
379  return nullptr;
380 }
381 
382 int visual_param_list_remove (VisParamList *self, const char *name)
383 {
384  visual_return_val_if_fail (self != nullptr, FALSE);
385  visual_return_val_if_fail (name != nullptr, FALSE);
386 
387  return self->remove (name);
388 }
389 
390 VisParam *visual_param_list_get (VisParamList *self, const char *name)
391 {
392  visual_return_val_if_fail (self != nullptr, nullptr);
393  visual_return_val_if_fail (name != nullptr, nullptr);
394 
395  return self->get (name);
396 }
397 
398 // VisParam implementation
399 
400 VisParam *visual_param_new (const char * name,
401  const char * description,
402  VisParamType type,
403  void * default_value,
404  VisClosure * validator)
405 {
406  try {
407  return new LV::Param (name, description, type, default_value, validator);
408  }
409  catch (std::exception& error) {
410  return nullptr;
411  }
412 }
413 
414 void visual_param_free (VisParam *self)
415 {
416  delete self;
417 }
418 
419 int visual_param_has_name (VisParam *self, const char *name)
420 {
421  visual_return_val_if_fail (self != nullptr, FALSE);
422 
423  return self->name == name;
424 }
425 
426 VisParamType visual_param_get_type (VisParam *self)
427 {
428  visual_return_val_if_fail (self != nullptr, VISUAL_PARAM_TYPE_NONE);
429 
430  return self->value->type;
431 }
432 
433 const char *visual_param_get_name (VisParam *self)
434 {
435  visual_return_val_if_fail (self != nullptr, nullptr);
436 
437  return LV::string_to_c (self->name);
438 }
439 
440 const char *visual_param_get_description (VisParam *self)
441 {
442  visual_return_val_if_fail (self != nullptr, nullptr);
443 
444  return LV::string_to_c (self->description);
445 }
446 
447 void visual_param_set_value_bool (VisParam *self, int value)
448 {
449  visual_return_if_fail (self != nullptr);
450 
451  visual_param_value_set_bool (self->value, value);
452 }
453 
454 void visual_param_set_value_integer (VisParam *self, int value)
455 {
456  visual_return_if_fail (self != nullptr);
457 
458  visual_param_value_set_integer (self->value, value);
459 }
460 
461 void visual_param_set_value_float (VisParam *self, float value)
462 {
463  visual_return_if_fail (self != nullptr);
464 
465  visual_param_value_set_float (self->value, value);
466 }
467 
468 void visual_param_set_value_double (VisParam *self, double value)
469 {
470  visual_return_if_fail (self != nullptr);
471 
472  visual_param_value_set_double (self->value, value);
473 }
474 
475 void visual_param_set_value_string (VisParam *self, const char *string)
476 {
477  visual_return_if_fail (self != nullptr);
478 
479  visual_param_value_set_string (self->value, string);
480 }
481 
482 void visual_param_set_value_color (VisParam *self, VisColor *color)
483 {
484  visual_return_if_fail (self != nullptr);
485 
486  visual_param_value_set_color (self->value, color);
487 }
488 
489 void visual_param_set_value_palette (VisParam *self, VisPalette *palette)
490 {
491  visual_return_if_fail (self != nullptr);
492 
493  visual_param_value_set_palette (self->value, palette);
494 }
495 
496 int visual_param_get_value_bool (VisParam *self)
497 {
498  visual_return_val_if_fail (self != nullptr, 0);
499 
500  return visual_param_value_get_bool (self->value);
501 }
502 
503 int visual_param_get_value_integer (VisParam *self)
504 {
505  visual_return_val_if_fail (self != nullptr, 0);
506 
507  return visual_param_value_get_integer (self->value);
508 }
509 
510 float visual_param_get_value_float (VisParam *self)
511 {
512  visual_return_val_if_fail (self != nullptr, 0.0f);
513 
514  return visual_param_value_get_float (self->value);
515 }
516 
517 double visual_param_get_value_double (VisParam *self)
518 {
519  visual_return_val_if_fail (self != nullptr, 0.0);
520 
521  return visual_param_value_get_double (self->value);
522 }
523 
524 const char *visual_param_get_value_string (VisParam *self)
525 {
526  visual_return_val_if_fail (self != nullptr, 0);
527 
528  return visual_param_value_get_string (self->value);
529 }
530 
531 VisColor *visual_param_get_value_color (VisParam *self)
532 {
533  visual_return_val_if_fail (self != nullptr, nullptr);
534 
535  return visual_param_value_get_color (self->value);
536 }
537 
538 VisPalette *visual_param_get_value_palette (VisParam *self)
539 {
540  visual_return_val_if_fail (self != nullptr, nullptr);
541 
542  return visual_param_value_get_palette (self->value);
543 }