22 #include <libOSC/libosc.h>
23 #include <libOSC/OSC-client.h>
29 int real_main(
int argc,
char *argv[], pthread_t *gtk_thread,
ulong id);
31 bool lives_osc_cb_quit(
void *context,
int arglen,
const void *vargs, OSCTimeTag when,
void *ra);
36 static volatile bool spinning;
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;
43 static bool private_cb(lives::_privateInfo *info,
void *data) {
44 if (info->id == msg_id) {
45 private_response = strdup(info->response);
47 pthread_cond_signal(&cond_done);
53 #endif // doxygen_skip
64 static list<livesAppCtx> appMgr;
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;
87 livesString str(L2U8(this->c_str()));
93 livesString str(F2U8(this->c_str()));
101 livesString str(U82F(this->c_str()));
107 livesString str(U82L(this->c_str()));
114 livesString str(U82L(this->c_str()));
120 livesString str(F2U8(this->c_str()));
121 str.assign(U82L(str.c_str()));
131 void livesApp::init(
int argc,
char *oargv[]) {
133 char progname[] =
"lives-exe";
134 if (argc < 0) argc = 0;
137 argv = (
char **)malloc(argc *
sizeof(
char *));
138 argv[0] = strdup(progname);
140 for (
int i = 1; i < argc; i++) {
141 argv[i] = strdup(oargv[i - 1]);
145 livesAppCtx *ctx =
new livesAppCtx;
147 pthread_t *gtk_thread =
new pthread_t;
151 appMgr.push_back(*ctx);
153 m_set =
new set(
this);
154 m_player =
new player(
this);
155 m_effectKeyMap =
new effectKeyMap(
this);
158 m_deinterlace =
false;
160 m_thread = gtk_thread;
169 livesApp::livesApp() : m_id(0l) {
175 livesApp::livesApp(
int argc,
char *argv[]) : m_id(0l) {
181 livesApp::~livesApp() {
182 if (!isValid())
return;
187 bool livesApp::isValid()
const {
188 return this != NULL && m_id != 0l;
192 bool livesApp::isPlaying()
const {
197 bool livesApp::isReady()
const {
202 const set &livesApp::getSet() {
207 const player &livesApp::getPlayer() {
213 return *m_multitrack;
218 closure *cl =
new closure;
220 cl->object = (livesApp *)
this;
221 cl->cb_type = cb_type;
222 cl->func = (callback_f)func;
224 while (pthread_mutex_trylock(&spin_mutex)) {
228 ((livesApp *)
this)->m_closures.push_back(cl);
229 pthread_mutex_unlock(&spin_mutex);
235 void livesApp::setClosures(closureList cl) {
241 ulong livesApp::addCallback(
lives_callback_t cb_type, modeChanged_callback_f func,
void *data)
const {
243 return appendClosure(cb_type, (callback_f)func, data);
248 return appendClosure(cb_type, (callback_f)func, data);
251 ulong livesApp::addCallback(
lives_callback_t cb_type, objectDestroyed_callback_f func,
void *data)
const {
253 return appendClosure(cb_type, (callback_f)func, data);
258 return appendClosure(cb_type, (callback_f)func, data);
261 bool livesApp::removeCallback(
ulong id)
const {
262 while (pthread_mutex_trylock(&spin_mutex)) {
266 closureListIterator it = ((livesApp *)
this)->m_closures.begin();
267 while (it != ((livesApp *)
this)->m_closures.end()) {
268 if ((*it)->id ==
id) {
270 ((livesApp *)
this)->m_closures.erase(it);
271 pthread_mutex_unlock(&spin_mutex);
276 pthread_mutex_unlock(&spin_mutex);
289 pthread_mutex_lock(&cond_mutex);
291 pthread_mutex_unlock(&cond_mutex);
293 removeCallback(cbid);
295 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
296 pthread_mutex_unlock(&cond_mutex);
310 livesString livesApp::chooseFileWithPreview(livesString dirname,
lives_filechooser_t preview_type, livesString title) {
311 livesString emptystr;
317 pthread_mutex_lock(&cond_mutex);
320 preview_type, msg_id)) {
321 pthread_mutex_unlock(&cond_mutex);
323 removeCallback(cbid);
325 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
326 pthread_mutex_unlock(&cond_mutex);
330 m_deinterlace = (bool)atoi(private_response + strlen(private_response) - 2);
339 livesString livesApp::chooseSet() {
340 livesString emptystr;
345 pthread_mutex_lock(&cond_mutex);
347 pthread_mutex_unlock(&cond_mutex);
349 removeCallback(cbid);
351 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
352 pthread_mutex_unlock(&cond_mutex);
363 livesStringList livesApp::availableSets() {
364 livesStringList list;
367 while (slist != NULL) {
372 lives_list_free(setlist);
377 clip livesApp::openFile(livesString fname,
bool with_audio,
double stime,
int frames,
bool deinterlace) {
379 if (fname.empty())
return clip();
385 pthread_mutex_lock(&cond_mutex);
387 pthread_mutex_unlock(&cond_mutex);
389 removeCallback(cbid);
391 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
392 pthread_mutex_unlock(&cond_mutex);
394 cid = strtoul(private_response, NULL, 10);
398 return clip(cid,
this);
402 bool livesApp::reloadSet(livesString setname) {
408 pthread_mutex_lock(&cond_mutex);
410 pthread_mutex_unlock(&cond_mutex);
412 removeCallback(cbid);
415 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
416 pthread_mutex_unlock(&cond_mutex);
418 bool ret = (bool)atoi(private_response);
426 bool livesApp::deinterlaceOption() {
427 return m_deinterlace;
444 pthread_mutex_lock(&cond_mutex);
446 pthread_mutex_unlock(&cond_mutex);
448 removeCallback(cbid);
451 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
452 pthread_mutex_unlock(&cond_mutex);
470 bool livesApp::cancel() {
471 if (!isValid())
return false;
478 pthread_mutex_lock(&cond_mutex);
480 pthread_mutex_unlock(&cond_mutex);
482 removeCallback(cbid);
485 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
486 pthread_mutex_unlock(&cond_mutex);
488 ret = (bool)atoi(private_response);
496 closureList &livesApp::closures() {
502 void livesApp::invalidate() {
507 bool livesApp::interactive() {
508 return mainw->interactive;
512 bool livesApp::setInteractive(
bool setting) {
517 pthread_mutex_lock(&cond_mutex);
519 pthread_mutex_unlock(&cond_mutex);
521 removeCallback(cbid);
523 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
524 pthread_mutex_unlock(&cond_mutex);
532 const effectKeyMap &livesApp::getEffectKeyMap() {
533 return *m_effectKeyMap;
538 bool livesApp::setPref(
const char *prefidx,
bool val)
const {
543 pthread_mutex_lock(&cond_mutex);
545 pthread_mutex_unlock(&cond_mutex);
547 removeCallback(cbid);
550 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
551 pthread_mutex_unlock(&cond_mutex);
558 bool livesApp::setPref(
const char *prefidx,
int val)
const {
563 pthread_mutex_lock(&cond_mutex);
565 pthread_mutex_unlock(&cond_mutex);
567 removeCallback(cbid);
570 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
571 pthread_mutex_unlock(&cond_mutex);
578 bool livesApp::setPref(
const char *prefidx,
int bitfield,
bool val)
const {
583 pthread_mutex_lock(&cond_mutex);
585 pthread_mutex_unlock(&cond_mutex);
587 removeCallback(cbid);
590 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
591 pthread_mutex_unlock(&cond_mutex);
601 player::player(livesApp *
lives) {
607 bool player::isValid()
const {
612 bool player::isPlaying()
const {
613 return isValid() && m_lives->isPlaying();
617 bool player::isRecording()
const {
622 bool player::play()
const {
623 if (!isValid() || !m_lives->isReady())
return false;
628 bool player::stop()
const {
629 if (!isPlaying())
return false;
633 pthread_mutex_lock(&cond_mutex);
635 pthread_mutex_unlock(&cond_mutex);
637 m_lives->removeCallback(cbid);
640 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
641 pthread_mutex_unlock(&cond_mutex);
643 bool ret = atoi(private_response);
651 void player::setSepWin(
bool setting)
const {
652 if (!isValid())
return;
656 pthread_mutex_lock(&cond_mutex);
658 pthread_mutex_unlock(&cond_mutex);
660 m_lives->removeCallback(cbid);
663 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
664 pthread_mutex_unlock(&cond_mutex);
672 void player::setFullScreen(
bool setting)
const {
673 if (!isValid())
return;
677 pthread_mutex_lock(&cond_mutex);
679 pthread_mutex_unlock(&cond_mutex);
681 m_lives->removeCallback(cbid);
684 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
685 pthread_mutex_unlock(&cond_mutex);
693 bool player::sepWin()
const {
694 if (!isValid())
return false;
699 bool player::fullScreen()
const {
700 if (!isValid())
return false;
705 bool player::setForegroundClip(clip c)
const {
706 if (!isPlaying())
return false;
711 bool player::setBackgroundClip(clip c)
const {
712 if (!isPlaying())
return false;
713 return c.setIsBackground();
717 clip player::foregroundClip()
const {
718 if (!isPlaying())
return clip();
719 if (m_lives->m_multitrack->isActive())
return clip();
724 clip player::backgroundClip()
const {
725 if (!isPlaying())
return clip();
726 if (m_lives->m_multitrack->isActive())
return clip();
731 void player::setFS(
bool setting)
const {
732 if (!isValid())
return;
736 pthread_mutex_lock(&cond_mutex);
738 pthread_mutex_unlock(&cond_mutex);
740 m_lives->removeCallback(cbid);
743 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
744 pthread_mutex_unlock(&cond_mutex);
752 double player::videoPlaybackTime(
bool background)
const {
753 if (!isValid())
return 0.;
757 if (!m_lives->m_multitrack->isActive()) {
760 if (!background)
return (
cfile->frameno - 1.) /
cfile->fps;
764 }
else return cfile->pointer_time;
771 double player::audioPlaybackTime()
const {
772 if (!isValid())
return 0.;
776 if (!m_lives->m_multitrack->isActive()) {
779 else return cfile->pointer_time;
786 double player::setAudioPlaybackTime(
double time)
const {
787 if (!isValid())
return 0.;
788 if (!m_lives->isPlaying())
return 0.;
792 if (time < 0. || time >
cfile->laudio_time)
return 0.;
797 pthread_mutex_lock(&cond_mutex);
799 pthread_mutex_unlock(&cond_mutex);
801 m_lives->removeCallback(cbid);
803 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
804 pthread_mutex_unlock(&cond_mutex);
809 return audioPlaybackTime();
813 double player::setPlaybackStartTime(
double time)
const {
814 if (!isValid())
return 0.;
815 if (!m_lives->isReady())
return 0.;
820 pthread_mutex_lock(&cond_mutex);
822 pthread_mutex_unlock(&cond_mutex);
824 m_lives->removeCallback(cbid);
826 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
827 pthread_mutex_unlock(&cond_mutex);
832 return videoPlaybackTime();
836 int player::setVideoPlaybackFrame(
int frame,
bool bg)
const {
837 if (!isValid())
return 0;
842 pthread_mutex_lock(&cond_mutex);
844 pthread_mutex_unlock(&cond_mutex);
846 m_lives->removeCallback(cbid);
848 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
849 pthread_mutex_unlock(&cond_mutex);
854 return videoPlaybackTime();
858 double player::elapsedTime()
const {
859 if (!isPlaying())
return 0.;
864 double player::currentFPS()
const {
865 if (!isValid())
return 0.;
868 return cfile->pb_fps;
872 double player::setCurrentFPS(
double fps)
const {
873 if (!isPlaying())
return 0.;
878 pthread_mutex_lock(&cond_mutex);
880 pthread_mutex_unlock(&cond_mutex);
882 m_lives->removeCallback(cbid);
884 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
885 pthread_mutex_unlock(&cond_mutex);
894 int player::currentAudioRate()
const {
895 if (!isValid())
return 0.;
903 if (!isValid())
return loopMode();
907 pthread_mutex_lock(&cond_mutex);
909 pthread_mutex_unlock(&cond_mutex);
911 m_lives->removeCallback(cbid);
913 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
914 pthread_mutex_unlock(&cond_mutex);
934 bool player::setPingPong(
bool setting)
const {
935 if (!isValid())
return pingPong();
939 pthread_mutex_lock(&cond_mutex);
941 pthread_mutex_unlock(&cond_mutex);
943 m_lives->removeCallback(cbid);
945 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
946 pthread_mutex_unlock(&cond_mutex);
955 bool player::pingPong()
const {
956 if (!isValid())
return false;
961 bool player::resyncFPS()
const {
962 if (!isPlaying())
return false;
966 pthread_mutex_lock(&cond_mutex);
968 pthread_mutex_unlock(&cond_mutex);
970 m_lives->removeCallback(cbid);
972 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
973 pthread_mutex_unlock(&cond_mutex);
984 set::set(livesApp *
lives) {
989 bool set::isValid()
const {
994 livesString set::name()
const {
995 if (!isValid())
return livesString();
1000 bool set::setName(livesString name)
const {
1001 if (!isValid())
return false;
1003 if (numClips() == 0)
return false;
1005 if (!name.empty()) {
1018 pthread_mutex_lock(&cond_mutex);
1020 pthread_mutex_unlock(&cond_mutex);
1022 m_lives->removeCallback(cbid);
1025 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1026 pthread_mutex_unlock(&cond_mutex);
1028 bool ret = (bool)atoi(private_response);
1036 unsigned int set::numClips()
const {
1037 if (!isValid())
return 0;
1038 (
const_cast<set *
>(
this))->update_clip_list();
1039 return m_clips.size();
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);
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();
1057 for (i = 0; i < (int)m_clips.size(); i++) {
1058 if (m_clips[i] == c.m_uid)
return i;
1064 bool set::save(livesString name,
bool force_append)
const {
1065 if (!isValid())
return FALSE;
1075 pthread_mutex_lock(&cond_mutex);
1077 pthread_mutex_unlock(&cond_mutex);
1079 m_lives->removeCallback(cbid);
1081 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1082 pthread_mutex_unlock(&cond_mutex);
1084 ret = (bool)(atoi(private_response));
1092 bool set::save()
const {
1093 return save(name());
1097 void set::update_clip_list() {
1098 clipListIterator it = m_clips.begin();
1099 while (it != m_clips.end()) {
1100 it = m_clips.erase(it);
1105 for (
int i = 0; ids[i] != 0l; i++) {
1106 m_clips.push_back(ids[i]);
1115 clip::clip() : m_uid(0l), m_lives(NULL) {};
1122 bool clip::isValid()
const {
1126 int clip::frames() {
1142 int clip::height() {
1150 double clip::FPS() {
1159 double clip::playbackFPS() {
1161 if (!m_lives->m_multitrack->isActive()) {
1164 }
else return m_lives->m_multitrack->FPS();
1170 int clip::audioRate() {
1179 int clip::playbackAudioRate() {
1182 if (!m_lives->m_multitrack->isActive()) {
1184 if (cnum > -1 &&
mainw->
files[cnum] != NULL) {
1194 double clip::audioLength() {
1203 int clip::audioChannels() {
1212 int clip::audioSampleSize() {
1221 bool clip::audioSigned() {
1233 if (cnum > -1 &&
mainw->
files[cnum] != NULL) {
1241 livesString clip::name() {
1247 return livesString();
1251 int clip::selectionStart() {
1260 int clip::selectionEnd() {
1269 bool clip::selectAll() {
1276 pthread_mutex_lock(&cond_mutex);
1278 pthread_mutex_unlock(&cond_mutex);
1280 m_lives->removeCallback(cbid);
1283 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1284 pthread_mutex_unlock(&cond_mutex);
1286 bool ret = (bool)atoi(private_response);
1294 bool clip::setSelectionStart(
unsigned int frame) {
1295 if (!isValid())
return false;
1301 pthread_mutex_lock(&cond_mutex);
1303 pthread_mutex_unlock(&cond_mutex);
1305 m_lives->removeCallback(cbid);
1308 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1309 pthread_mutex_unlock(&cond_mutex);
1311 bool ret = (bool)atoi(private_response);
1319 bool clip::setSelectionEnd(
unsigned int frame) {
1320 if (!isValid())
return false;
1326 pthread_mutex_lock(&cond_mutex);
1328 pthread_mutex_unlock(&cond_mutex);
1330 m_lives->removeCallback(cbid);
1333 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1334 pthread_mutex_unlock(&cond_mutex);
1336 bool ret = (bool)atoi(private_response);
1344 bool clip::switchTo() {
1345 if (!isValid())
return false;
1346 if (m_lives->m_multitrack->isActive())
return false;
1352 pthread_mutex_lock(&cond_mutex);
1354 pthread_mutex_unlock(&cond_mutex);
1356 m_lives->removeCallback(cbid);
1359 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1360 pthread_mutex_unlock(&cond_mutex);
1362 bool ret = (bool)atoi(private_response);
1370 bool clip::setIsBackground() {
1371 if (!isValid())
return false;
1372 if (m_lives->m_multitrack->isActive())
return false;
1378 pthread_mutex_lock(&cond_mutex);
1380 pthread_mutex_unlock(&cond_mutex);
1382 m_lives->removeCallback(cbid);
1385 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1386 pthread_mutex_unlock(&cond_mutex);
1388 bool ret = (bool)atoi(private_response);
1398 effectKeyMap::effectKeyMap(livesApp *
lives) {
1403 bool effectKeyMap::isValid()
const {
1408 effectKey effectKeyMap::at(
int i)
const {
1413 size_t effectKeyMap::size()
const {
1414 if (!isValid())
return 0;
1419 bool effectKeyMap::clear()
const {
1420 if (!isValid())
return false;
1425 pthread_mutex_lock(&cond_mutex);
1427 pthread_mutex_unlock(&cond_mutex);
1429 m_lives->removeCallback(cbid);
1432 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1433 pthread_mutex_unlock(&cond_mutex);
1435 bool ret = (bool)atoi(private_response);
1446 effectKey::effectKey() {
1451 effectKey::effectKey(livesApp *
lives,
int key) {
1457 bool effectKey::isValid()
const {
1463 int effectKey::key() {
1468 int effectKey::numModes() {
1469 if (!isValid())
return 0;
1474 int effectKey::numMappedModes() {
1475 if (!isValid())
return 0;
1480 int effectKey::currentMode() {
1481 if (!isValid())
return -1;
1486 bool effectKey::enabled() {
1487 if (!isValid())
return false;
1492 int effectKey::setCurrentMode(
int new_mode) {
1493 if (!isValid())
return -1;
1494 if (new_mode < 0 || new_mode >= numMappedModes())
return currentMode();
1496 if (new_mode == currentMode())
return currentMode();
1502 pthread_mutex_lock(&cond_mutex);
1504 pthread_mutex_unlock(&cond_mutex);
1506 m_lives->removeCallback(cbid);
1507 return currentMode();
1509 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1510 pthread_mutex_unlock(&cond_mutex);
1514 return currentMode();
1518 bool effectKey::setEnabled(
bool setting) {
1519 if (!isValid())
return false;
1525 pthread_mutex_lock(&cond_mutex);
1528 m_lives->removeCallback(cbid);
1531 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1532 pthread_mutex_unlock(&cond_mutex);
1543 int effectKey::appendMapping(effect fx) {
1544 if (!isValid())
return -1;
1546 if (!fx.isValid())
return -1;
1548 if (fx.m_lives != m_lives)
return -1;
1550 if (!m_lives->isReady() && !m_lives->isPlaying())
return -1;
1552 int mode = numMappedModes();
1553 if (mode == numModes())
return -1;
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);
1563 m_lives->removeCallback(cbid);
1566 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1567 pthread_mutex_unlock(&cond_mutex);
1569 bool ret = (bool)atoi(private_response);
1571 if (ret)
return mode;
1577 bool effectKey::removeMapping(
int mode) {
1578 if (!isValid())
return false;
1580 if (!m_lives->isReady() && !m_lives->isPlaying())
return false;
1582 if (mode >= numMappedModes())
return false;
1588 pthread_mutex_lock(&cond_mutex);
1590 pthread_mutex_unlock(&cond_mutex);
1592 m_lives->removeCallback(cbid);
1595 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1596 pthread_mutex_unlock(&cond_mutex);
1598 bool ret = (bool)atoi(private_response);
1606 effect effectKey::at(
int mode) {
1608 if (!isValid())
return e;
1610 if (idx == -1)
return e;
1611 e = effect(m_lives, idx);
1618 effect::effect(
const livesApp &
lives, livesString hashname,
bool match_full) {
1620 m_lives = (livesApp *)&
lives;
1626 effect::effect(
const livesApp &
lives, livesString package, livesString fxname, livesString author,
int version) {
1628 m_lives = (livesApp *)&
lives;
1637 bool effect::isValid()
const {
1638 return (m_idx != -1 && m_lives != NULL && m_lives->isValid() && m_lives->status() !=
LIVES_STATUS_NOTREADY);
1642 effect::effect() : m_lives(NULL), m_idx(-1) {}
1644 effect::effect(livesApp *
lives,
int idx) : m_lives(
lives), m_idx(idx) {}
1651 if (m == NULL) m_lives = NULL;
1652 else m_lives = m->m_lives;
1656 block::block(
multitrack m,
int track,
double time) {
1657 m_lives = m.m_lives;
1658 if (!m.isActive()) m_uid = 0l;
1661 if (tr == NULL) m_uid = 0l;
1662 else m_uid = tr->uid;
1667 bool block::isValid()
const {
1668 if (m_lives == NULL || !m_lives->isValid() || !m_lives->m_multitrack->isActive() || m_uid == 0l ||
1674 void block::invalidate() {
1679 double block::startTime() {
1681 if (tr == NULL)
return -1.;
1686 double block::length() {
1688 if (tr == NULL)
return -1.;
1694 clip block::clipSource() {
1696 if (tr == NULL)
return clip();
1698 if (cnum == -1)
return clip();
1703 int block::track() {
1705 if (tr == NULL)
return 0;
1710 bool block::remove() {
1711 if (!isValid())
return false;
1712 if (!m_lives->isReady())
return false;
1715 if (tr == NULL)
return false;
1720 pthread_mutex_lock(&cond_mutex);
1722 pthread_mutex_unlock(&cond_mutex);
1724 m_lives->removeCallback(cbid);
1727 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1728 pthread_mutex_unlock(&cond_mutex);
1730 bool ret = (bool)atoi(private_response);
1732 if (ret) invalidate();
1739 bool block::moveTo(
int track,
double time) {
1740 if (!isValid())
return false;
1741 if (!m_lives->isReady())
return false;
1744 if (tr == NULL)
return false;
1749 pthread_mutex_lock(&cond_mutex);
1751 pthread_mutex_unlock(&cond_mutex);
1753 m_lives->removeCallback(cbid);
1756 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1757 pthread_mutex_unlock(&cond_mutex);
1759 bool ret = (bool)atoi(private_response);
1761 if (ret) invalidate();
1776 bool multitrack::isValid()
const {
1781 bool multitrack::isActive()
const {
1786 double multitrack::currentTime()
const {
1787 if (!isActive())
return 0.;
1788 return m_lives->m_player->videoPlaybackTime();
1792 double multitrack::setCurrentTime(
double time)
const {
1793 if (!isActive() || !m_lives->isReady())
return currentTime();
1794 return m_lives->m_player->setPlaybackStartTime(time);
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();
1808 pthread_mutex_lock(&cond_mutex);
1810 pthread_mutex_unlock(&cond_mutex);
1812 m_lives->removeCallback(cbid);
1815 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1816 pthread_mutex_unlock(&cond_mutex);
1818 ulong uid = strtoul(private_response, NULL, 10);
1820 return block(
const_cast<multitrack *
>(
this), uid);
1826 livesString multitrack::wipeLayout(
bool force)
const {
1827 livesString emptystr;
1828 if (!isActive())
return emptystr;
1829 if (!m_lives->isReady())
return emptystr;
1835 pthread_mutex_lock(&cond_mutex);
1837 pthread_mutex_unlock(&cond_mutex);
1839 m_lives->removeCallback(cbid);
1842 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1843 pthread_mutex_unlock(&cond_mutex);
1853 livesString multitrack::chooseLayout()
const {
1854 livesString emptystr;
1855 if (!isActive())
return emptystr;
1856 if (!m_lives->isReady())
return emptystr;
1862 pthread_mutex_lock(&cond_mutex);
1864 pthread_mutex_unlock(&cond_mutex);
1866 m_lives->removeCallback(cbid);
1869 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1870 pthread_mutex_unlock(&cond_mutex);
1880 livesStringList multitrack::availableLayouts()
const {
1881 livesStringList list;
1882 if (!isValid())
return list;
1884 while (layoutlist != NULL) {
1888 layoutlist = layoutlist->next;
1894 bool multitrack::reloadLayout(livesString layoutname)
const {
1895 if (!isActive())
return false;
1896 if (!m_lives->isReady())
return false;
1902 pthread_mutex_lock(&cond_mutex);
1904 pthread_mutex_unlock(&cond_mutex);
1906 m_lives->removeCallback(cbid);
1909 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1910 pthread_mutex_unlock(&cond_mutex);
1912 bool ret = (bool)atoi(private_response);
1920 livesString multitrack::saveLayout(livesString name)
const {
1921 livesString emptystr;
1922 if (!isActive())
return emptystr;
1923 if (!m_lives->isReady())
return emptystr;
1929 pthread_mutex_lock(&cond_mutex);
1931 pthread_mutex_unlock(&cond_mutex);
1933 m_lives->removeCallback(cbid);
1936 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1937 pthread_mutex_unlock(&cond_mutex);
1939 char *lname = strdup(private_response);
1947 livesString multitrack::saveLayout()
const {
1948 livesString emptystr;
1949 if (!isActive())
return emptystr;
1950 if (!m_lives->isReady())
return emptystr;
1956 pthread_mutex_lock(&cond_mutex);
1958 pthread_mutex_unlock(&cond_mutex);
1960 m_lives->removeCallback(cbid);
1963 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1964 pthread_mutex_unlock(&cond_mutex);
1966 char *lname = strdup(private_response);
1974 clip multitrack::render(
bool with_audio,
bool normalise_audio)
const {
1976 if (!isActive())
return c;
1977 if (!m_lives->isReady())
return c;
1983 pthread_mutex_lock(&cond_mutex);
1985 pthread_mutex_unlock(&cond_mutex);
1987 m_lives->removeCallback(cbid);
1990 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
1991 pthread_mutex_unlock(&cond_mutex);
1993 ulong uid = strtoul(private_response, NULL, 10);
1994 c = clip(uid, m_lives);
2001 effect multitrack::autoTransition()
const {
2010 bool multitrack::setAutoTransition(effect autotrans)
const {
2011 if (!m_lives->isValid())
return false;
2012 if (!autotrans.isValid())
return disableAutoTransition();
2023 bool multitrack::disableAutoTransition()
const {
2024 if (!m_lives->isValid())
return false;
2031 int multitrack::currentTrack()
const {
2032 if (!isActive())
return 0;
2037 bool multitrack::setCurrentTrack(
int track)
const {
2039 if (!isActive())
return false;
2044 pthread_mutex_lock(&cond_mutex);
2046 pthread_mutex_unlock(&cond_mutex);
2048 m_lives->removeCallback(cbid);
2050 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2051 pthread_mutex_unlock(&cond_mutex);
2053 bool ret = (bool)(atoi(private_response));
2062 livesString multitrack::trackLabel(
int track)
const {
2063 livesString emptystr;
2064 if (!isActive())
return emptystr;
2075 double multitrack::FPS()
const {
2076 if (!isActive())
return 0.;
2081 bool multitrack::setTrackLabel(
int track, livesString label)
const {
2083 if (!isActive())
return false;
2088 pthread_mutex_lock(&cond_mutex);
2090 pthread_mutex_unlock(&cond_mutex);
2092 m_lives->removeCallback(cbid);
2094 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2095 pthread_mutex_unlock(&cond_mutex);
2097 bool ret = (bool)(atoi(private_response));
2121 if (!isActive())
return gravity();
2126 pthread_mutex_lock(&cond_mutex);
2128 pthread_mutex_unlock(&cond_mutex);
2130 m_lives->removeCallback(cbid);
2132 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2133 pthread_mutex_unlock(&cond_mutex);
2153 if (!isActive())
return insertMode();
2158 pthread_mutex_lock(&cond_mutex);
2160 pthread_mutex_unlock(&cond_mutex);
2162 m_lives->removeCallback(cbid);
2164 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2165 pthread_mutex_unlock(&cond_mutex);
2170 return insertMode();
2174 int multitrack::numAudioTracks()
const {
2175 if (!isActive())
return 0;
2180 int multitrack::numVideoTracks()
const {
2181 if (!isActive())
return 0;
2186 int multitrack::addVideoTrack(
bool in_front)
const {
2187 if (!isActive())
return -1;
2188 if (m_lives->isReady())
return -1.;
2193 pthread_mutex_lock(&cond_mutex);
2195 pthread_mutex_unlock(&cond_mutex);
2197 m_lives->removeCallback(cbid);
2199 while (spinning) pthread_cond_wait(&cond_done, &cond_mutex);
2200 pthread_mutex_unlock(&cond_mutex);
2202 int tnum = atoi(private_response);
2238 if (!
lives.isReady())
return false;
2255 #ifdef HAVE_PULSE_AUDIO
2324 #ifndef DOXYGEN_SKIP
2328 lives::livesApp *lapp;
2331 else lapp = lives::find_instance_for_id(
id);
2333 if (lapp == NULL)
return;
2335 pthread_mutex_lock(&spin_mutex);
2337 lives::closureList cl = lapp->closures();
2339 lives::closureListIterator it = cl.begin();
2340 while (it != cl.end()) {
2341 if ((*it)->cb_type == cb_type) {
2344 lives::modeChangedInfo info;
2346 lives::modeChanged_callback_f fn = (lives::modeChanged_callback_f)((*it)->func);
2347 ret = (fn)((*it)->object, &info, (*it)->data);
2352 lives::appQuitInfo info;
2353 info.signum = atoi(msgstring);
2354 lives::appQuit_callback_f fn = (lives::appQuit_callback_f)((*it)->func);
2356 ret = (fn)((*it)->object, &info, (*it)->data);
2361 lives::objectDestroyed_callback_f fn = (lives::objectDestroyed_callback_f)((*it)->func);
2362 ret = (fn)((*it)->object, (*it)->data);
2367 lives::_privateInfo info;
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);
2382 lapp->setClosures(cl);
2389 pthread_mutex_unlock(&spin_mutex);
2392 #endif // doxygen_skip