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
20extern "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
36static volatile bool spinning;
37static ulong msg_id;
38static char *private_response;
39static pthread_mutex_t spin_mutex = PTHREAD_MUTEX_INITIALIZER;
40static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
41static pthread_cond_t cond_done = PTHREAD_COND_INITIALIZER;
42
43static 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
57namespace lives {
58#ifndef DOXYGEN_SKIP
59typedef struct {
60 ulong id;
61 livesApp *app;
62} livesAppCtx;
63
64static list<livesAppCtx> appMgr;
65
66static 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
76void livesString::setEncoding(lives_char_encoding_t enc) {
77 m_encoding = enc;
78}
79
80lives_char_encoding_t livesString::encoding() {
81 return m_encoding;
82}
83
84livesString 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
131void 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
169livesApp::livesApp() : m_id(0l) {
170 if (appMgr.empty())
171 init(0, NULL);
172}
173
174
175livesApp::livesApp(int argc, char *argv[]) : m_id(0l) {
176 if (appMgr.empty())
177 init(argc, argv);
178}
179
180
181livesApp::~livesApp() {
182 if (!isValid()) return;
183 idle_quit(m_thread);
184}
185
186
187bool livesApp::isValid() const {
188 return this != NULL && m_id != 0l;
189}
190
191
192bool livesApp::isPlaying() const {
193 return status() == LIVES_STATUS_PLAYING;
194}
195
196
197bool livesApp::isReady() const {
198 return status() == LIVES_STATUS_READY;
199}
200
201
202const set &livesApp::getSet() {
203 return *m_set;
204}
205
206
207const player &livesApp::getPlayer() {
208 return *m_player;
209}
210
211
212const multitrack &livesApp::getMultitrack() {
213 return *m_multitrack;
214}
215
216
217ulong 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
235void livesApp::setClosures(closureList cl) {
236 m_closures = cl;
237}
238
239#endif
240
241ulong 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
246ulong 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
251ulong 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
256ulong 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
261bool 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
281lives_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
310livesString 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
339livesString 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
363livesStringList 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
377clip 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
402bool 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
426bool livesApp::deinterlaceOption() {
427 return m_deinterlace;
428}
429
430
431lives_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
438lives_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
460lives_status_t livesApp::status() const {
461 if (!isValid()) return LIVES_STATUS_INVALID;
464 if ((mainw->preview || mainw->event_list != NULL) && mainw->multitrack == NULL) return LIVES_STATUS_PREVIEW;
466 return LIVES_STATUS_READY;
467}
468
469
470bool 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
496closureList &livesApp::closures() {
497 return m_closures;
498}
499
500#endif
501
502void livesApp::invalidate() {
503 m_id = 0l;
504}
505
506
507bool livesApp::interactive() {
508 return mainw->interactive;
509}
510
511
512bool 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
532const effectKeyMap &livesApp::getEffectKeyMap() {
533 return *m_effectKeyMap;
534}
535
536
537#ifndef DOXYGEN_SKIP
538bool 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
558bool 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
578bool 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
601player::player(livesApp *lives) {
602 // make shared ptr
603 m_lives = lives;
604}
605
606
607bool player::isValid() const {
608 return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY;
609}
610
611
612bool player::isPlaying() const {
613 return isValid() && m_lives->isPlaying();
614}
615
616
617bool player::isRecording() const {
618 return isValid() && mainw->record;
619}
620
621
622bool player::play() const {
623 if (!isValid() || !m_lives->isReady()) return false;
624 return start_player();
625}
626
627
628bool 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
651void 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
672void 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
693bool player::sepWin() const {
694 if (!isValid()) return false;
695 return mainw->sep_win;
696}
697
698
699bool player::fullScreen() const {
700 if (!isValid()) return false;
701 return mainw->fs;
702}
703
704
705bool player::setForegroundClip(clip c) const {
706 if (!isPlaying()) return false;
707 return c.switchTo();
708}
709
710
711bool player::setBackgroundClip(clip c) const {
712 if (!isPlaying()) return false;
713 return c.setIsBackground();
714}
715
716
717clip 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
724clip 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
731void 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
752double 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) {
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
771double 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
786double 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
813double 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
836int 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
858double player::elapsedTime() const {
859 if (!isPlaying()) return 0.;
861}
862
863
864double 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
872double 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
894int 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
902lives_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
923lives_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
934bool 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
955bool player::pingPong() const {
956 if (!isValid()) return false;
957 return mainw->ping_pong;
958}
959
960
961bool 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
984set::set(livesApp *lives) {
985 m_lives = lives;
986}
987
988
989bool set::isValid() const {
990 return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY;
991}
992
993
994livesString set::name() const {
995 if (!isValid()) return livesString();
996 return livesString(mainw->set_name, LIVES_CHAR_ENCODING_UTF8);
997}
998
999
1000bool 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
1036unsigned 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
1043clip 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
1051int 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
1064bool 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
1092bool set::save() const {
1093 return save(name());
1094}
1095
1096
1097void 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
1115clip::clip() : m_uid(0l), m_lives(NULL) {};
1116
1117clip::clip(ulong uid, livesApp *lives) {
1118 m_uid = uid;
1119 m_lives = lives;
1120}
1121
1122bool 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
1126int 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
1134int 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
1142int 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
1150double 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
1159double 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
1170int 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
1179int 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
1194double 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
1203int 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
1212int 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
1221bool 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
1230lives_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
1241livesString 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
1251int 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
1260int 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
1269bool 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
1294bool 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
1319bool 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
1344bool 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
1370bool 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
1398effectKeyMap::effectKeyMap(livesApp *lives) {
1399 m_lives = lives;
1400}
1401
1402
1403bool effectKeyMap::isValid() const {
1404 return m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY;
1405}
1406
1407
1408effectKey effectKeyMap::at(int i) const {
1409 return (*this)[i];
1410}
1411
1412
1413size_t effectKeyMap::size() const {
1414 if (!isValid()) return 0;
1415 return (size_t) prefs::rteKeysVirtual(*m_lives);
1416}
1417
1418
1419bool 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
1446effectKey::effectKey() {
1447 m_key = 0;
1448}
1449
1450
1451effectKey::effectKey(livesApp *lives, int key) {
1452 m_lives = lives;
1453 m_key = key;
1454}
1455
1456
1457bool 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
1463int effectKey::key() {
1464 return m_key;
1465}
1466
1467
1468int effectKey::numModes() {
1469 if (!isValid()) return 0;
1471}
1472
1473
1474int effectKey::numMappedModes() {
1475 if (!isValid()) return 0;
1476 return get_num_mapped_modes_for_key(m_key);
1477}
1478
1479
1480int effectKey::currentMode() {
1481 if (!isValid()) return -1;
1482 return get_current_mode_for_key(m_key);
1483}
1484
1485
1486bool effectKey::enabled() {
1487 if (!isValid()) return false;
1488 return get_rte_key_is_enabled(m_key);
1489}
1490
1491
1492int 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
1518bool 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
1543int 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
1577bool 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
1606effect 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
1618effect::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
1626effect::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
1637bool effect::isValid() const {
1638 return (m_idx != -1 && m_lives != NULL && m_lives->isValid() && m_lives->status() != LIVES_STATUS_NOTREADY);
1639}
1640
1641
1642effect::effect() : m_lives(NULL), m_idx(-1) {}
1643
1644effect::effect(livesApp *lives, int idx) : m_lives(lives), m_idx(idx) {}
1645
1646
1649
1650block::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
1656block::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
1667bool 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
1674void block::invalidate() {
1675 m_uid = 0l;
1676}
1677
1678
1679double 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
1686double 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
1694clip 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
1703int 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
1710bool 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
1739bool 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
1771multitrack::multitrack(livesApp *lives) {
1772 m_lives = lives;
1773}
1774
1775
1776bool multitrack::isValid() const {
1777 return m_lives != NULL && m_lives->m_id != 0l && m_lives->status() != LIVES_STATUS_NOTREADY;
1778}
1779
1780
1781bool multitrack::isActive() const {
1782 return (isValid() && mainw->multitrack != NULL);
1783}
1784
1785
1786double multitrack::currentTime() const {
1787 if (!isActive()) return 0.;
1788 return m_lives->m_player->videoPlaybackTime();
1789}
1790
1791
1792double multitrack::setCurrentTime(double time) const {
1793 if (!isActive() || !m_lives->isReady()) return currentTime();
1794 return m_lives->m_player->setPlaybackStartTime(time);
1795}
1796
1797
1798block 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
1826livesString 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
1853livesString 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
1880livesStringList 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
1894bool 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
1920livesString 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
1947livesString 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
1974clip 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
2001effect 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
2010bool 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
2023bool 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
2031int multitrack::currentTrack() const {
2032 if (!isActive()) return 0;
2033 return mainw->multitrack->current_track;
2034}
2035
2036
2037bool 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
2062livesString 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
2075double multitrack::FPS() const {
2076 if (!isActive()) return 0.;
2077 return mainw->multitrack->fps;
2078}
2079
2080
2081bool 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
2106lives_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
2119lives_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
2142lives_insert_mode_t multitrack::insertMode() const {
2143 if (!isActive()) return LIVES_INSERT_MODE_NORMAL;
2144 switch (mainw->multitrack->opts.insert_mode) {
2145 default:
2147 }
2148}
2149
2150
2151lives_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
2174int multitrack::numAudioTracks() const {
2175 if (!isActive()) return 0;
2176 return mainw->multitrack->opts.back_audio_tracks;
2177}
2178
2179
2180int multitrack::numVideoTracks() const {
2181 if (!isActive()) return 0;
2182 return mainw->multitrack->num_video_tracks;
2183}
2184
2185
2186int 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
2215namespace prefs {
2216livesString 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
2221livesString 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
2226livesString 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;
2233 if (::prefs->audio_src == AUDIO_SRC_EXT) return LIVES_AUDIO_SOURCE_EXTERNAL;
2235}
2236
2237bool 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;
2244 if (::prefs->audio_player == AUD_PLAYER_SOX) return LIVES_AUDIO_PLAYER_SOX;
2245 if (::prefs->audio_player == AUD_PLAYER_JACK) return LIVES_AUDIO_PLAYER_JACK;
2246 if (::prefs->audio_player == AUD_PLAYER_PULSE) return LIVES_AUDIO_PLAYER_PULSE;
2248}
2249
2250int 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
2269int rteKeysVirtual(const livesApp &lives) {
2270 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return 0;
2272}
2273
2274double maxFPS(const livesApp &lives) {
2275 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return 0.;
2276 return FPS_MAX;
2277}
2278
2279bool audioFollowsVideoChanges(const livesApp &lives) {
2280 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2282}
2283
2284bool audioFollowsFPSChanges(const livesApp &lives) {
2285 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2287}
2288
2289bool 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
2294bool 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
2299bool sepWinSticky(const livesApp &lives) {
2300 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2302}
2303
2304bool setSepWinSticky(const livesApp &lives, bool setting) {
2305 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2307}
2308
2309bool mtExitRender(const livesApp &lives) {
2310 if (!lives.isValid() || lives.status() == LIVES_STATUS_NOTREADY) return false;
2312}
2313
2314bool 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
2326void 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;
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;
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
boolean normalise_audio(int fnum, double start, double end, float thresh)
Definition: audio.c:280
#define is_realtime_aplayer(ptype)
Definition: audio.h:236
int weed_get_idx_for_hashname(const char *hashname, boolean fullname)
fullname includes author and version
int rte_keymode_get_filter_idx(int key, int mode)
returns filter_class index of key/mode (or -1 if no filter bound)
weed_plant_t * get_weed_filter(int idx)
int get_transition_param(weed_plant_t *filter, boolean skip_internal)
LIVES_GLOBAL_INLINE weed_timecode_t get_event_timecode(weed_plant_t *plant)
Definition: events.c:98
char * get_menu_name(lives_clip_t *sfile, boolean add_setname)
Definition: gui.c:4487
boolean idle_remove_block(ulong uid, ulong id)
Definition: lbindings.c:1695
boolean idle_mt_set_track(int tnum, ulong id)
Definition: lbindings.c:1234
boolean idle_reload_layout(const char *lname, ulong id)
Definition: lbindings.c:1773
boolean idle_set_interactive(boolean setting, ulong id)
Definition: lbindings.c:1453
int get_first_fx_matched(const char *package, const char *fxname, const char *author, int version)
Definition: lbindings.c:348
boolean idle_set_current_audio_time(double time, ulong id)
Definition: lbindings.c:1292
ulong * get_unique_ids(void)
utility functions for liblives /////
Definition: lbindings.c:214
boolean idle_fx_setmode(int key, int mode, ulong id)
Definition: lbindings.c:1579
boolean start_player(void)
Definition: lbindings.c:257
boolean idle_set_loop_mode(int mode, ulong id)
Definition: lbindings.c:1902
boolean idle_select_all(int cnum, ulong id)
Definition: lbindings.c:1823
boolean idle_set_gravity(int grav, ulong id)
Definition: lbindings.c:1518
boolean idle_insert_vtrack(boolean in_front, ulong id)
Definition: lbindings.c:1264
boolean get_rte_key_is_enabled(int key)
Definition: lbindings.c:367
boolean idle_select_start(int cnum, int frame, ulong id)
Definition: lbindings.c:1839
boolean idle_show_info(const char *text, boolean blocking, ulong id)
idlefunc hooks
Definition: lbindings.c:1201
boolean idle_set_current_time(double time, ulong id)
Definition: lbindings.c:1277
boolean idle_set_sepwin(boolean setting, ulong id)
Definition: lbindings.c:1466
boolean idle_insert_block(int clipno, boolean ign_sel, boolean with_audio, ulong id)
Definition: lbindings.c:1677
boolean idle_wipe_layout(boolean force, ulong id)
Definition: lbindings.c:1742
boolean idle_set_current_frame(int frame, boolean bg, ulong id)
Definition: lbindings.c:1888
boolean idle_quit(pthread_t *gtk_thread)
Definition: lbindings.c:1329
int get_current_mode_for_key(int key)
Definition: lbindings.c:362
boolean idle_render_layout(boolean with_aud, boolean normalise_aud, ulong id)
Definition: lbindings.c:1806
boolean idle_switch_clip(int type, int cnum, ulong id)
Definition: lbindings.c:1217
boolean idle_set_pref_int(const char *prefidx, int val, ulong id)
Definition: lbindings.c:1629
boolean idle_move_block(ulong uid, int track, double time, ulong id)
Definition: lbindings.c:1715
boolean idle_set_ping_pong(boolean setting, ulong id)
Definition: lbindings.c:1505
boolean idle_save_layout(const char *lname, ulong id)
Definition: lbindings.c:1789
boolean idle_set_fullscreen_sepwin(boolean setting, ulong id)
Definition: lbindings.c:1492
boolean idle_save_set(const char *name, boolean force_append, ulong id)
Definition: lbindings.c:1340
boolean idle_fx_enable(int key, boolean setting, ulong id)
Definition: lbindings.c:1596
boolean idle_unmap_effects(ulong id)
Definition: lbindings.c:1309
boolean idle_set_insert_mode(int mode, ulong id)
Definition: lbindings.c:1531
boolean idle_set_current_fps(double fps, ulong id)
Definition: lbindings.c:1873
boolean idle_choose_layout(ulong id)
Definition: lbindings.c:1758
boolean idle_choose_set(ulong id)
Definition: lbindings.c:1389
boolean idle_reload_set(const char *setname, ulong id)
Definition: lbindings.c:1432
boolean idle_set_pref_bitmapped(const char *prefidx, int bitfield, boolean val, ulong id)
Definition: lbindings.c:1645
boolean idle_map_fx(int key, int mode, int idx, ulong id)
Definition: lbindings.c:1544
boolean idle_cancel_proc(ulong id)
Definition: lbindings.c:1927
boolean idle_set_track_label(int tnum, const char *label, ulong id)
Definition: lbindings.c:1248
boolean idle_set_set_name(ulong id)
Definition: lbindings.c:1404
boolean idle_resync_fps(ulong id)
Definition: lbindings.c:1915
boolean idle_select_end(int cnum, int frame, ulong id)
Definition: lbindings.c:1856
boolean idle_set_pref_bool(const char *prefidx, boolean val, ulong id)
Definition: lbindings.c:1613
boolean idle_open_file(const char *fname, double stime, int frames, ulong id)
Definition: lbindings.c:1413
boolean idle_stop_playback(ulong id)
Definition: lbindings.c:1320
int cnum_for_uid(ulong uid)
Definition: lbindings.c:238
boolean idle_set_if_mode(lives_interface_mode_t mode, ulong id)
Definition: lbindings.c:1662
int get_num_mapped_modes_for_key(int key)
Definition: lbindings.c:357
boolean idle_unmap_fx(int key, int mode, ulong id)
Definition: lbindings.c:1561
boolean idle_set_fullscreen(boolean setting, ulong id)
Definition: lbindings.c:1479
boolean idle_choose_file_with_preview(const char *dirname, const char *title, int preview_type, ulong id)
Definition: lbindings.c:1367
int Boolean
Definition: liblives.cpp:21
track_rect * find_block_by_uid(lives_mt *mt, ulong uid)
Definition: multitrack.c:23012
bool lives_osc_cb_quit(void *context, int arglen, const void *vargs, OSCTimeTag when, void *ra)
void binding_cb(lives_callback_t cb_type, const char *msgstring, ulong id)
Definition: liblives.cpp:2326
int real_main(int argc, char *argv[], pthread_t *gtk_thread, ulong id)
Definition: main.c:4111
Header file for liblives.
lives_filechooser_t
Filechooser hinting types.
Definition: liblives.hpp:39
@ LIVES_FILE_CHOOSER_AUDIO_ONLY
file chooser options for single audio file
Definition: liblives.hpp:41
@ LIVES_FILE_CHOOSER_VIDEO_AUDIO
file chooser options for single video or audio file
Definition: liblives.hpp:40
lives_endian_t
Endian values.
Definition: liblives.hpp:72
@ LIVES_LITTLEENDIAN
Definition: liblives.hpp:73
@ LIVES_BIGENDIAN
Definition: liblives.hpp:74
lives_interface_mode_t
LiVES operation mode.
Definition: liblives.hpp:49
@ LIVES_INTERFACE_MODE_MULTITRACK
multitrack mode
Definition: liblives.hpp:52
@ LIVES_INTERFACE_MODE_INVALID
livesApp instance is invalid
Definition: liblives.hpp:50
@ LIVES_INTERFACE_MODE_CLIPEDIT
clip editor mode
Definition: liblives.hpp:51
lives_insert_mode_t
Multitrack insert modes.
Definition: liblives.hpp:171
@ LIVES_INSERT_MODE_NORMAL
Definition: liblives.hpp:172
lives_status_t
LiVES operational status.
Definition: liblives.hpp:59
@ LIVES_STATUS_INVALID
livesApp instance is invalid
Definition: liblives.hpp:60
@ LIVES_STATUS_PLAYING
application is playing, only player commands will be responded to
Definition: liblives.hpp:63
@ LIVES_STATUS_NOTREADY
application is starting up; not ready
Definition: liblives.hpp:61
@ LIVES_STATUS_PROCESSING
application is processing, commands will be ignored
Definition: liblives.hpp:64
@ LIVES_STATUS_READY
application is ready for commands
Definition: liblives.hpp:62
@ LIVES_STATUS_PREVIEW
user is previewing an operation, commands will be ignored
Definition: liblives.hpp:65
lives_audio_player_t
Audio players.
Definition: liblives.hpp:158
@ LIVES_AUDIO_PLAYER_SOX
Audio playback is through Sox.
Definition: liblives.hpp:162
@ LIVES_AUDIO_PLAYER_JACK
Audio playback is thorugh Jack.
Definition: liblives.hpp:161
@ LIVES_AUDIO_PLAYER_PULSE
Audio playback is through PulseAudio.
Definition: liblives.hpp:160
@ LIVES_AUDIO_PLAYER_UNKNOWN
Unknown / invalid.
Definition: liblives.hpp:159
lives_callback_t
Callback types.
Definition: liblives.hpp:81
@ LIVES_CALLBACK_APP_QUIT
sent when app quits
Definition: liblives.hpp:92
@ LIVES_CALLBACK_MODE_CHANGED
sent when interface mode changes
Definition: liblives.hpp:101
@ LIVES_CALLBACK_OBJECT_DESTROYED
sent when livesApp object is deleted
Definition: liblives.hpp:103
@ LIVES_CALLBACK_PRIVATE
for internal use
Definition: liblives.hpp:106
lives_gravity_t
Multitrack gravity.
Definition: liblives.hpp:179
@ LIVES_GRAVITY_LEFT
inserted blocks gravitate to the left
Definition: liblives.hpp:181
@ LIVES_GRAVITY_RIGHT
inserted blocks gravitate to the right
Definition: liblives.hpp:182
@ LIVES_GRAVITY_NORMAL
no gravity
Definition: liblives.hpp:180
lives_loop_mode_t
Player looping modes (bitmap)
Definition: liblives.hpp:189
@ LIVES_LOOP_MODE_FIT_AUDIO
video keeps looping until audio playback finishes
Definition: liblives.hpp:192
@ LIVES_LOOP_MODE_CONTINUOUS
both video and audio loop continuously
Definition: liblives.hpp:191
@ LIVES_LOOP_MODE_NONE
no looping
Definition: liblives.hpp:190
lives_char_encoding_t
Character encoding types.
Definition: liblives.hpp:114
@ LIVES_CHAR_ENCODING_LOCAL8BIT
8 bit locale file encoding
Definition: liblives.hpp:116
@ LIVES_CHAR_ENCODING_FILESYSTEM
file system encoding (UTF-8 on windows, local8bit on others)
Definition: liblives.hpp:117
@ LIVES_CHAR_ENCODING_UTF8
UTF-8 char encoding.
Definition: liblives.hpp:115
lives_audio_source_t
Audio sources.
Definition: liblives.hpp:148
@ LIVES_AUDIO_SOURCE_EXTERNAL
Audio source is external to LiVES.
Definition: liblives.hpp:151
@ LIVES_AUDIO_SOURCE_INTERNAL
Audio source is internal to LiVES.
Definition: liblives.hpp:150
@ LIVES_AUDIO_SOURCE_UNKNOWN
Unknown / invalid.
Definition: liblives.hpp:149
lives_dialog_response_t
Dialog response values.
Definition: liblives.hpp:129
@ LIVES_DIALOG_RESPONSE_INVALID
INVALID response.
Definition: liblives.hpp:131
@ LIVES_DIALOG_RESPONSE_NONE
Response not obtained.
Definition: liblives.hpp:132
LIVES_GLOBAL_INLINE uint64_t lives_random(void)
Definition: machinestate.c:58
#define lives_free
Definition: machinestate.h:52
mainwindow * mainw
Definition: main.c:103
#define ulong
Definition: main.h:178
char * repl_workdir(const char *entry, boolean fwd)
Definition: utils.c:3534
#define AFORM_UNSIGNED
Definition: main.h:786
LiVESList * get_set_list(const char *dir, boolean utf8)
Definition: utils.c:5305
#define FPS_MAX
maximum fps we will allow (double)
Definition: main.h:218
#define cfile
Definition: main.h:1833
#define AFORM_BIG_ENDIAN
Definition: main.h:787
boolean is_legal_set_name(const char *set_name, boolean allow_dupes, boolean leeway)
Definition: utils.c:2975
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
Definition: mainwindow.h:37
boolean mt_track_is_audio(lives_mt *mt, int ntrack)
return TRUE if ntrack is a valid backing audio track
Definition: multitrack.c:23048
void mt_set_autotrans(int idx)
Definition: multitrack.c:6080
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
boolean mt_track_is_video(lives_mt *mt, int ntrack)
return TRUE if ntrack is a valid video track
Definition: multitrack.c:23042
lives_mt * multitrack(weed_plant_t *event_list, int orig_file, double fps)
create and return lives_mt struct
Definition: multitrack.c:6448
int get_track_for_block(track_rect *block)
return track number for a given block
Definition: multitrack.c:231
char * get_track_name(lives_mt *mt, int track_num, boolean is_audio)
Definition: multitrack.c:1038
int get_clip_for_block(track_rect *block)
Definition: multitrack.c:23107
@ GRAV_MODE_RIGHT
Definition: multitrack.h:87
@ GRAV_MODE_LEFT
Definition: multitrack.h:86
bool setAudioSource(const livesApp &lives, lives_audio_source_t asrc)
Definition: liblives.cpp:2237
bool isRealtimeAudioPlayer(lives_audio_player_t player_type)
Definition: liblives.cpp:2261
bool audioFollowsVideoChanges(const livesApp &lives)
Definition: liblives.cpp:2279
bool setAudioFollowsVideoChanges(const livesApp &lives, bool setting)
Definition: liblives.cpp:2289
lives_audio_source_t audioSource(const livesApp &lives)
Definition: liblives.cpp:2231
bool setSepWinSticky(const livesApp &lives, bool setting)
Definition: liblives.cpp:2304
bool audioFollowsFPSChanges(const livesApp &lives)
Definition: liblives.cpp:2284
bool setAudioFollowsFPSChanges(const livesApp &lives, bool setting)
Definition: liblives.cpp:2294
livesString currentAudioDir(const livesApp &lives)
Definition: liblives.cpp:2221
lives_audio_player_t audioPlayer(const livesApp &lives)
Definition: liblives.cpp:2242
bool mtExitRender(const livesApp &lives)
Definition: liblives.cpp:2309
int rteKeysVirtual(const livesApp &lives)
Definition: liblives.cpp:2269
livesString currentVideoLoadDir(const livesApp &lives)
Definition: liblives.cpp:2216
double maxFPS(const livesApp &lives)
Definition: liblives.cpp:2274
int audioPlayerRate(const livesApp &lives)
Definition: liblives.cpp:2250
livesString tmpDir(const livesApp &lives)
Definition: liblives.cpp:2226
bool setMtExitRender(const livesApp &lives, bool setting)
Definition: liblives.cpp:2314
bool sepWinSticky(const livesApp &lives)
Definition: liblives.cpp:2299
#define PREF_REC_EXT_AUDIO
Definition: preferences.h:892
_prefs * prefs
Definition: preferences.h:847
#define SEPWIN_TYPE_NON_STICKY
Definition: preferences.h:187
#define AUD_PLAYER_SOX
Definition: preferences.h:42
#define AUDIO_OPTS_FOLLOW_CLIPS
Definition: preferences.h:255
#define SEPWIN_TYPE_STICKY
Definition: preferences.h:188
#define PREF_AUDIO_OPTS
Definition: preferences.h:893
#define PREF_MT_EXIT_RENDER
Definition: preferences.h:1034
#define AUD_PLAYER_NONE
Definition: preferences.h:41
#define AUDIO_OPTS_FOLLOW_FPS
Definition: preferences.h:256
#define AUD_PLAYER_JACK
Definition: preferences.h:43
#define AUDIO_SRC_EXT
Definition: preferences.h:206
#define PREF_SEPWIN_TYPE
Definition: preferences.h:894
#define AUD_PLAYER_PULSE
Definition: preferences.h:44
volatile uint32_t audio_opts
Definition: preferences.h:254
int audio_src
Definition: preferences.h:204
boolean mt_exit_render
Definition: preferences.h:275
short rte_keys_virtual
Definition: preferences.h:223
short sepwin_type
Definition: preferences.h:186
int max_modes_per_key
maximum effect modes per key
Definition: preferences.h:350
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
Definition: main.h:905
frames_t frames
number of video frames
Definition: main.h:890
frames_t end
Definition: main.h:891
int asampsize
audio sample size in bits (8 or 16)
Definition: main.h:908
int vsize
frame height (vertical) in pixels
Definition: main.h:897
int achans
number of audio channels (0, 1 or 2)
Definition: main.h:907
double laudio_time
Definition: main.h:929
uint32_t signed_endian
bitfield
Definition: main.h:909
double pb_fps
current playback rate, may vary from fps, can be 0. or negative
Definition: main.h:1007
uint64_t unique_id
this and the handle can be used to uniquely id a file
Definition: main.h:880
frames_t frameno
Definition: main.h:934
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
int arate
current audio playback rate (varies if the clip rate is changed)
Definition: main.h:906
double fps
Definition: main.h:893
frames_t start
Definition: main.h:891
double aframeno
and the audio 'frame' for when we are looping
Definition: mainwindow.h:962
volatile ticks_t currticks
wall clock time, updated whenever lives_get_*_ticks is called
Definition: mainwindow.h:1005
void * pulsed
pulseaudio player
Definition: mainwindow.h:1463
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
volatile boolean record
Definition: mainwindow.h:794
boolean go_away
Definition: mainwindow.h:1614
volatile boolean loop_cont
Definition: mainwindow.h:764
boolean preview
Definition: mainwindow.h:757
int current_file
Definition: mainwindow.h:727
void * jackd
jack audio player / transport
Definition: mainwindow.h:1453
boolean loop
Definition: mainwindow.h:763
boolean fs
Definition: mainwindow.h:762
int blend_file
background clip details
Definition: mainwindow.h:976
boolean sep_win
Definition: mainwindow.h:761
LiVESList * current_layouts_map
map of all layouts for set
Definition: mainwindow.h:1470
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
volatile boolean ping_pong
Definition: mainwindow.h:765
boolean is_processing
states
Definition: mainwindow.h:820
char set_name[256]
Definition: mainwindow.h:749
char audio_dir[PATH_MAX]
Definition: mainwindow.h:733
int playing_file
which number file we are playing (or -1) [generally mainw->current_file]
Definition: mainwindow.h:943
char vid_load_dir[PATH_MAX]
Definition: mainwindow.h:730
weed_event_t * event_list
current event_list, for recording
Definition: mainwindow.h:803
const char * version(void)
#define TRUE
Definition: videoplugin.h:59
#define FALSE
Definition: videoplugin.h:60
WIDGET_HELPER_GLOBAL_INLINE double lives_ruler_get_value(LiVESRuler *ruler)