LiVES  3.2.0
liblives.cpp
Go to the documentation of this file.
1 // liblives.cpp
2 // LiVES (lives-exe)
3 // (c) G. Finch <salsaman@gmail.com> 2015 - 2017
4 // Released under the GPL 3 or later
5 // see file ../COPYING for licensing details
6 
11 #ifndef DOXYGEN_SKIP
12 
13 #include "liblives.hpp"
14 
15 #include <stdlib.h>
16 #include <pthread.h>
17 #include <unistd.h>
18 #include <iostream>
19 
20 extern "C" {
21  typedef int Boolean;
22 #include <libOSC/libosc.h>
23 #include <libOSC/OSC-client.h>
24 
25 #include "main.h"
26 #include "lbindings.h"
27 #include "effects-weed.h"
28 
29  int real_main(int argc, char *argv[], pthread_t *gtk_thread, ulong id);
30 
31  bool lives_osc_cb_quit(void *context, int arglen, const void *vargs, OSCTimeTag when, void *ra);
32 
33  track_rect *find_block_by_uid(lives_mt *mt, ulong uid);
34 }
35 
36 static volatile bool spinning;
37 static ulong msg_id;
38 static char *private_response;
39 static pthread_mutex_t spin_mutex = PTHREAD_MUTEX_INITIALIZER;
40 static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
41 static pthread_cond_t cond_done = PTHREAD_COND_INITIALIZER;
42 
43 static bool private_cb(lives::_privateInfo *info, void *data) {
44  if (info->id == msg_id) {
45  private_response = strdup(info->response);
46  spinning = false;
47  pthread_cond_signal(&cond_done);
48  return false;
49  }
50  return true;
51 }
52 
53 #endif // doxygen_skip
54 
56 
57 namespace lives {
58 #ifndef DOXYGEN_SKIP
59 typedef struct {
60  ulong id;
61  livesApp *app;
62 } livesAppCtx;
63 
64 static list<livesAppCtx> appMgr;
65 
66 static livesApp *find_instance_for_id(ulong id) {
67  list<livesAppCtx>::iterator it;
68  for (it = appMgr.begin(); it != appMgr.end(); it++) {
69  if ((*it).id == id) return (*it).app;
70  }
71  return NULL;
72 }
73 
74 #endif
75 
76 void livesString::setEncoding(lives_char_encoding_t enc) {
77  m_encoding = enc;
78 }
79 
80 lives_char_encoding_t livesString::encoding() {
81  return m_encoding;
82 }
83 
84 livesString livesString::toEncoding(lives_char_encoding_t enc) {
85  if (enc == LIVES_CHAR_ENCODING_UTF8) {
86  if (m_encoding == LIVES_CHAR_ENCODING_LOCAL8BIT) {
87  livesString str(L2U8(this->c_str()));
88  str.setEncoding(LIVES_CHAR_ENCODING_UTF8);
89  return str;
90  }
91 #ifndef IS_MINGW
92  else if (m_encoding == LIVES_CHAR_ENCODING_FILESYSTEM) {
93  livesString str(F2U8(this->c_str()));
94  str.setEncoding(LIVES_CHAR_ENCODING_UTF8);
95  return str;
96  }
97 #endif
98  } else if (enc == LIVES_CHAR_ENCODING_FILESYSTEM) {
99 #ifndef IS_MINGW
100  if (m_encoding == LIVES_CHAR_ENCODING_UTF8) {
101  livesString str(U82F(this->c_str()));
102  str.setEncoding(LIVES_CHAR_ENCODING_FILESYSTEM);
103  return str;
104  }
105 #else
106  if (m_encoding == LIVES_CHAR_ENCODING_LOCAL8BIT) {
107  livesString str(U82L(this->c_str()));
108  str.setEncoding(LIVES_CHAR_ENCODING_FILESYSTEM);
109  return str;
110  }
111 #endif
112  } else if (enc == LIVES_CHAR_ENCODING_LOCAL8BIT) {
113  if (m_encoding == LIVES_CHAR_ENCODING_UTF8) {
114  livesString str(U82L(this->c_str()));
115  str.setEncoding(LIVES_CHAR_ENCODING_LOCAL8BIT);
116  return str;
117  }
118 #ifndef IS_MINGW
119  if (m_encoding == LIVES_CHAR_ENCODING_FILESYSTEM) {
120  livesString str(F2U8(this->c_str()));
121  str.assign(U82L(str.c_str()));
122  str.setEncoding(LIVES_CHAR_ENCODING_LOCAL8BIT);
123  return str;
124  }
125 #endif
126  }
127  return *this;
128 }
129 
130 
131 void livesApp::init(int argc, char *oargv[]) {
132  char **argv;
133  char progname[] = "lives-exe";
134  if (argc < 0) argc = 0;
135  argc++;
136 
137  argv = (char **)malloc(argc * sizeof(char *));
138  argv[0] = strdup(progname);
139 
140  for (int i = 1; i < argc; i++) {
141  argv[i] = strdup(oargv[i - 1]);
142  }
143 
144  ulong id = lives_random();
145  livesAppCtx *ctx = new livesAppCtx;
146 
147  pthread_t *gtk_thread = new pthread_t;
148 
149  ctx->id = id;
150  ctx->app = this;
151  appMgr.push_back(*ctx);
152 
153  m_set = new set(this);
154  m_player = new player(this);
155  m_effectKeyMap = new effectKeyMap(this);
156  m_multitrack = new multitrack(this);
157 
158  m_deinterlace = false;
159 
160  m_thread = gtk_thread;
161 
162  m_id = id;
163 
164  real_main(argc, argv, m_thread, m_id);
165  free(argv);
166 }
167 
168 
169 livesApp::livesApp() : m_id(0l) {
170  if (appMgr.empty())
171  init(0, NULL);
172 }
173 
174 
175 livesApp::livesApp(int argc, char *argv[]) : m_id(0l) {
176  if (appMgr.empty())
177  init(argc, argv);
178 }
179 
180 
181 livesApp::~livesApp() {
182  if (!isValid()) return;
183  idle_quit(m_thread);
184 }
185 
186 
187 bool livesApp::isValid() const {
188  return this != NULL && m_id != 0l;
189 }
190 
191 
192 bool livesApp::isPlaying() const {
193  return status() == LIVES_STATUS_PLAYING;
194 }
195 
196 
197 bool livesApp::isReady() const {
198  return status() == LIVES_STATUS_READY;
199 }
200 
201 
202 const set &livesApp::getSet() {
203  return *m_set;
204 }
205 
206 
207 const player &livesApp::getPlayer() {
208  return *m_player;
209 }
210 
211 
212 const multitrack &livesApp::getMultitrack() {
213  return *m_multitrack;
214 }
215 
216 
217 ulong livesApp::appendClosure(lives_callback_t cb_type, callback_f func, void *data) const {
218  closure *cl = new closure;
219  cl->id = lives_random();
220  cl->object = (livesApp *)this;
221  cl->cb_type = cb_type;
222  cl->func = (callback_f)func;
223  cl->data = data;
224  while (pthread_mutex_trylock(&spin_mutex)) {
225  // lock mutex so that new callbacks cannot be added yet
226  lives_usleep(::prefs->sleep_time);
227  }
228  ((livesApp *)this)->m_closures.push_back(cl);
229  pthread_mutex_unlock(&spin_mutex);
230  return cl->id;
231 }
232 
233 #ifndef DOXYGEN_SKIP
234 
235 void livesApp::setClosures(closureList cl) {
236  m_closures = cl;
237 }
238 
239 #endif
240 
241 ulong livesApp::addCallback(lives_callback_t cb_type, modeChanged_callback_f func, void *data) const {
242  if (cb_type != LIVES_CALLBACK_MODE_CHANGED) return 0l;
243  return appendClosure(cb_type, (callback_f)func, data);
244 }
245 
246 ulong livesApp::addCallback(lives_callback_t cb_type, private_callback_f func, void *data) const {
247  if (cb_type != LIVES_CALLBACK_PRIVATE) return 0l;
248  return appendClosure(cb_type, (callback_f)func, data);
249 }
250 
251 ulong livesApp::addCallback(lives_callback_t cb_type, objectDestroyed_callback_f func, void *data) const {
252  if (cb_type != LIVES_CALLBACK_OBJECT_DESTROYED) return 0l;
253  return appendClosure(cb_type, (callback_f)func, data);
254 }
255 
256 ulong livesApp::addCallback(lives_callback_t cb_type, appQuit_callback_f func, void *data) const {
257  if (cb_type != LIVES_CALLBACK_APP_QUIT) return 0l;
258  return appendClosure(cb_type, (callback_f)func, data);
259 }
260 
261 bool livesApp::removeCallback(ulong id) const {
262  while (pthread_mutex_trylock(&spin_mutex)) {
263  // lock mutex so that new callbacks cannot be added yet
264  lives_usleep(::prefs->sleep_time);
265  }
266  closureListIterator it = ((livesApp *)this)->m_closures.begin();
267  while (it != ((livesApp *)this)->m_closures.end()) {
268  if ((*it)->id == id) {
269  delete *it;
270  ((livesApp *)this)->m_closures.erase(it);
271  pthread_mutex_unlock(&spin_mutex);
272  return true;
273  }
274  ++it;
275  }
276  pthread_mutex_unlock(&spin_mutex);
277  return false;
278 }
279 
280 
281 lives_dialog_response_t livesApp::showInfo(livesString text, bool blocking) {
283  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return ret;
284  // if blocking wait for response
285  if (blocking) {
286  spinning = true;
287  msg_id = lives_random();
288  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
289  pthread_mutex_lock(&cond_mutex);
290  if (!idle_show_info(text.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(), blocking, msg_id)) {
291  pthread_mutex_unlock(&cond_mutex);
292  spinning = false;
293  removeCallback(cbid);
294  } else {
295  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
296  pthread_mutex_unlock(&cond_mutex);
297  if (isValid()) {
298  ret = (lives_dialog_response_t)atoi(private_response);
299  lives_free(private_response);
300  }
301  }
302  return ret;
303  }
304  if (idle_show_info(text.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(), blocking, 0))
306  return ret;
307 }
308 
309 
310 livesString livesApp::chooseFileWithPreview(livesString dirname, lives_filechooser_t preview_type, livesString title) {
311  livesString emptystr;
312  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return emptystr;
313  if (preview_type != LIVES_FILE_CHOOSER_VIDEO_AUDIO && preview_type != LIVES_FILE_CHOOSER_AUDIO_ONLY) return emptystr;
314  spinning = true;
315  msg_id = lives_random();
316  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
317  pthread_mutex_lock(&cond_mutex);
318  if (!idle_choose_file_with_preview(dirname.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str(),
319  title.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(),
320  preview_type, msg_id)) {
321  pthread_mutex_unlock(&cond_mutex);
322  spinning = false;
323  removeCallback(cbid);
324  } else {
325  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
326  pthread_mutex_unlock(&cond_mutex);
327  if (isValid()) {
328  // last 2 chars are " " and %d (deinterlace choice)
329  livesString str(private_response, strlen(private_response) - 2, LIVES_CHAR_ENCODING_FILESYSTEM);
330  m_deinterlace = (bool)atoi(private_response + strlen(private_response) - 2);
331  lives_free(private_response);
332  return str;
333  }
334  }
335  return emptystr;
336 }
337 
338 
339 livesString livesApp::chooseSet() {
340  livesString emptystr;
341  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return emptystr;
342  spinning = true;
343  msg_id = lives_random();
344  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
345  pthread_mutex_lock(&cond_mutex);
346  if (!idle_choose_set(msg_id)) {
347  pthread_mutex_unlock(&cond_mutex);
348  spinning = false;
349  removeCallback(cbid);
350  } else {
351  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
352  pthread_mutex_unlock(&cond_mutex);
353  if (isValid()) {
354  livesString str(private_response, LIVES_CHAR_ENCODING_FILESYSTEM);
355  lives_free(private_response);
356  return str;
357  }
358  }
359  return emptystr;
360 }
361 
362 
363 livesStringList livesApp::availableSets() {
364  livesStringList list;
365  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return list;
366  LiVESList *setlist = get_set_list(::prefs->workdir, true), *slist = setlist;
367  while (slist != NULL) {
368  list.push_back(livesString((const char *)slist->data, LIVES_CHAR_ENCODING_UTF8));
369  lives_free(slist->data);
370  slist = slist->next;
371  }
372  lives_list_free(setlist);
373  return list;
374 }
375 
376 
377 clip livesApp::openFile(livesString fname, bool with_audio, double stime, int frames, bool deinterlace) {
378  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return clip();
379  if (fname.empty()) return clip();
380  spinning = true;
381  msg_id = lives_random();
382  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
383  ulong cid = 0l;
384 
385  pthread_mutex_lock(&cond_mutex);
386  if (!idle_open_file(fname.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str(), stime, frames, msg_id)) {
387  pthread_mutex_unlock(&cond_mutex);
388  spinning = false;
389  removeCallback(cbid);
390  } else {
391  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
392  pthread_mutex_unlock(&cond_mutex);
393  if (isValid()) {
394  cid = strtoul(private_response, NULL, 10);
395  lives_free(private_response);
396  }
397  }
398  return clip(cid, this);
399 }
400 
401 
402 bool livesApp::reloadSet(livesString setname) {
403  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return false;
404  spinning = true;
405  msg_id = lives_random();
406  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
407 
408  pthread_mutex_lock(&cond_mutex);
409  if (!idle_reload_set(setname.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str(), msg_id)) {
410  pthread_mutex_unlock(&cond_mutex);
411  spinning = false;
412  removeCallback(cbid);
413  return false;
414  }
415  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
416  pthread_mutex_unlock(&cond_mutex);
417  if (isValid()) {
418  bool ret = (bool)atoi(private_response);
419  lives_free(private_response);
420  return ret;
421  }
422  return false;
423 }
424 
425 
426 bool livesApp::deinterlaceOption() {
427  return m_deinterlace;
428 }
429 
430 
431 lives_interface_mode_t livesApp::mode() {
432  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return LIVES_INTERFACE_MODE_INVALID;
433  if (m_multitrack->isActive()) return LIVES_INTERFACE_MODE_MULTITRACK;
435 }
436 
437 
438 lives_interface_mode_t livesApp::setMode(lives_interface_mode_t newmode) {
439  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return LIVES_INTERFACE_MODE_INVALID;
440  spinning = true;
441  msg_id = lives_random();
442  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
443 
444  pthread_mutex_lock(&cond_mutex);
445  if (!idle_set_if_mode(newmode, msg_id)) {
446  pthread_mutex_unlock(&cond_mutex);
447  spinning = false;
448  removeCallback(cbid);
449  return mode();
450  }
451  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
452  pthread_mutex_unlock(&cond_mutex);
453  if (isValid()) {
454  lives_free(private_response);
455  }
456  return mode();
457 }
458 
459 
460 lives_status_t livesApp::status() const {
461  if (!isValid()) return LIVES_STATUS_INVALID;
462  if (mainw->go_away) return LIVES_STATUS_NOTREADY;
464  if ((mainw->preview || mainw->event_list != NULL) && mainw->multitrack == NULL) return LIVES_STATUS_PREVIEW;
465  if (mainw->playing_file > -1 || mainw->preview) return LIVES_STATUS_PLAYING;
466  return LIVES_STATUS_READY;
467 }
468 
469 
470 bool livesApp::cancel() {
471  if (!isValid()) return false;
472  if (status() != LIVES_STATUS_PROCESSING) return false;
473  bool ret = false;
474  spinning = true;
475  msg_id = lives_random();
476  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
477 
478  pthread_mutex_lock(&cond_mutex);
479  if (!idle_cancel_proc(msg_id)) {
480  pthread_mutex_unlock(&cond_mutex);
481  spinning = false;
482  removeCallback(cbid);
483  return false;
484  }
485  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
486  pthread_mutex_unlock(&cond_mutex);
487  if (isValid()) {
488  ret = (bool)atoi(private_response);
489  lives_free(private_response);
490  }
491  return ret;
492 }
493 
494 #ifndef DOXYGEN_SKIP
495 
496 closureList &livesApp::closures() {
497  return m_closures;
498 }
499 
500 #endif
501 
502 void livesApp::invalidate() {
503  m_id = 0l;
504 }
505 
506 
507 bool livesApp::interactive() {
508  return mainw->interactive;
509 }
510 
511 
512 bool livesApp::setInteractive(bool setting) {
513  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return mainw->interactive;
514  spinning = true;
515  msg_id = lives_random();
516  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
517  pthread_mutex_lock(&cond_mutex);
518  if (!idle_set_interactive(setting, msg_id)) {
519  pthread_mutex_unlock(&cond_mutex);
520  spinning = false;
521  removeCallback(cbid);
522  }
523  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
524  pthread_mutex_unlock(&cond_mutex);
525  if (isValid()) {
526  lives_free(private_response);
527  }
528  return setting;
529 }
530 
531 
532 const effectKeyMap &livesApp::getEffectKeyMap() {
533  return *m_effectKeyMap;
534 }
535 
536 
537 #ifndef DOXYGEN_SKIP
538 bool livesApp::setPref(const char *prefidx, bool val) const {
539  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return false;
540  spinning = true;
541  msg_id = lives_random();
542  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
543  pthread_mutex_lock(&cond_mutex);
544  if (!idle_set_pref_bool(prefidx, val, msg_id)) {
545  pthread_mutex_unlock(&cond_mutex);
546  spinning = false;
547  removeCallback(cbid);
548  return false;
549  }
550  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
551  pthread_mutex_unlock(&cond_mutex);
552  if (isValid()) {
553  lives_free(private_response);
554  }
555  return true;
556 }
557 
558 bool livesApp::setPref(const char *prefidx, int val) const {
559  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return false;
560  spinning = true;
561  msg_id = lives_random();
562  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
563  pthread_mutex_lock(&cond_mutex);
564  if (!idle_set_pref_int(prefidx, val, msg_id)) {
565  pthread_mutex_unlock(&cond_mutex);
566  spinning = false;
567  removeCallback(cbid);
568  return false;
569  }
570  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
571  pthread_mutex_unlock(&cond_mutex);
572  if (isValid()) {
573  lives_free(private_response);
574  }
575  return true;
576 }
577 
578 bool livesApp::setPref(const char *prefidx, int bitfield, bool val) const {
579  if (!isValid() || status() == LIVES_STATUS_NOTREADY) return false;
580  spinning = true;
581  msg_id = lives_random();
582  ulong cbid = addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
583  pthread_mutex_lock(&cond_mutex);
584  if (!idle_set_pref_bitmapped(prefidx, bitfield, val, msg_id)) {
585  pthread_mutex_unlock(&cond_mutex);
586  spinning = false;
587  removeCallback(cbid);
588  return false;
589  }
590  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
591  pthread_mutex_unlock(&cond_mutex);
592  if (isValid()) {
593  lives_free(private_response);
594  }
595  return true;
596 }
597 #endif
598 
600 
601 player::player(livesApp *lives) {
602  // make shared ptr
603  m_lives = lives;
604 }
605 
606 
607 bool player::isValid() const {
608  return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY;
609 }
610 
611 
612 bool player::isPlaying() const {
613  return isValid() && m_lives->isPlaying();
614 }
615 
616 
617 bool player::isRecording() const {
618  return isValid() && mainw->record;
619 }
620 
621 
622 bool player::play() const {
623  if (!isValid() || !m_lives->isReady()) return false;
624  return start_player();
625 }
626 
627 
628 bool player::stop() const {
629  if (!isPlaying()) return false;
630  spinning = true;
631  msg_id = lives_random();
632  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
633  pthread_mutex_lock(&cond_mutex);
634  if (!idle_stop_playback(msg_id)) {
635  pthread_mutex_unlock(&cond_mutex);
636  spinning = false;
637  m_lives->removeCallback(cbid);
638  return false;
639  }
640  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
641  pthread_mutex_unlock(&cond_mutex);
642  if (isValid()) {
643  bool ret = atoi(private_response);
644  lives_free(private_response);
645  return ret;
646  }
647  return false;
648 }
649 
650 
651 void player::setSepWin(bool setting) const {
652  if (!isValid()) return;
653  spinning = true;
654  msg_id = lives_random();
655  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
656  pthread_mutex_lock(&cond_mutex);
657  if (!idle_set_sepwin(setting, msg_id)) {
658  pthread_mutex_unlock(&cond_mutex);
659  spinning = false;
660  m_lives->removeCallback(cbid);
661  return;
662  }
663  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
664  pthread_mutex_unlock(&cond_mutex);
665  if (isValid()) {
666  lives_free(private_response);
667  }
668  return;
669 }
670 
671 
672 void player::setFullScreen(bool setting) const {
673  if (!isValid()) return;
674  spinning = true;
675  msg_id = lives_random();
676  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
677  pthread_mutex_lock(&cond_mutex);
678  if (!idle_set_fullscreen(setting, msg_id)) {
679  pthread_mutex_unlock(&cond_mutex);
680  spinning = false;
681  m_lives->removeCallback(cbid);
682  return;
683  }
684  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
685  pthread_mutex_unlock(&cond_mutex);
686  if (isValid()) {
687  lives_free(private_response);
688  }
689  return;
690 }
691 
692 
693 bool player::sepWin() const {
694  if (!isValid()) return false;
695  return mainw->sep_win;
696 }
697 
698 
699 bool player::fullScreen() const {
700  if (!isValid()) return false;
701  return mainw->fs;
702 }
703 
704 
705 bool player::setForegroundClip(clip c) const {
706  if (!isPlaying()) return false;
707  return c.switchTo();
708 }
709 
710 
711 bool player::setBackgroundClip(clip c) const {
712  if (!isPlaying()) return false;
713  return c.setIsBackground();
714 }
715 
716 
717 clip player::foregroundClip() const {
718  if (!isPlaying()) return clip();
719  if (m_lives->m_multitrack->isActive()) return clip();
720  if (mainw->files[mainw->playing_file] != NULL) return clip(mainw->files[mainw->playing_file]->unique_id, m_lives);
721  return clip();
722 }
723 
724 clip player::backgroundClip() const {
725  if (!isPlaying()) return clip();
726  if (m_lives->m_multitrack->isActive()) return clip();
727  if (mainw->files[mainw->blend_file] != NULL) return clip(mainw->files[mainw->blend_file]->unique_id, m_lives);
728  return clip();
729 }
730 
731 void player::setFS(bool setting) const {
732  if (!isValid()) return;
733  spinning = true;
734  msg_id = lives_random();
735  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
736  pthread_mutex_lock(&cond_mutex);
737  if (!idle_set_fullscreen_sepwin(setting, msg_id)) {
738  pthread_mutex_unlock(&cond_mutex);
739  spinning = false;
740  m_lives->removeCallback(cbid);
741  return;
742  }
743  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
744  pthread_mutex_unlock(&cond_mutex);
745  if (isValid()) {
746  lives_free(private_response);
747  }
748  return;
749 }
750 
751 
752 double player::videoPlaybackTime(bool background) const {
753  if (!isValid()) return 0.;
754 
755  if (m_lives->status() == LIVES_STATUS_NOTREADY || m_lives->status() == LIVES_STATUS_PROCESSING) return 0.;
756 
757  if (!m_lives->m_multitrack->isActive()) {
758  if (mainw->current_file == -1) return 0.;
759  if (mainw->playing_file > -1) {
760  if (!background) return (cfile->frameno - 1.) / cfile->fps;
761  else if (mainw->blend_file != -1 && mainw->blend_file != mainw->current_file && mainw->files[mainw->blend_file] != NULL) {
762  return mainw->files[mainw->blend_file]->frameno;
763  } else return 0.;
764  } else return cfile->pointer_time;
765  } else {
766  return lives_ruler_get_value(LIVES_RULER(mainw->multitrack->timeline));
767  }
768 }
769 
770 
771 double player::audioPlaybackTime() const {
772  if (!isValid()) return 0.;
773 
774  if (m_lives->status() != LIVES_STATUS_NOTREADY || m_lives->status() == LIVES_STATUS_PROCESSING) return 0.;
775 
776  if (!m_lives->m_multitrack->isActive()) {
777  if (mainw->current_file == -1) return 0.;
778  if (mainw->playing_file > -1) return (mainw->aframeno - 1.) / cfile->fps;
779  else return cfile->pointer_time;
780  } else {
781  return lives_ruler_get_value(LIVES_RULER(mainw->multitrack->timeline));
782  }
783 }
784 
785 
786 double player::setAudioPlaybackTime(double time) const {
787  if (!isValid()) return 0.;
788  if (!m_lives->isPlaying()) return 0.;
789  if (!is_realtime_aplayer(::prefs->audio_player)) return 0.;
790  if (mainw->record && ::prefs->audio_src == AUDIO_SRC_EXT) return 0.;
791  if (mainw->multitrack != NULL) return 0.;
792  if (time < 0. || time > cfile->laudio_time) return 0.;
793 
794  spinning = true;
795  msg_id = lives_random();
796  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
797  pthread_mutex_lock(&cond_mutex);
798  if (!idle_set_current_audio_time(time, msg_id)) {
799  pthread_mutex_unlock(&cond_mutex);
800  spinning = false;
801  m_lives->removeCallback(cbid);
802  } else {
803  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
804  pthread_mutex_unlock(&cond_mutex);
805  if (isValid()) {
806  lives_free(private_response);
807  }
808  }
809  return audioPlaybackTime();
810 }
811 
812 
813 double player::setPlaybackStartTime(double time) const {
814  if (!isValid()) return 0.;
815  if (!m_lives->isReady()) return 0.;
816 
817  spinning = true;
818  msg_id = lives_random();
819  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
820  pthread_mutex_lock(&cond_mutex);
821  if (!idle_set_current_time(time, msg_id)) {
822  pthread_mutex_unlock(&cond_mutex);
823  spinning = false;
824  m_lives->removeCallback(cbid);
825  } else {
826  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
827  pthread_mutex_unlock(&cond_mutex);
828  if (isValid()) {
829  lives_free(private_response);
830  }
831  }
832  return videoPlaybackTime();
833 }
834 
835 
836 int player::setVideoPlaybackFrame(int frame, bool bg) const {
837  if (!isValid()) return 0;
838 
839  spinning = true;
840  msg_id = lives_random();
841  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
842  pthread_mutex_lock(&cond_mutex);
843  if (!idle_set_current_frame(frame, bg, msg_id)) {
844  pthread_mutex_unlock(&cond_mutex);
845  spinning = false;
846  m_lives->removeCallback(cbid);
847  } else {
848  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
849  pthread_mutex_unlock(&cond_mutex);
850  if (isValid()) {
851  lives_free(private_response);
852  }
853  }
854  return videoPlaybackTime();
855 }
856 
857 
858 double player::elapsedTime() const {
859  if (!isPlaying()) return 0.;
861 }
862 
863 
864 double player::currentFPS() const {
865  if (!isValid()) return 0.;
866  if (mainw->current_file == -1 || cfile == NULL) return 0.;
867  if (m_lives->status() != LIVES_STATUS_PLAYING && m_lives->status() != LIVES_STATUS_READY) return 0.;
868  return cfile->pb_fps;
869 }
870 
871 
872 double player::setCurrentFPS(double fps) const {
873  if (!isPlaying()) return 0.;
874 
875  spinning = true;
876  msg_id = lives_random();
877  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
878  pthread_mutex_lock(&cond_mutex);
879  if (!idle_set_current_fps(fps, msg_id)) {
880  pthread_mutex_unlock(&cond_mutex);
881  spinning = false;
882  m_lives->removeCallback(cbid);
883  } else {
884  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
885  pthread_mutex_unlock(&cond_mutex);
886  if (isValid()) {
887  lives_free(private_response);
888  }
889  }
890  return currentFPS();
891 }
892 
893 
894 int player::currentAudioRate() const {
895  if (!isValid()) return 0.;
896  if (m_lives->status() != LIVES_STATUS_PLAYING && m_lives->status() != LIVES_STATUS_READY) return 0.;
897  if (mainw->current_file == -1 || cfile == NULL) return 0.;
898  return cfile->arps;
899 }
900 
901 
902 lives_loop_mode_t player::setLoopMode(lives_loop_mode_t mode) const {
903  if (!isValid()) return loopMode();
904  spinning = true;
905  msg_id = lives_random();
906  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
907  pthread_mutex_lock(&cond_mutex);
908  if (!idle_set_loop_mode(mode, msg_id)) {
909  pthread_mutex_unlock(&cond_mutex);
910  spinning = false;
911  m_lives->removeCallback(cbid);
912  } else {
913  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
914  pthread_mutex_unlock(&cond_mutex);
915  if (isValid()) {
916  lives_free(private_response);
917  }
918  }
919  return loopMode();
920 }
921 
922 
923 lives_loop_mode_t player::loopMode() const {
924  unsigned int lmode = LIVES_LOOP_MODE_NONE;
925  if (!isValid()) return (lives_loop_mode_t)lmode;
926 
927  if (mainw->loop) lmode |= LIVES_LOOP_MODE_FIT_AUDIO;
929 
930  return (lives_loop_mode_t)lmode;
931 }
932 
933 
934 bool player::setPingPong(bool setting) const {
935  if (!isValid()) return pingPong();
936  spinning = true;
937  msg_id = lives_random();
938  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
939  pthread_mutex_lock(&cond_mutex);
940  if (!idle_set_ping_pong(setting, msg_id)) {
941  pthread_mutex_unlock(&cond_mutex);
942  spinning = false;
943  m_lives->removeCallback(cbid);
944  } else {
945  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
946  pthread_mutex_unlock(&cond_mutex);
947  if (isValid()) {
948  lives_free(private_response);
949  }
950  }
951  return pingPong();
952 }
953 
954 
955 bool player::pingPong() const {
956  if (!isValid()) return false;
957  return mainw->ping_pong;
958 }
959 
960 
961 bool player::resyncFPS() const {
962  if (!isPlaying()) return false;
963  spinning = true;
964  msg_id = lives_random();
965  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
966  pthread_mutex_lock(&cond_mutex);
967  if (!idle_resync_fps(msg_id)) {
968  pthread_mutex_unlock(&cond_mutex);
969  spinning = false;
970  m_lives->removeCallback(cbid);
971  } else {
972  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
973  pthread_mutex_unlock(&cond_mutex);
974  if (isValid()) {
975  lives_free(private_response);
976  }
977  }
978  return true;
979 }
980 
981 
983 
984 set::set(livesApp *lives) {
985  m_lives = lives;
986 }
987 
988 
989 bool set::isValid() const {
990  return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY;
991 }
992 
993 
994 livesString set::name() const {
995  if (!isValid()) return livesString();
996  return livesString(mainw->set_name, LIVES_CHAR_ENCODING_UTF8);
997 }
998 
999 
1000 bool set::setName(livesString name) const {
1001  if (!isValid()) return false;
1002  if (strlen(mainw->set_name) > 0) return false;
1003  if (numClips() == 0) return false;
1004 
1005  if (!name.empty()) {
1006  const char *new_set_name = name.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str();
1007  if (is_legal_set_name(new_set_name, TRUE)) {
1008  lives_snprintf(mainw->set_name, 128, "%s", new_set_name);
1009  return true;
1010  }
1011  return false;
1012  }
1013 
1014  spinning = true;
1015  msg_id = lives_random();
1016  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1017 
1018  pthread_mutex_lock(&cond_mutex);
1019  if (!idle_set_set_name(msg_id)) {
1020  pthread_mutex_unlock(&cond_mutex);
1021  spinning = false;
1022  m_lives->removeCallback(cbid);
1023  return false;
1024  }
1025  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1026  pthread_mutex_unlock(&cond_mutex);
1027  if (isValid()) {
1028  bool ret = (bool)atoi(private_response);
1029  lives_free(private_response);
1030  return ret;
1031  }
1032  return false;
1033 }
1034 
1035 
1036 unsigned int set::numClips() const {
1037  if (!isValid()) return 0;
1038  (const_cast<set *>(this))->update_clip_list();
1039  return m_clips.size();
1040 }
1041 
1042 
1043 clip set::nthClip(unsigned int n) const {
1044  if (!isValid()) return clip();
1045  (const_cast<set *>(this))->update_clip_list();
1046  if (n >= m_clips.size()) return clip();
1047  return clip(m_clips[n], m_lives);
1048 }
1049 
1050 
1051 int set::indexOf(clip c) const {
1052  if (!isValid()) return -1;
1053  if (!c.isValid()) return -1;
1054  if (m_clips.empty()) return -1;
1055  (const_cast<set *>(this))->update_clip_list();
1056  int i;
1057  for (i = 0; i < (int)m_clips.size(); i++) {
1058  if (m_clips[i] == c.m_uid) return i;
1059  }
1060  return -1;
1061 }
1062 
1063 
1064 bool set::save(livesString name, bool force_append) const {
1065  if (!isValid()) return FALSE;
1066  const char *cname = name.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str();
1067 
1068  spinning = true;
1069  msg_id = lives_random();
1070 
1071  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1072 
1073  bool ret = false;
1074 
1075  pthread_mutex_lock(&cond_mutex);
1076  if (!idle_save_set(cname, force_append, msg_id)) {
1077  pthread_mutex_unlock(&cond_mutex);
1078  spinning = false;
1079  m_lives->removeCallback(cbid);
1080  } else {
1081  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1082  pthread_mutex_unlock(&cond_mutex);
1083  if (isValid()) {
1084  ret = (bool)(atoi(private_response));
1085  lives_free(private_response);
1086  }
1087  }
1088  return ret;
1089 }
1090 
1091 
1092 bool set::save() const {
1093  return save(name());
1094 }
1095 
1096 
1097 void set::update_clip_list() {
1098  clipListIterator it = m_clips.begin();
1099  while (it != m_clips.end()) {
1100  it = m_clips.erase(it);
1101  }
1102  if (isValid()) {
1103  ulong *ids = get_unique_ids();
1104 
1105  for (int i = 0; ids[i] != 0l; i++) {
1106  m_clips.push_back(ids[i]);
1107  }
1108  lives_free(ids);
1109  }
1110 }
1111 
1112 
1114 
1115 clip::clip() : m_uid(0l), m_lives(NULL) {};
1116 
1117 clip::clip(ulong uid, livesApp *lives) {
1118  m_uid = uid;
1119  m_lives = lives;
1120 }
1121 
1122 bool clip::isValid() const {
1123  return (m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY && cnum_for_uid(m_uid) != -1);
1124 }
1125 
1126 int clip::frames() {
1127  if (isValid()) {
1128  int cnum = cnum_for_uid(m_uid);
1129  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->frames;
1130  }
1131  return 0;
1132 }
1133 
1134 int clip::width() {
1135  if (isValid()) {
1136  int cnum = cnum_for_uid(m_uid);
1137  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->hsize;
1138  }
1139  return 0;
1140 }
1141 
1142 int clip::height() {
1143  if (isValid()) {
1144  int cnum = cnum_for_uid(m_uid);
1145  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->vsize;
1146  }
1147  return 0;
1148 }
1149 
1150 double clip::FPS() {
1151  if (isValid()) {
1152  int cnum = cnum_for_uid(m_uid);
1153  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->fps;
1154  }
1155  return 0.;
1156 }
1157 
1158 
1159 double clip::playbackFPS() {
1160  if (isValid()) {
1161  if (!m_lives->m_multitrack->isActive()) {
1162  int cnum = cnum_for_uid(m_uid);
1163  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->pb_fps;
1164  } else return m_lives->m_multitrack->FPS();
1165  }
1166  return 0.;
1167 }
1168 
1169 
1170 int clip::audioRate() {
1171  if (isValid()) {
1172  int cnum = cnum_for_uid(m_uid);
1173  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->arate;
1174  }
1175  return 0;
1176 }
1177 
1178 
1179 int clip::playbackAudioRate() {
1180  int arps = -1;
1181  if (isValid()) {
1182  if (!m_lives->m_multitrack->isActive()) {
1183  int cnum = cnum_for_uid(m_uid);
1184  if (cnum > -1 && mainw->files[cnum] != NULL) {
1185  arps = mainw->files[cnum]->arps;
1186  arps *= mainw->files[cnum]->pb_fps / mainw->files[cnum]->fps;
1187  }
1188  } else arps = mainw->files[mainw->multitrack->render_file]->arate;
1189  }
1190  return arps;
1191 }
1192 
1193 
1194 double clip::audioLength() {
1195  if (isValid()) {
1196  int cnum = cnum_for_uid(m_uid);
1197  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->laudio_time;
1198  }
1199  return 0.;
1200 }
1201 
1202 
1203 int clip::audioChannels() {
1204  if (isValid()) {
1205  int cnum = cnum_for_uid(m_uid);
1206  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->achans;
1207  }
1208  return 0;
1209 }
1210 
1211 
1212 int clip::audioSampleSize() {
1213  if (isValid()) {
1214  int cnum = cnum_for_uid(m_uid);
1215  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->asampsize;
1216  }
1217  return 0;
1218 }
1219 
1220 
1221 bool clip::audioSigned() {
1222  if (isValid()) {
1223  int cnum = cnum_for_uid(m_uid);
1224  if (cnum > -1 && mainw->files[cnum] != NULL) return !(mainw->files[cnum]->signed_endian & AFORM_UNSIGNED);
1225  }
1226  return true;
1227 }
1228 
1229 
1230 lives_endian_t clip::audioEndian() {
1231  if (isValid()) {
1232  int cnum = cnum_for_uid(m_uid);
1233  if (cnum > -1 && mainw->files[cnum] != NULL) {
1235  }
1236  }
1237  return LIVES_LITTLEENDIAN;
1238 }
1239 
1240 
1241 livesString clip::name() {
1242  if (isValid()) {
1243  int cnum = cnum_for_uid(m_uid);
1244  if (cnum > -1 &&
1245  mainw->files[cnum] != NULL) return livesString(get_menu_name(mainw->files[cnum], FALSE), LIVES_CHAR_ENCODING_UTF8);
1246  }
1247  return livesString();
1248 }
1249 
1250 
1251 int clip::selectionStart() {
1252  if (isValid()) {
1253  int cnum = cnum_for_uid(m_uid);
1254  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->start;
1255  }
1256  return 0;
1257 }
1258 
1259 
1260 int clip::selectionEnd() {
1261  if (isValid()) {
1262  int cnum = cnum_for_uid(m_uid);
1263  if (cnum > -1 && mainw->files[cnum] != NULL) return mainw->files[cnum]->end;
1264  }
1265  return 0;
1266 }
1267 
1268 
1269 bool clip::selectAll() {
1270  if (!isValid() || m_lives->status() == LIVES_STATUS_NOTREADY) return false;
1271  spinning = true;
1272  msg_id = lives_random();
1273  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1274 
1275  int cnum = cnum_for_uid(m_uid);
1276  pthread_mutex_lock(&cond_mutex);
1277  if (!idle_select_all(cnum, msg_id)) {
1278  pthread_mutex_unlock(&cond_mutex);
1279  spinning = false;
1280  m_lives->removeCallback(cbid);
1281  return false;
1282  }
1283  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1284  pthread_mutex_unlock(&cond_mutex);
1285  if (isValid()) {
1286  bool ret = (bool)atoi(private_response);
1287  lives_free(private_response);
1288  return ret;
1289  }
1290  return false;
1291 }
1292 
1293 
1294 bool clip::setSelectionStart(unsigned int frame) {
1295  if (!isValid()) return false;
1296  spinning = true;
1297  msg_id = lives_random();
1298  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1299 
1300  int cnum = cnum_for_uid(m_uid);
1301  pthread_mutex_lock(&cond_mutex);
1302  if (!idle_select_start(cnum, frame, msg_id)) {
1303  pthread_mutex_unlock(&cond_mutex);
1304  spinning = false;
1305  m_lives->removeCallback(cbid);
1306  return false;
1307  }
1308  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1309  pthread_mutex_unlock(&cond_mutex);
1310  if (isValid()) {
1311  bool ret = (bool)atoi(private_response);
1312  lives_free(private_response);
1313  return ret;
1314  }
1315  return false;
1316 }
1317 
1318 
1319 bool clip::setSelectionEnd(unsigned int frame) {
1320  if (!isValid()) return false;
1321  spinning = true;
1322  msg_id = lives_random();
1323  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1324 
1325  int cnum = cnum_for_uid(m_uid);
1326  pthread_mutex_lock(&cond_mutex);
1327  if (!idle_select_end(cnum, frame, msg_id)) {
1328  pthread_mutex_unlock(&cond_mutex);
1329  spinning = false;
1330  m_lives->removeCallback(cbid);
1331  return false;
1332  }
1333  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1334  pthread_mutex_unlock(&cond_mutex);
1335  if (isValid()) {
1336  bool ret = (bool)atoi(private_response);
1337  lives_free(private_response);
1338  return ret;
1339  }
1340  return false;
1341 }
1342 
1343 
1344 bool clip::switchTo() {
1345  if (!isValid()) return false;
1346  if (m_lives->m_multitrack->isActive()) return false;
1347  spinning = true;
1348  msg_id = lives_random();
1349  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1350 
1351  int cnum = cnum_for_uid(m_uid);
1352  pthread_mutex_lock(&cond_mutex);
1353  if (!idle_switch_clip(1, cnum, msg_id)) {
1354  pthread_mutex_unlock(&cond_mutex);
1355  spinning = false;
1356  m_lives->removeCallback(cbid);
1357  return false;
1358  }
1359  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1360  pthread_mutex_unlock(&cond_mutex);
1361  if (isValid()) {
1362  bool ret = (bool)atoi(private_response);
1363  lives_free(private_response);
1364  return ret;
1365  }
1366  return false;
1367 }
1368 
1369 
1370 bool clip::setIsBackground() {
1371  if (!isValid()) return false;
1372  if (m_lives->m_multitrack->isActive()) return false;
1373  spinning = true;
1374  msg_id = lives_random();
1375  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1376 
1377  int cnum = cnum_for_uid(m_uid);
1378  pthread_mutex_lock(&cond_mutex);
1379  if (!idle_switch_clip(2, cnum, msg_id)) {
1380  pthread_mutex_unlock(&cond_mutex);
1381  spinning = false;
1382  m_lives->removeCallback(cbid);
1383  return false;
1384  }
1385  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1386  pthread_mutex_unlock(&cond_mutex);
1387  if (isValid()) {
1388  bool ret = (bool)atoi(private_response);
1389  lives_free(private_response);
1390  return ret;
1391  }
1392  return false;
1393 }
1394 
1396 
1398 effectKeyMap::effectKeyMap(livesApp *lives) {
1399  m_lives = lives;
1400 }
1401 
1402 
1403 bool effectKeyMap::isValid() const {
1404  return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY;
1405 }
1406 
1407 
1408 effectKey effectKeyMap::at(int i) const {
1409  return (*this)[i];
1410 }
1411 
1412 
1413 size_t effectKeyMap::size() const {
1414  if (!isValid()) return 0;
1415  return (size_t) prefs::rteKeysVirtual(*m_lives);
1416 }
1417 
1418 
1419 bool effectKeyMap::clear() const {
1420  if (!isValid()) return false;
1421  spinning = true;
1422  msg_id = lives_random();
1423  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1424 
1425  pthread_mutex_lock(&cond_mutex);
1426  if (!idle_unmap_effects(msg_id)) {
1427  pthread_mutex_unlock(&cond_mutex);
1428  spinning = false;
1429  m_lives->removeCallback(cbid);
1430  return false;
1431  }
1432  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1433  pthread_mutex_unlock(&cond_mutex);
1434  if (isValid()) {
1435  bool ret = (bool)atoi(private_response);
1436  lives_free(private_response);
1437  return ret;
1438  }
1439  return false;
1440 }
1441 
1442 
1444 
1446 effectKey::effectKey() {
1447  m_key = 0;
1448 }
1449 
1450 
1451 effectKey::effectKey(livesApp *lives, int key) {
1452  m_lives = lives;
1453  m_key = key;
1454 }
1455 
1456 
1457 bool effectKey::isValid() const {
1458  return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY &&
1459  m_key >= 1 && m_key <= prefs::rteKeysVirtual(*(m_lives));
1460 }
1461 
1462 
1463 int effectKey::key() {
1464  return m_key;
1465 }
1466 
1467 
1468 int effectKey::numModes() {
1469  if (!isValid()) return 0;
1471 }
1472 
1473 
1474 int effectKey::numMappedModes() {
1475  if (!isValid()) return 0;
1476  return get_num_mapped_modes_for_key(m_key);
1477 }
1478 
1479 
1480 int effectKey::currentMode() {
1481  if (!isValid()) return -1;
1482  return get_current_mode_for_key(m_key);
1483 }
1484 
1485 
1486 bool effectKey::enabled() {
1487  if (!isValid()) return false;
1488  return get_rte_key_is_enabled(m_key);
1489 }
1490 
1491 
1492 int effectKey::setCurrentMode(int new_mode) {
1493  if (!isValid()) return -1;
1494  if (new_mode < 0 || new_mode >= numMappedModes()) return currentMode();
1495 
1496  if (new_mode == currentMode()) return currentMode();
1497 
1498  spinning = true;
1499  msg_id = lives_random();
1500  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1501 
1502  pthread_mutex_lock(&cond_mutex);
1503  if (!idle_fx_setmode(m_key, new_mode, msg_id)) {
1504  pthread_mutex_unlock(&cond_mutex);
1505  spinning = false;
1506  m_lives->removeCallback(cbid);
1507  return currentMode();
1508  }
1509  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1510  pthread_mutex_unlock(&cond_mutex);
1511  if (isValid()) {
1512  lives_free(private_response);
1513  }
1514  return currentMode();
1515 }
1516 
1517 
1518 bool effectKey::setEnabled(bool setting) {
1519  if (!isValid()) return false;
1520 
1521  spinning = true;
1522  msg_id = lives_random();
1523  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1524 
1525  pthread_mutex_lock(&cond_mutex);
1526  if (!idle_fx_enable(m_key, setting, msg_id)) {
1527  spinning = false;
1528  m_lives->removeCallback(cbid);
1529  return enabled();
1530  }
1531  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1532  pthread_mutex_unlock(&cond_mutex);
1533  if (isValid()) {
1534  lives_free(private_response);
1535 
1536  // TODO: if it was a generator, wait for playing or error
1537 
1538  }
1539  return enabled();
1540 }
1541 
1542 
1543 int effectKey::appendMapping(effect fx) {
1544  if (!isValid()) return -1;
1545 
1546  if (!fx.isValid()) return -1;
1547 
1548  if (fx.m_lives != m_lives) return -1;
1549 
1550  if (!m_lives->isReady() && !m_lives->isPlaying()) return -1;
1551 
1552  int mode = numMappedModes();
1553  if (mode == numModes()) return -1;
1554 
1555  spinning = true;
1556  msg_id = lives_random();
1557  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1558 
1559  pthread_mutex_lock(&cond_mutex);
1560  if (!idle_map_fx(m_key, mode, fx.m_idx, msg_id)) {
1561  pthread_mutex_unlock(&cond_mutex);
1562  spinning = false;
1563  m_lives->removeCallback(cbid);
1564  return -1;
1565  }
1566  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1567  pthread_mutex_unlock(&cond_mutex);
1568  if (isValid()) {
1569  bool ret = (bool)atoi(private_response);
1570  lives_free(private_response);
1571  if (ret) return mode;
1572  }
1573  return -1;
1574 }
1575 
1576 
1577 bool effectKey::removeMapping(int mode) {
1578  if (!isValid()) return false;
1579 
1580  if (!m_lives->isReady() && !m_lives->isPlaying()) return false;
1581 
1582  if (mode >= numMappedModes()) return false;
1583 
1584  spinning = true;
1585  msg_id = lives_random();
1586  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1587 
1588  pthread_mutex_lock(&cond_mutex);
1589  if (!idle_unmap_fx(m_key, mode, msg_id)) {
1590  pthread_mutex_unlock(&cond_mutex);
1591  spinning = false;
1592  m_lives->removeCallback(cbid);
1593  return false;
1594  }
1595  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1596  pthread_mutex_unlock(&cond_mutex);
1597  if (isValid()) {
1598  bool ret = (bool)atoi(private_response);
1599  lives_free(private_response);
1600  return ret;
1601  }
1602  return false;
1603 }
1604 
1605 
1606 effect effectKey::at(int mode) {
1607  effect e;
1608  if (!isValid()) return e;
1609  int idx = rte_keymode_get_filter_idx(m_key, mode);
1610  if (idx == -1) return e;
1611  e = effect(m_lives, idx);
1612  return e;
1613 }
1614 
1615 
1617 
1618 effect::effect(const livesApp &lives, livesString hashname, bool match_full) {
1619  m_idx = -1;
1620  m_lives = (livesApp *)&lives;
1621  if (m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY) {
1622  m_idx = weed_get_idx_for_hashname(hashname.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(), match_full);
1623  }
1624 }
1625 
1626 effect::effect(const livesApp &lives, livesString package, livesString fxname, livesString author, int version) {
1627  m_idx = -1;
1628  m_lives = (livesApp *)&lives;
1629  if (m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY) {
1630  m_idx = get_first_fx_matched(package.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(),
1631  fxname.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(),
1632  author.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(),
1633  version);
1634  }
1635 }
1636 
1637 bool effect::isValid() const {
1638  return (m_idx != -1 && m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY);
1639 }
1640 
1641 
1642 effect::effect() : m_lives(NULL), m_idx(-1) {}
1643 
1644 effect::effect(livesApp *lives, int idx) : m_lives(lives), m_idx(idx) {}
1645 
1646 
1649 
1650 block::block(multitrack *m, ulong uid) : m_uid(uid) {
1651  if (m == NULL) m_lives = NULL;
1652  else m_lives = m->m_lives;
1653 }
1654 
1655 
1656 block::block(multitrack m, int track, double time) {
1657  m_lives = m.m_lives;
1658  if (!m.isActive()) m_uid = 0l;
1659  else {
1660  track_rect *tr = get_block_from_track_and_time(mainw->multitrack, track, time);
1661  if (tr == NULL) m_uid = 0l;
1662  else m_uid = tr->uid;
1663  }
1664 }
1665 
1666 
1667 bool block::isValid() const {
1668  if (m_lives == NULL || !m_lives->isValid() || !m_lives->m_multitrack->isActive() || m_uid == 0l ||
1669  find_block_by_uid(mainw->multitrack, m_uid) == NULL) return false;
1670  return true;
1671 }
1672 
1673 
1674 void block::invalidate() {
1675  m_uid = 0l;
1676 }
1677 
1678 
1679 double block::startTime() {
1680  track_rect *tr = find_block_by_uid(mainw->multitrack, m_uid);
1681  if (tr == NULL) return -1.;
1682  return (double)get_event_timecode(tr->start_event) / TICKS_PER_SECOND_DBL;
1683 }
1684 
1685 
1686 double block::length() {
1687  track_rect *tr = find_block_by_uid(mainw->multitrack, m_uid);
1688  if (tr == NULL) return -1.;
1689  return (double)get_event_timecode(tr->end_event) / TICKS_PER_SECOND_DBL + 1. / mainw->multitrack->fps -
1690  (double)get_event_timecode(tr->start_event) / TICKS_PER_SECOND_DBL;
1691 }
1692 
1693 
1694 clip block::clipSource() {
1695  track_rect *tr = find_block_by_uid(mainw->multitrack, m_uid);
1696  if (tr == NULL) return clip();
1697  int cnum = get_clip_for_block(tr);
1698  if (cnum == -1) return clip();
1699  return clip(mainw->files[cnum]->unique_id, m_lives);
1700 }
1701 
1702 
1703 int block::track() {
1704  track_rect *tr = find_block_by_uid(mainw->multitrack, m_uid);
1705  if (tr == NULL) return 0;
1706  return get_track_for_block(tr);
1707 }
1708 
1709 
1710 bool block::remove() {
1711  if (!isValid()) return false;
1712  if (!m_lives->isReady()) return false;
1713 
1714  track_rect *tr = find_block_by_uid(mainw->multitrack, m_uid);
1715  if (tr == NULL) return false;
1716 
1717  spinning = true;
1718  msg_id = lives_random();
1719  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1720  pthread_mutex_lock(&cond_mutex);
1721  if (!idle_remove_block(m_uid, msg_id)) {
1722  pthread_mutex_unlock(&cond_mutex);
1723  spinning = false;
1724  m_lives->removeCallback(cbid);
1725  return false;
1726  }
1727  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1728  pthread_mutex_unlock(&cond_mutex);
1729  if (isValid()) {
1730  bool ret = (bool)atoi(private_response);
1731  lives_free(private_response);
1732  if (ret) invalidate();
1733  return ret;
1734  }
1735  return false;
1736 }
1737 
1738 
1739 bool block::moveTo(int track, double time) {
1740  if (!isValid()) return false;
1741  if (!m_lives->isReady()) return false;
1742 
1743  track_rect *tr = find_block_by_uid(mainw->multitrack, m_uid);
1744  if (tr == NULL) return false;
1745 
1746  spinning = true;
1747  msg_id = lives_random();
1748  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1749  pthread_mutex_lock(&cond_mutex);
1750  if (!idle_move_block(m_uid, track, time, msg_id)) {
1751  pthread_mutex_unlock(&cond_mutex);
1752  spinning = false;
1753  m_lives->removeCallback(cbid);
1754  return false;
1755  }
1756  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1757  pthread_mutex_unlock(&cond_mutex);
1758  if (isValid()) {
1759  bool ret = (bool)atoi(private_response);
1760  lives_free(private_response);
1761  if (ret) invalidate();
1762  return ret;
1763  }
1764  return false;
1765 }
1766 
1767 
1770 
1771 multitrack::multitrack(livesApp *lives) {
1772  m_lives = lives;
1773 }
1774 
1775 
1776 bool multitrack::isValid() const {
1777  return m_lives != NULL && m_lives->m_id != 0l && m_lives->status() != LIVES_STATUS_NOTREADY;
1778 }
1779 
1780 
1781 bool multitrack::isActive() const {
1782  return (isValid() && mainw->multitrack != NULL);
1783 }
1784 
1785 
1786 double multitrack::currentTime() const {
1787  if (!isActive()) return 0.;
1788  return m_lives->m_player->videoPlaybackTime();
1789 }
1790 
1791 
1792 double multitrack::setCurrentTime(double time) const {
1793  if (!isActive() || !m_lives->isReady()) return currentTime();
1794  return m_lives->m_player->setPlaybackStartTime(time);
1795 }
1796 
1797 
1798 block multitrack::insertBlock(clip c, bool ign_sel, bool without_audio) const {
1799  if (!isActive()) return block();
1800  if (!c.isValid()) return block();
1801  if (!m_lives->isReady()) return block();
1802 
1803  int clipno = cnum_for_uid(c.m_uid);
1804 
1805  spinning = true;
1806  msg_id = lives_random();
1807  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1808  pthread_mutex_lock(&cond_mutex);
1809  if (!idle_insert_block(clipno, ign_sel, !without_audio, msg_id)) {
1810  pthread_mutex_unlock(&cond_mutex);
1811  spinning = false;
1812  m_lives->removeCallback(cbid);
1813  return block();
1814  }
1815  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1816  pthread_mutex_unlock(&cond_mutex);
1817  if (isValid()) {
1818  ulong uid = strtoul(private_response, NULL, 10);
1819  lives_free(private_response);
1820  return block(const_cast<multitrack *>(this), uid);
1821  }
1822  return block();
1823 }
1824 
1825 
1826 livesString multitrack::wipeLayout(bool force) const {
1827  livesString emptystr;
1828  if (!isActive()) return emptystr;
1829  if (!m_lives->isReady()) return emptystr;
1830 
1831  spinning = true;
1832  msg_id = lives_random();
1833  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1834 
1835  pthread_mutex_lock(&cond_mutex);
1836  if (!idle_wipe_layout(force, msg_id)) {
1837  pthread_mutex_unlock(&cond_mutex);
1838  spinning = false;
1839  m_lives->removeCallback(cbid);
1840  return emptystr;
1841  }
1842  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1843  pthread_mutex_unlock(&cond_mutex);
1844  if (isValid()) {
1845  livesString str(private_response, LIVES_CHAR_ENCODING_UTF8);
1846  lives_free(private_response);
1847  return str;
1848  }
1849  return emptystr;
1850 }
1851 
1852 
1853 livesString multitrack::chooseLayout() const {
1854  livesString emptystr;
1855  if (!isActive()) return emptystr;
1856  if (!m_lives->isReady()) return emptystr;
1857 
1858  spinning = true;
1859  msg_id = lives_random();
1860  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1861 
1862  pthread_mutex_lock(&cond_mutex);
1863  if (!idle_choose_layout(msg_id)) {
1864  pthread_mutex_unlock(&cond_mutex);
1865  spinning = false;
1866  m_lives->removeCallback(cbid);
1867  return emptystr;
1868  }
1869  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1870  pthread_mutex_unlock(&cond_mutex);
1871  if (isValid()) {
1872  livesString str(private_response, LIVES_CHAR_ENCODING_UTF8);
1873  lives_free(private_response);
1874  return str;
1875  }
1876  return emptystr;
1877 }
1878 
1879 
1880 livesStringList multitrack::availableLayouts() const {
1881  livesStringList list;
1882  if (!isValid()) return list;
1883  LiVESList *layoutlist = mainw->current_layouts_map;
1884  while (layoutlist != NULL) {
1885  char *data = repl_workdir((const char *)layoutlist->data, FALSE);
1886  list.push_back(livesString(data, LIVES_CHAR_ENCODING_FILESYSTEM).toEncoding(LIVES_CHAR_ENCODING_UTF8));
1887  lives_free(data);
1888  layoutlist = layoutlist->next;
1889  }
1890  return list;
1891 }
1892 
1893 
1894 bool multitrack::reloadLayout(livesString layoutname) const {
1895  if (!isActive()) return false;
1896  if (!m_lives->isReady()) return false;
1897 
1898  spinning = true;
1899  msg_id = lives_random();
1900  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1901 
1902  pthread_mutex_lock(&cond_mutex);
1903  if (!idle_reload_layout(layoutname.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str(), msg_id)) {
1904  pthread_mutex_unlock(&cond_mutex);
1905  spinning = false;
1906  m_lives->removeCallback(cbid);
1907  return false;
1908  }
1909  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1910  pthread_mutex_unlock(&cond_mutex);
1911  if (isValid()) {
1912  bool ret = (bool)atoi(private_response);
1913  lives_free(private_response);
1914  return ret;
1915  }
1916  return false;
1917 }
1918 
1919 
1920 livesString multitrack::saveLayout(livesString name) const {
1921  livesString emptystr;
1922  if (!isActive()) return emptystr;
1923  if (!m_lives->isReady()) return emptystr;
1924 
1925  spinning = true;
1926  msg_id = lives_random();
1927  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1928 
1929  pthread_mutex_lock(&cond_mutex);
1930  if (!idle_save_layout(name.toEncoding(LIVES_CHAR_ENCODING_FILESYSTEM).c_str(), msg_id)) {
1931  pthread_mutex_unlock(&cond_mutex);
1932  spinning = false;
1933  m_lives->removeCallback(cbid);
1934  return emptystr;
1935  }
1936  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1937  pthread_mutex_unlock(&cond_mutex);
1938  if (isValid()) {
1939  char *lname = strdup(private_response);
1940  lives_free(private_response);
1941  return livesString(lname).toEncoding(LIVES_CHAR_ENCODING_UTF8);
1942  }
1943  return emptystr;
1944 }
1945 
1946 
1947 livesString multitrack::saveLayout() const {
1948  livesString emptystr;
1949  if (!isActive()) return emptystr;
1950  if (!m_lives->isReady()) return emptystr;
1951 
1952  spinning = true;
1953  msg_id = lives_random();
1954  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1955 
1956  pthread_mutex_lock(&cond_mutex);
1957  if (!idle_save_layout(NULL, msg_id)) {
1958  pthread_mutex_unlock(&cond_mutex);
1959  spinning = false;
1960  m_lives->removeCallback(cbid);
1961  return emptystr;
1962  }
1963  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1964  pthread_mutex_unlock(&cond_mutex);
1965  if (isValid()) {
1966  char *lname = strdup(private_response);
1967  lives_free(private_response);
1968  return livesString(lname).toEncoding(LIVES_CHAR_ENCODING_UTF8);
1969  }
1970  return emptystr;
1971 }
1972 
1973 
1974 clip multitrack::render(bool with_audio, bool normalise_audio) const {
1975  clip c;
1976  if (!isActive()) return c;
1977  if (!m_lives->isReady()) return c;
1978 
1979  spinning = true;
1980  msg_id = lives_random();
1981  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
1982 
1983  pthread_mutex_lock(&cond_mutex);
1984  if (!idle_render_layout(with_audio, normalise_audio, msg_id)) {
1985  pthread_mutex_unlock(&cond_mutex);
1986  spinning = false;
1987  m_lives->removeCallback(cbid);
1988  return c;
1989  }
1990  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1991  pthread_mutex_unlock(&cond_mutex);
1992  if (isValid()) {
1993  ulong uid = strtoul(private_response, NULL, 10);
1994  c = clip(uid, m_lives);
1995  lives_free(private_response);
1996  }
1997  return c;
1998 }
1999 
2000 
2001 effect multitrack::autoTransition() const {
2002  effect e;
2003  if (!m_lives->isValid() || m_lives->status() == LIVES_STATUS_NOTREADY) return e;
2004  if (::prefs->atrans_fx == -1) return e;
2005  e = effect(m_lives, ::prefs->atrans_fx);
2006  return e;
2007 }
2008 
2009 
2010 bool multitrack::setAutoTransition(effect autotrans) const {
2011  if (!m_lives->isValid()) return false;
2012  if (!autotrans.isValid()) return disableAutoTransition();
2013 
2014  // check if is transition
2015  if (get_transition_param(get_weed_filter(autotrans.m_idx), FALSE) == -1) return false;
2016 
2017  if (m_lives->status() != LIVES_STATUS_READY && m_lives->status() != LIVES_STATUS_PLAYING) return false;
2018  mt_set_autotrans(autotrans.m_idx);
2019  return true;
2020 }
2021 
2022 
2023 bool multitrack::disableAutoTransition() const {
2024  if (!m_lives->isValid()) return false;
2025  if (m_lives->status() != LIVES_STATUS_READY && m_lives->status() != LIVES_STATUS_PLAYING) return false;
2026  mt_set_autotrans(-1);
2027  return true;
2028 }
2029 
2030 
2031 int multitrack::currentTrack() const {
2032  if (!isActive()) return 0;
2033  return mainw->multitrack->current_track;
2034 }
2035 
2036 
2037 bool multitrack::setCurrentTrack(int track) const {
2038  if (m_lives->status() == LIVES_STATUS_PROCESSING) return false;
2039  if (!isActive()) return false;
2040 
2041  spinning = true;
2042  msg_id = lives_random();
2043  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
2044  pthread_mutex_lock(&cond_mutex);
2045  if (!idle_mt_set_track(track, msg_id)) {
2046  pthread_mutex_unlock(&cond_mutex);
2047  spinning = false;
2048  m_lives->removeCallback(cbid);
2049  } else {
2050  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2051  pthread_mutex_unlock(&cond_mutex);
2052  if (isValid()) {
2053  bool ret = (bool)(atoi(private_response));
2054  lives_free(private_response);
2055  return ret;
2056  }
2057  }
2058  return false;
2059 }
2060 
2061 
2062 livesString multitrack::trackLabel(int track) const {
2063  livesString emptystr;
2064  if (!isActive()) return emptystr;
2065 
2066  if (mt_track_is_video(mainw->multitrack, track))
2067  return livesString(get_track_name(mainw->multitrack, track, FALSE), LIVES_CHAR_ENCODING_UTF8);
2068  if (mt_track_is_audio(mainw->multitrack, track))
2069  return livesString(get_track_name(mainw->multitrack, track, TRUE), LIVES_CHAR_ENCODING_UTF8);
2070 
2071  return emptystr;
2072 }
2073 
2074 
2075 double multitrack::FPS() const {
2076  if (!isActive()) return 0.;
2077  return mainw->multitrack->fps;
2078 }
2079 
2080 
2081 bool multitrack::setTrackLabel(int track, livesString label) const {
2082  if (m_lives->status() == LIVES_STATUS_PROCESSING) return false;
2083  if (!isActive()) return false;
2084 
2085  spinning = true;
2086  msg_id = lives_random();
2087  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
2088  pthread_mutex_lock(&cond_mutex);
2089  if (!idle_set_track_label(track, label.toEncoding(LIVES_CHAR_ENCODING_UTF8).c_str(), msg_id)) {
2090  pthread_mutex_unlock(&cond_mutex);
2091  spinning = false;
2092  m_lives->removeCallback(cbid);
2093  } else {
2094  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2095  pthread_mutex_unlock(&cond_mutex);
2096  if (isValid()) {
2097  bool ret = (bool)(atoi(private_response));
2098  lives_free(private_response);
2099  return ret;
2100  }
2101  }
2102  return false;
2103 }
2104 
2105 
2106 lives_gravity_t multitrack::gravity() const {
2107  if (!isActive()) return LIVES_GRAVITY_NORMAL;
2108  switch (mainw->multitrack->opts.grav_mode) {
2109  case GRAV_MODE_LEFT:
2110  return LIVES_GRAVITY_LEFT;
2111  case GRAV_MODE_RIGHT:
2112  return LIVES_GRAVITY_RIGHT;
2113  default:
2114  return LIVES_GRAVITY_NORMAL;
2115  }
2116 }
2117 
2118 
2119 lives_gravity_t multitrack::setGravity(lives_gravity_t grav) const {
2120  if (m_lives->status() == LIVES_STATUS_PROCESSING) return gravity();
2121  if (!isActive()) return gravity();
2122 
2123  spinning = true;
2124  msg_id = lives_random();
2125  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
2126  pthread_mutex_lock(&cond_mutex);
2127  if (!idle_set_gravity((int)grav, msg_id)) {
2128  pthread_mutex_unlock(&cond_mutex);
2129  spinning = false;
2130  m_lives->removeCallback(cbid);
2131  } else {
2132  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2133  pthread_mutex_unlock(&cond_mutex);
2134  if (isValid()) {
2135  lives_free(private_response);
2136  }
2137  }
2138  return gravity();
2139 }
2140 
2141 
2142 lives_insert_mode_t multitrack::insertMode() const {
2143  if (!isActive()) return LIVES_INSERT_MODE_NORMAL;
2144  switch (mainw->multitrack->opts.insert_mode) {
2145  default:
2146  return LIVES_INSERT_MODE_NORMAL;
2147  }
2148 }
2149 
2150 
2151 lives_insert_mode_t multitrack::setInsertMode(lives_insert_mode_t mode) const {
2152  if (m_lives->status() == LIVES_STATUS_PROCESSING) return insertMode();
2153  if (!isActive()) return insertMode();
2154 
2155  spinning = true;
2156  msg_id = lives_random();
2157  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
2158  pthread_mutex_lock(&cond_mutex);
2159  if (!idle_set_insert_mode((int)mode, msg_id)) {
2160  pthread_mutex_unlock(&cond_mutex);
2161  spinning = false;
2162  m_lives->removeCallback(cbid);
2163  } else {
2164  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2165  pthread_mutex_unlock(&cond_mutex);
2166  if (isValid()) {
2167  lives_free(private_response);
2168  }
2169  }
2170  return insertMode();
2171 }
2172 
2173 
2174 int multitrack::numAudioTracks() const {
2175  if (!isActive()) return 0;
2176  return mainw->multitrack->opts.back_audio_tracks;
2177 }
2178 
2179 
2180 int multitrack::numVideoTracks() const {
2181  if (!isActive()) return 0;
2182  return mainw->multitrack->num_video_tracks;
2183 }
2184 
2185 
2186 int multitrack::addVideoTrack(bool in_front) const {
2187  if (!isActive()) return -1;
2188  if (m_lives->isReady()) return -1.;
2189 
2190  spinning = true;
2191  msg_id = lives_random();
2192  ulong cbid = m_lives->addCallback(LIVES_CALLBACK_PRIVATE, private_cb, NULL);
2193  pthread_mutex_lock(&cond_mutex);
2194  if (!idle_insert_vtrack(in_front, msg_id)) {
2195  pthread_mutex_unlock(&cond_mutex);
2196  spinning = false;
2197  m_lives->removeCallback(cbid);
2198  } else {
2199  while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2200  pthread_mutex_unlock(&cond_mutex);
2201  if (isValid()) {
2202  int tnum = atoi(private_response);
2203  lives_free(private_response);
2204  return tnum;
2205  }
2206  }
2207  return -1;
2208 }
2209 
2210 
2212 
2214 
2215 namespace prefs {
2216 livesString currentVideoLoadDir(const livesApp &lives) {
2217  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return livesString();
2218  return livesString(mainw->vid_load_dir, LIVES_CHAR_ENCODING_UTF8);
2219 }
2220 
2221 livesString currentAudioDir(const livesApp &lives) {
2222  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return livesString();
2223  return livesString(mainw->audio_dir, LIVES_CHAR_ENCODING_UTF8);
2224 }
2225 
2226 livesString tmpDir(const livesApp &lives) {
2227  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return livesString();
2228  return livesString(::prefs->workdir, LIVES_CHAR_ENCODING_FILESYSTEM);
2229 }
2230 
2232  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return LIVES_AUDIO_SOURCE_UNKNOWN;
2235 }
2236 
2237 bool setAudioSource(const livesApp &lives, lives_audio_source_t asrc) {
2238  if (!lives.isReady()) return false;
2239  return lives.setPref(PREF_REC_EXT_AUDIO, (bool)(asrc == LIVES_AUDIO_SOURCE_EXTERNAL));
2240 }
2241 
2243  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return LIVES_AUDIO_PLAYER_UNKNOWN;
2248 }
2249 
2250 int audioPlayerRate(const livesApp &lives) {
2251  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return 0;
2252 #ifdef ENABLE_JACK
2253  if (::prefs->audio_player == AUD_PLAYER_JACK && mainw->jackd != NULL) return mainw->jackd->sample_out_rate;
2254 #endif
2255 #ifdef HAVE_PULSE_AUDIO
2256  if (::prefs->audio_player == AUD_PLAYER_PULSE && mainw->pulsed != NULL) return mainw->pulsed->out_arate;
2257 #endif
2258  return 0;
2259 }
2260 
2262  int ptype = AUD_PLAYER_NONE;
2263  if (player_type == LIVES_AUDIO_PLAYER_SOX) ptype = AUD_PLAYER_SOX;
2264  else if (player_type == LIVES_AUDIO_PLAYER_JACK) ptype = AUD_PLAYER_JACK;
2265  else if (player_type == LIVES_AUDIO_PLAYER_PULSE) ptype = AUD_PLAYER_PULSE;
2266  return is_realtime_aplayer(ptype);
2267 }
2268 
2269 int rteKeysVirtual(const livesApp &lives) {
2270  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return 0;
2272 }
2273 
2274 double maxFPS(const livesApp &lives) {
2275  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return 0.;
2276  return FPS_MAX;
2277 }
2278 
2279 bool audioFollowsVideoChanges(const livesApp &lives) {
2280  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2282 }
2283 
2284 bool audioFollowsFPSChanges(const livesApp &lives) {
2285  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2287 }
2288 
2289 bool setAudioFollowsVideoChanges(const livesApp &lives, bool setting) {
2290  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2291  return lives.setPref(PREF_AUDIO_OPTS, AUDIO_OPTS_FOLLOW_CLIPS, setting);
2292 }
2293 
2294 bool setAudioFollowsFPSChanges(const livesApp &lives, bool setting) {
2295  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2296  return lives.setPref(PREF_AUDIO_OPTS, AUDIO_OPTS_FOLLOW_FPS, setting);
2297 }
2298 
2299 bool sepWinSticky(const livesApp &lives) {
2300  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2302 }
2303 
2304 bool setSepWinSticky(const livesApp &lives, bool setting) {
2305  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2306  return lives.setPref(PREF_SEPWIN_TYPE, setting ? SEPWIN_TYPE_STICKY : SEPWIN_TYPE_NON_STICKY);
2307 }
2308 
2309 bool mtExitRender(const livesApp &lives) {
2310  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2312 }
2313 
2314 bool setMtExitRender(const livesApp &lives, bool setting) {
2315  if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2316  return lives.setPref(PREF_MT_EXIT_RENDER, setting);
2317 }
2318 }
2319 }
2320 
2321 
2323 
2324 #ifndef DOXYGEN_SKIP
2325 
2326 void binding_cb(lives_callback_t cb_type, const char *msgstring, ulong id) {
2327  bool ret;
2328  lives::livesApp *lapp;
2329 
2330  if (cb_type == LIVES_CALLBACK_OBJECT_DESTROYED) lapp = (lives::livesApp *)id;
2331  else lapp = lives::find_instance_for_id(id);
2332 
2333  if (lapp == NULL) return;
2334 
2335  pthread_mutex_lock(&spin_mutex); // lock mutex so that new callbacks cannot be added yet
2336 
2337  lives::closureList cl = lapp->closures();
2338 
2339  lives::closureListIterator it = cl.begin();
2340  while (it != cl.end()) {
2341  if ((*it)->cb_type == cb_type) {
2342  switch (cb_type) {
2344  lives::modeChangedInfo info;
2345  info.mode = (lives_interface_mode_t)atoi(msgstring);
2346  lives::modeChanged_callback_f fn = (lives::modeChanged_callback_f)((*it)->func);
2347  ret = (fn)((*it)->object, &info, (*it)->data);
2348  }
2349  break;
2350  case LIVES_CALLBACK_APP_QUIT: {
2351  // TODO !! test
2352  lives::appQuitInfo info;
2353  info.signum = atoi(msgstring);
2354  lives::appQuit_callback_f fn = (lives::appQuit_callback_f)((*it)->func);
2355  lapp->invalidate();
2356  ret = (fn)((*it)->object, &info, (*it)->data);
2357  spinning = false;
2358  }
2359  break;
2361  lives::objectDestroyed_callback_f fn = (lives::objectDestroyed_callback_f)((*it)->func);
2362  ret = (fn)((*it)->object, (*it)->data);
2363  }
2364  break;
2365  case LIVES_CALLBACK_PRIVATE: {
2366  // private event type
2367  lives::_privateInfo info;
2368  char *endptr;
2369  info.id = strtoul(msgstring, &endptr, 10);
2370  info.response = endptr + 1;
2371  lives::private_callback_f fn = (lives::private_callback_f)((*it)->func);
2372  ret = (fn)(&info, (*it)->data);
2373  }
2374  break;
2375  default:
2376  ++it;
2377  continue;
2378  }
2379  if (!ret) {
2380  delete *it;
2381  it = cl.erase(it);
2382  lapp->setClosures(cl);
2383  continue;
2384  }
2385  }
2386  ++it;
2387  }
2388 
2389  pthread_mutex_unlock(&spin_mutex);
2390 }
2391 
2392 #endif // doxygen_skip
idle_set_pref_bool
boolean idle_set_pref_bool(const char *prefidx, boolean val, ulong id)
Definition: lbindings.c:1613
idle_set_current_frame
boolean idle_set_current_frame(int frame, boolean bg, ulong id)
Definition: lbindings.c:1888
mainwindow::jackd
void * jackd
jack audio player / transport
Definition: mainwindow.h:1453
AFORM_UNSIGNED
#define AFORM_UNSIGNED
Definition: main.h:786
idle_switch_clip
boolean idle_switch_clip(int type, int cnum, ulong id)
Definition: lbindings.c:1217
LIVES_AUDIO_PLAYER_UNKNOWN
@ LIVES_AUDIO_PLAYER_UNKNOWN
Unknown / invalid.
Definition: liblives.hpp:159
LIVES_GRAVITY_NORMAL
@ LIVES_GRAVITY_NORMAL
no gravity
Definition: liblives.hpp:180
idle_set_insert_mode
boolean idle_set_insert_mode(int mode, ulong id)
Definition: lbindings.c:1531
idle_set_current_time
boolean idle_set_current_time(double time, ulong id)
Definition: lbindings.c:1277
idle_set_pref_bitmapped
boolean idle_set_pref_bitmapped(const char *prefidx, int bitfield, boolean val, ulong id)
Definition: lbindings.c:1645
LIVES_INSERT_MODE_NORMAL
@ LIVES_INSERT_MODE_NORMAL
Definition: liblives.hpp:172
lives_ruler_get_value
WIDGET_HELPER_GLOBAL_INLINE double lives_ruler_get_value(LiVESRuler *ruler)
Definition: widget-helper.c:5272
LIVES_STATUS_PROCESSING
@ LIVES_STATUS_PROCESSING
application is processing, commands will be ignored
Definition: liblives.hpp:64
liblives.hpp
Header file for liblives.
lives_free
#define lives_free
Definition: machinestate.h:52
LIVES_INTERFACE_MODE_MULTITRACK
@ LIVES_INTERFACE_MODE_MULTITRACK
multitrack mode
Definition: liblives.hpp:52
GRAV_MODE_LEFT
@ GRAV_MODE_LEFT
Definition: multitrack.h:86
PREF_REC_EXT_AUDIO
#define PREF_REC_EXT_AUDIO
Definition: preferences.h:892
idle_set_current_audio_time
boolean idle_set_current_audio_time(double time, ulong id)
Definition: lbindings.c:1292
get_rte_key_is_enabled
boolean get_rte_key_is_enabled(int key)
Definition: lbindings.c:367
LIVES_AUDIO_PLAYER_JACK
@ LIVES_AUDIO_PLAYER_JACK
Audio playback is thorugh Jack.
Definition: liblives.hpp:161
mainwindow::record
volatile boolean record
Definition: mainwindow.h:794
lives::prefs::audioPlayerRate
int audioPlayerRate(const livesApp &lives)
Definition: liblives.cpp:2250
lives_callback_t
lives_callback_t
Callback types.
Definition: liblives.hpp:81
idle_set_loop_mode
boolean idle_set_loop_mode(int mode, ulong id)
Definition: lbindings.c:1902
mainwindow::loop
boolean loop
Definition: mainwindow.h:763
lives::prefs::setAudioSource
bool setAudioSource(const livesApp &lives, lives_audio_source_t asrc)
Definition: liblives.cpp:2237
_prefs::workdir
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
idle_set_set_name
boolean idle_set_set_name(ulong id)
Definition: lbindings.c:1404
version
const char * version(void)
LIVES_AUDIO_SOURCE_EXTERNAL
@ LIVES_AUDIO_SOURCE_EXTERNAL
Audio source is external to LiVES.
Definition: liblives.hpp:151
mainwindow::current_file
int current_file
Definition: mainwindow.h:727
idle_select_all
boolean idle_select_all(int cnum, ulong id)
Definition: lbindings.c:1823
get_weed_filter
weed_plant_t * get_weed_filter(int idx)
Definition: effects-weed.c:11014
LIVES_DIALOG_RESPONSE_INVALID
@ LIVES_DIALOG_RESPONSE_INVALID
INVALID response.
Definition: liblives.hpp:131
LIVES_CALLBACK_MODE_CHANGED
@ LIVES_CALLBACK_MODE_CHANGED
sent when interface mode changes
Definition: liblives.hpp:101
lives_dialog_response_t
lives_dialog_response_t
Dialog response values.
Definition: liblives.hpp:129
start_player
boolean start_player(void)
Definition: lbindings.c:257
cfile
#define cfile
Definition: main.h:1833
mainwindow::preview
boolean preview
Definition: mainwindow.h:757
lives_clip_t::start
frames_t start
Definition: main.h:891
idle_unmap_fx
boolean idle_unmap_fx(int key, int mode, ulong id)
Definition: lbindings.c:1561
LIVES_CALLBACK_OBJECT_DESTROYED
@ LIVES_CALLBACK_OBJECT_DESTROYED
sent when livesApp object is deleted
Definition: liblives.hpp:103
rte_keymode_get_filter_idx
int rte_keymode_get_filter_idx(int key, int mode)
returns filter_class index of key/mode (or -1 if no filter bound)
Definition: effects-weed.c:9416
lives_clip_t::frames
frames_t frames
number of video frames
Definition: main.h:890
LIVES_AUDIO_PLAYER_PULSE
@ LIVES_AUDIO_PLAYER_PULSE
Audio playback is through PulseAudio.
Definition: liblives.hpp:160
get_unique_ids
ulong * get_unique_ids(void)
utility functions for liblives /////
Definition: lbindings.c:214
prefs
_prefs * prefs
Definition: preferences.h:847
_prefs::audio_player
short audio_player
Definition: preferences.h:40
lives::prefs::setAudioFollowsVideoChanges
bool setAudioFollowsVideoChanges(const livesApp &lives, bool setting)
Definition: liblives.cpp:2289
lives::prefs::audioSource
lives_audio_source_t audioSource(const livesApp &lives)
Definition: liblives.cpp:2231
PREF_SEPWIN_TYPE
#define PREF_SEPWIN_TYPE
Definition: preferences.h:894
SEPWIN_TYPE_STICKY
#define SEPWIN_TYPE_STICKY
Definition: preferences.h:188
find_block_by_uid
track_rect * find_block_by_uid(lives_mt *mt, ulong uid)
Definition: multitrack.c:23012
LIVES_INTERFACE_MODE_CLIPEDIT
@ LIVES_INTERFACE_MODE_CLIPEDIT
clip editor mode
Definition: liblives.hpp:51
lives_status_t
lives_status_t
LiVES operational status.
Definition: liblives.hpp:59
TICKS_PER_SECOND_DBL
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
Definition: mainwindow.h:37
idle_set_current_fps
boolean idle_set_current_fps(double fps, ulong id)
Definition: lbindings.c:1873
lives::prefs::audioPlayer
lives_audio_player_t audioPlayer(const livesApp &lives)
Definition: liblives.cpp:2242
AUD_PLAYER_NONE
#define AUD_PLAYER_NONE
Definition: preferences.h:41
lives_random
LIVES_GLOBAL_INLINE uint64_t lives_random(void)
Definition: machinestate.c:58
lives_endian_t
lives_endian_t
Endian values.
Definition: liblives.hpp:72
LIVES_CHAR_ENCODING_FILESYSTEM
@ LIVES_CHAR_ENCODING_FILESYSTEM
file system encoding (UTF-8 on windows, local8bit on others)
Definition: liblives.hpp:117
GRAV_MODE_RIGHT
@ GRAV_MODE_RIGHT
Definition: multitrack.h:87
lives::prefs::audioFollowsVideoChanges
bool audioFollowsVideoChanges(const livesApp &lives)
Definition: liblives.cpp:2279
LIVES_STATUS_READY
@ LIVES_STATUS_READY
application is ready for commands
Definition: liblives.hpp:62
idle_select_end
boolean idle_select_end(int cnum, int frame, ulong id)
Definition: lbindings.c:1856
lives::prefs::sepWinSticky
bool sepWinSticky(const livesApp &lives)
Definition: liblives.cpp:2299
lives::prefs::maxFPS
double maxFPS(const livesApp &lives)
Definition: liblives.cpp:2274
_prefs::rte_keys_virtual
short rte_keys_virtual
Definition: preferences.h:223
mainwindow::event_list
weed_event_t * event_list
current event_list, for recording
Definition: mainwindow.h:803
lives::prefs::setMtExitRender
bool setMtExitRender(const livesApp &lives, bool setting)
Definition: liblives.cpp:2314
lives_gravity_t
lives_gravity_t
Multitrack gravity.
Definition: liblives.hpp:179
idle_set_pref_int
boolean idle_set_pref_int(const char *prefidx, int val, ulong id)
Definition: lbindings.c:1629
mainwindow::set_name
char set_name[256]
Definition: mainwindow.h:749
idle_move_block
boolean idle_move_block(ulong uid, int track, double time, ulong id)
Definition: lbindings.c:1715
LIVES_STATUS_INVALID
@ LIVES_STATUS_INVALID
livesApp instance is invalid
Definition: liblives.hpp:60
mainwindow::audio_dir
char audio_dir[PATH_MAX]
Definition: mainwindow.h:733
get_track_for_block
int get_track_for_block(track_rect *block)
return track number for a given block
Definition: multitrack.c:231
TRUE
#define TRUE
Definition: videoplugin.h:59
LIVES_CALLBACK_APP_QUIT
@ LIVES_CALLBACK_APP_QUIT
sent when app quits
Definition: liblives.hpp:92
LIVES_LITTLEENDIAN
@ LIVES_LITTLEENDIAN
Definition: liblives.hpp:73
idle_insert_block
boolean idle_insert_block(int clipno, boolean ign_sel, boolean with_audio, ulong id)
Definition: lbindings.c:1677
LIVES_AUDIO_SOURCE_UNKNOWN
@ LIVES_AUDIO_SOURCE_UNKNOWN
Unknown / invalid.
Definition: liblives.hpp:149
get_block_from_track_and_time
track_rect * get_block_from_track_and_time(lives_mt *mt, int track, double time)
get timeline end time of block
Definition: multitrack.c:23099
LIVES_AUDIO_SOURCE_INTERNAL
@ LIVES_AUDIO_SOURCE_INTERNAL
Audio source is internal to LiVES.
Definition: liblives.hpp:150
LIVES_STATUS_PREVIEW
@ LIVES_STATUS_PREVIEW
user is previewing an operation, commands will be ignored
Definition: liblives.hpp:65
LIVES_GRAVITY_LEFT
@ LIVES_GRAVITY_LEFT
inserted blocks gravitate to the left
Definition: liblives.hpp:181
mainwindow::loop_cont
volatile boolean loop_cont
Definition: mainwindow.h:764
idle_set_interactive
boolean idle_set_interactive(boolean setting, ulong id)
Definition: lbindings.c:1453
_prefs::audio_opts
volatile uint32_t audio_opts
Definition: preferences.h:254
is_realtime_aplayer
#define is_realtime_aplayer(ptype)
Definition: audio.h:236
lives_clip_t::fps
double fps
Definition: main.h:893
lives_insert_mode_t
lives_insert_mode_t
Multitrack insert modes.
Definition: liblives.hpp:171
LIVES_CHAR_ENCODING_UTF8
@ LIVES_CHAR_ENCODING_UTF8
UTF-8 char encoding.
Definition: liblives.hpp:115
idle_set_track_label
boolean idle_set_track_label(int tnum, const char *label, ulong id)
Definition: lbindings.c:1248
weed_get_idx_for_hashname
int weed_get_idx_for_hashname(const char *hashname, boolean fullname)
fullname includes author and version
Definition: effects-weed.c:10840
idle_cancel_proc
boolean idle_cancel_proc(ulong id)
Definition: lbindings.c:1927
LIVES_LOOP_MODE_NONE
@ LIVES_LOOP_MODE_NONE
no looping
Definition: liblives.hpp:190
_prefs::audio_src
int audio_src
Definition: preferences.h:204
lives_clip_t::frameno
frames_t frameno
Definition: main.h:934
idle_insert_vtrack
boolean idle_insert_vtrack(boolean in_front, ulong id)
Definition: lbindings.c:1264
real_main
int real_main(int argc, char *argv[], pthread_t *gtk_thread, ulong id)
Definition: main.c:4111
mt_track_is_video
boolean mt_track_is_video(lives_mt *mt, int ntrack)
return TRUE if ntrack is a valid video track
Definition: multitrack.c:23042
idle_stop_playback
boolean idle_stop_playback(ulong id)
Definition: lbindings.c:1320
mainwindow::blend_file
int blend_file
background clip details
Definition: mainwindow.h:976
mt_set_autotrans
void mt_set_autotrans(int idx)
Definition: multitrack.c:6080
get_set_list
LiVESList * get_set_list(const char *dir, boolean utf8)
Definition: utils.c:5305
lives_osc_cb_quit
bool lives_osc_cb_quit(void *context, int arglen, const void *vargs, OSCTimeTag when, void *ra)
idle_resync_fps
boolean idle_resync_fps(ulong id)
Definition: lbindings.c:1915
lives_clip_t::signed_endian
uint32_t signed_endian
bitfield
Definition: main.h:909
mainwindow::sep_win
boolean sep_win
Definition: mainwindow.h:761
idle_open_file
boolean idle_open_file(const char *fname, double stime, int frames, ulong id)
Definition: lbindings.c:1413
get_current_mode_for_key
int get_current_mode_for_key(int key)
Definition: lbindings.c:362
idle_save_set
boolean idle_save_set(const char *name, boolean force_append, ulong id)
Definition: lbindings.c:1340
mainwindow::playing_file
int playing_file
which number file we are playing (or -1) [generally mainw->current_file]
Definition: mainwindow.h:943
idle_set_gravity
boolean idle_set_gravity(int grav, ulong id)
Definition: lbindings.c:1518
_prefs::max_modes_per_key
int max_modes_per_key
maximum effect modes per key
Definition: preferences.h:350
idle_set_fullscreen
boolean idle_set_fullscreen(boolean setting, ulong id)
Definition: lbindings.c:1479
mainwindow::files
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
LIVES_LOOP_MODE_CONTINUOUS
@ LIVES_LOOP_MODE_CONTINUOUS
both video and audio loop continuously
Definition: liblives.hpp:191
idle_set_ping_pong
boolean idle_set_ping_pong(boolean setting, ulong id)
Definition: lbindings.c:1505
lives::prefs::currentAudioDir
livesString currentAudioDir(const livesApp &lives)
Definition: liblives.cpp:2221
get_first_fx_matched
int get_first_fx_matched(const char *package, const char *fxname, const char *author, int version)
Definition: lbindings.c:348
mainwindow::pulsed
void * pulsed
pulseaudio player
Definition: mainwindow.h:1463
SEPWIN_TYPE_NON_STICKY
#define SEPWIN_TYPE_NON_STICKY
Definition: preferences.h:187
mainwindow::aframeno
double aframeno
and the audio 'frame' for when we are looping
Definition: mainwindow.h:962
idle_mt_set_track
boolean idle_mt_set_track(int tnum, ulong id)
Definition: lbindings.c:1234
mt_track_is_audio
boolean mt_track_is_audio(lives_mt *mt, int ntrack)
return TRUE if ntrack is a valid backing audio track
Definition: multitrack.c:23048
PREF_AUDIO_OPTS
#define PREF_AUDIO_OPTS
Definition: preferences.h:893
idle_set_fullscreen_sepwin
boolean idle_set_fullscreen_sepwin(boolean setting, ulong id)
Definition: lbindings.c:1492
lives_clip_t::arps
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
Definition: main.h:905
get_event_timecode
LIVES_GLOBAL_INLINE weed_timecode_t get_event_timecode(weed_plant_t *plant)
Definition: events.c:98
LIVES_STATUS_NOTREADY
@ LIVES_STATUS_NOTREADY
application is starting up; not ready
Definition: liblives.hpp:61
lives_interface_mode_t
lives_interface_mode_t
LiVES operation mode.
Definition: liblives.hpp:49
LIVES_FILE_CHOOSER_AUDIO_ONLY
@ LIVES_FILE_CHOOSER_AUDIO_ONLY
file chooser options for single audio file
Definition: liblives.hpp:41
lives_clip_t::unique_id
uint64_t unique_id
this and the handle can be used to uniquely id a file
Definition: main.h:880
lives_clip_t::hsize
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
LIVES_BIGENDIAN
@ LIVES_BIGENDIAN
Definition: liblives.hpp:74
lives_audio_source_t
lives_audio_source_t
Audio sources.
Definition: liblives.hpp:148
LIVES_INTERFACE_MODE_INVALID
@ LIVES_INTERFACE_MODE_INVALID
livesApp instance is invalid
Definition: liblives.hpp:50
idle_set_if_mode
boolean idle_set_if_mode(lives_interface_mode_t mode, ulong id)
Definition: lbindings.c:1662
lives::prefs::isRealtimeAudioPlayer
bool isRealtimeAudioPlayer(lives_audio_player_t player_type)
Definition: liblives.cpp:2261
AUDIO_OPTS_FOLLOW_FPS
#define AUDIO_OPTS_FOLLOW_FPS
Definition: preferences.h:256
get_transition_param
int get_transition_param(weed_plant_t *filter, boolean skip_internal)
Definition: effects-weed.c:8656
idle_select_start
boolean idle_select_start(int cnum, int frame, ulong id)
Definition: lbindings.c:1839
lives::prefs::currentVideoLoadDir
livesString currentVideoLoadDir(const livesApp &lives)
Definition: liblives.cpp:2216
idle_reload_set
boolean idle_reload_set(const char *setname, ulong id)
Definition: lbindings.c:1432
get_track_name
char * get_track_name(lives_mt *mt, int track_num, boolean is_audio)
Definition: multitrack.c:1038
mainwindow::multitrack
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
idle_set_sepwin
boolean idle_set_sepwin(boolean setting, ulong id)
Definition: lbindings.c:1466
mainwindow::go_away
boolean go_away
Definition: mainwindow.h:1614
lives::prefs::setAudioFollowsFPSChanges
bool setAudioFollowsFPSChanges(const livesApp &lives, bool setting)
Definition: liblives.cpp:2294
lives_clip_t::laudio_time
double laudio_time
Definition: main.h:929
mainwindow::current_layouts_map
LiVESList * current_layouts_map
map of all layouts for set
Definition: mainwindow.h:1470
main.h
LIVES_CALLBACK_PRIVATE
@ LIVES_CALLBACK_PRIVATE
for internal use
Definition: liblives.hpp:106
AUD_PLAYER_SOX
#define AUD_PLAYER_SOX
Definition: preferences.h:42
multitrack
lives_mt * multitrack(weed_plant_t *event_list, int orig_file, double fps)
create and return lives_mt struct
Definition: multitrack.c:6448
_prefs::mt_exit_render
boolean mt_exit_render
Definition: preferences.h:275
get_num_mapped_modes_for_key
int get_num_mapped_modes_for_key(int key)
Definition: lbindings.c:357
PREF_MT_EXIT_RENDER
#define PREF_MT_EXIT_RENDER
Definition: preferences.h:1034
mainwindow::fs
boolean fs
Definition: mainwindow.h:762
lives_char_encoding_t
lives_char_encoding_t
Character encoding types.
Definition: liblives.hpp:114
lives::prefs::setSepWinSticky
bool setSepWinSticky(const livesApp &lives, bool setting)
Definition: liblives.cpp:2304
_prefs::sleep_time
int sleep_time
Definition: preferences.h:176
AUDIO_SRC_EXT
#define AUDIO_SRC_EXT
Definition: preferences.h:206
mainw
mainwindow * mainw
Definition: main.c:103
cnum_for_uid
int cnum_for_uid(ulong uid)
Definition: lbindings.c:238
binding_cb
void binding_cb(lives_callback_t cb_type, const char *msgstring, ulong id)
Definition: liblives.cpp:2326
lives_audio_player_t
lives_audio_player_t
Audio players.
Definition: liblives.hpp:158
LIVES_LOOP_MODE_FIT_AUDIO
@ LIVES_LOOP_MODE_FIT_AUDIO
video keeps looping until audio playback finishes
Definition: liblives.hpp:192
idle_map_fx
boolean idle_map_fx(int key, int mode, int idx, ulong id)
Definition: lbindings.c:1544
lives_clip_t::pb_fps
double pb_fps
current playback rate, may vary from fps, can be 0. or negative
Definition: main.h:1007
idle_show_info
boolean idle_show_info(const char *text, boolean blocking, ulong id)
idlefunc hooks
Definition: lbindings.c:1201
idle_reload_layout
boolean idle_reload_layout(const char *lname, ulong id)
Definition: lbindings.c:1773
idle_fx_enable
boolean idle_fx_enable(int key, boolean setting, ulong id)
Definition: lbindings.c:1596
idle_quit
boolean idle_quit(pthread_t *gtk_thread)
Definition: lbindings.c:1329
mainwindow::vid_load_dir
char vid_load_dir[PATH_MAX]
Definition: mainwindow.h:730
LIVES_AUDIO_PLAYER_SOX
@ LIVES_AUDIO_PLAYER_SOX
Audio playback is through Sox.
Definition: liblives.hpp:162
idle_choose_layout
boolean idle_choose_layout(ulong id)
Definition: lbindings.c:1758
lives::prefs::tmpDir
livesString tmpDir(const livesApp &lives)
Definition: liblives.cpp:2226
lives_clip_t::vsize
int vsize
frame height (vertical) in pixels
Definition: main.h:897
lives
Definition: liblives.cpp:57
Boolean
int Boolean
Definition: liblives.cpp:21
normalise_audio
boolean normalise_audio(int fnum, double start, double end, float thresh)
Definition: audio.c:280
lbindings.h
AUD_PLAYER_PULSE
#define AUD_PLAYER_PULSE
Definition: preferences.h:44
lives::prefs::rteKeysVirtual
int rteKeysVirtual(const livesApp &lives)
Definition: liblives.cpp:2269
idle_unmap_effects
boolean idle_unmap_effects(ulong id)
Definition: lbindings.c:1309
AUD_PLAYER_JACK
#define AUD_PLAYER_JACK
Definition: preferences.h:43
get_menu_name
char * get_menu_name(lives_clip_t *sfile, boolean add_setname)
Definition: gui.c:4487
idle_fx_setmode
boolean idle_fx_setmode(int key, int mode, ulong id)
Definition: lbindings.c:1579
LIVES_DIALOG_RESPONSE_NONE
@ LIVES_DIALOG_RESPONSE_NONE
Response not obtained.
Definition: liblives.hpp:132
mainwindow::is_processing
boolean is_processing
states
Definition: mainwindow.h:820
LIVES_GRAVITY_RIGHT
@ LIVES_GRAVITY_RIGHT
inserted blocks gravitate to the right
Definition: liblives.hpp:182
effects-weed.h
idle_choose_file_with_preview
boolean idle_choose_file_with_preview(const char *dirname, const char *title, int preview_type, ulong id)
Definition: lbindings.c:1367
lives::prefs::mtExitRender
bool mtExitRender(const livesApp &lives)
Definition: liblives.cpp:2309
FPS_MAX
#define FPS_MAX
maximum fps we will allow (double)
Definition: main.h:218
mainwindow::currticks
volatile ticks_t currticks
wall clock time, updated whenever lives_get_*_ticks is called
Definition: mainwindow.h:1005
lives::prefs::audioFollowsFPSChanges
bool audioFollowsFPSChanges(const livesApp &lives)
Definition: liblives.cpp:2284
mainwindow::ping_pong
volatile boolean ping_pong
Definition: mainwindow.h:765
idle_choose_set
boolean idle_choose_set(ulong id)
Definition: lbindings.c:1389
LIVES_CHAR_ENCODING_LOCAL8BIT
@ LIVES_CHAR_ENCODING_LOCAL8BIT
8 bit locale file encoding
Definition: liblives.hpp:116
AUDIO_OPTS_FOLLOW_CLIPS
#define AUDIO_OPTS_FOLLOW_CLIPS
Definition: preferences.h:255
lives_clip_t::asampsize
int asampsize
audio sample size in bits (8 or 16)
Definition: main.h:908
lives_filechooser_t
lives_filechooser_t
Filechooser hinting types.
Definition: liblives.hpp:39
repl_workdir
char * repl_workdir(const char *entry, boolean fwd)
Definition: utils.c:3534
ulong
#define ulong
Definition: main.h:178
idle_render_layout
boolean idle_render_layout(boolean with_aud, boolean normalise_aud, ulong id)
Definition: lbindings.c:1806
lives_loop_mode_t
lives_loop_mode_t
Player looping modes (bitmap)
Definition: liblives.hpp:189
idle_remove_block
boolean idle_remove_block(ulong uid, ulong id)
Definition: lbindings.c:1695
LIVES_STATUS_PLAYING
@ LIVES_STATUS_PLAYING
application is playing, only player commands will be responded to
Definition: liblives.hpp:63
lives_clip_t::arate
int arate
current audio playback rate (varies if the clip rate is changed)
Definition: main.h:906
get_clip_for_block
int get_clip_for_block(track_rect *block)
Definition: multitrack.c:23107
FALSE
#define FALSE
Definition: videoplugin.h:60
idle_save_layout
boolean idle_save_layout(const char *lname, ulong id)
Definition: lbindings.c:1789
_prefs::atrans_fx
int atrans_fx
Definition: preferences.h:353
_prefs::sepwin_type
short sepwin_type
Definition: preferences.h:186
LIVES_FILE_CHOOSER_VIDEO_AUDIO
@ LIVES_FILE_CHOOSER_VIDEO_AUDIO
file chooser options for single video or audio file
Definition: liblives.hpp:40
lives_clip_t::achans
int achans
number of audio channels (0, 1 or 2)
Definition: main.h:907
idle_wipe_layout
boolean idle_wipe_layout(boolean force, ulong id)
Definition: lbindings.c:1742
AFORM_BIG_ENDIAN
#define AFORM_BIG_ENDIAN
Definition: main.h:787
is_legal_set_name
boolean is_legal_set_name(const char *set_name, boolean allow_dupes, boolean leeway)
Definition: utils.c:2975
lives_clip_t::end
frames_t end
Definition: main.h:891