static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr)
{
- // detect if the producer has finished playing. Is there a better way to do it ?
+ // detect if the producer has finished playing. Is there a better way to do it?
if (self->m_isBlocked) return;
if (mlt_properties_get_double(MLT_FRAME_PROPERTIES(frame_ptr), "_speed") == 0.0) {
self->emitConsumerStopped();
}
}
-Render::Render(const QString & rendererName, int winid, int extid, QWidget *parent): QObject(parent), m_name(rendererName), m_mltConsumer(NULL), m_mltProducer(NULL), m_mltTextProducer(NULL), m_winid(winid), m_externalwinid(extid), m_framePosition(0), m_isBlocked(true), m_blackClip(NULL), m_isSplitView(false), m_isZoneMode(false), m_isLoopMode(false)
+Render::Render(const QString & rendererName, int winid, int /* extid */, QWidget *parent) :
+ QObject(parent),
+ m_isBlocked(true),
+ m_name(rendererName),
+ m_mltConsumer(NULL),
+ m_mltProducer(NULL),
+ m_framePosition(0),
+ m_isZoneMode(false),
+ m_isLoopMode(false),
+ m_isSplitView(false),
+ m_blackClip(NULL),
+ m_winid(winid)
{
kDebug() << "////////// USING PROFILE: " << (char*)KdenliveSettings::current_profile().toUtf8().data();
- refreshTimer = new QTimer(this);
- connect(refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
+ m_refreshTimer = new QTimer(this);
+ connect(m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
/*if (rendererName == "project") m_monitorId = 10000;
else m_monitorId = 10001;*/
- osdTimer = new QTimer(this);
- connect(osdTimer, SIGNAL(timeout()), this, SLOT(slotOsdTimeout()));
-
- m_osdProfile = KStandardDirs::locate("data", "kdenlive/profiles/metadata.properties");
+ m_osdTimer = new QTimer(this);
+ connect(m_osdTimer, SIGNAL(timeout()), this, SLOT(slotOsdTimeout()));
buildConsumer();
void Render::closeMlt()
{
- delete osdTimer;
- delete refreshTimer;
- if (m_mltConsumer)
- delete m_mltConsumer;
- if (m_mltProducer)
- delete m_mltProducer;
- if (m_blackClip) delete m_blackClip;
+ delete m_osdTimer;
+ delete m_refreshTimer;
+ delete m_mltConsumer;
+ delete m_mltProducer;
+ delete m_blackClip;
//delete m_osdInfo;
}
m_activeProfile = KdenliveSettings::current_profile();
tmp = decodedString(m_activeProfile);
setenv("MLT_PROFILE", tmp, 1);
- if (m_blackClip) delete m_blackClip;
+ delete m_blackClip;
m_blackClip = NULL;
m_mltProfile = new Mlt::Profile(tmp);
m_mltConsumer->set("resize", 1);
m_mltConsumer->set("window_id", m_winid);
m_mltConsumer->set("terminate_on_pause", 1);
- m_mltConsumer->set("window_background", decodedString(KdenliveSettings::window_background().name()));
+ tmp = decodedString(KdenliveSettings::window_background().name());
+ m_mltConsumer->set("window_background", tmp);
+ delete [] tmp;
+ // FIXME: the event object returned by the listen gets leaked...
m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
m_mltConsumer->set("rescale", "nearest");
if (producer == NULL || producer->is_blank() || !producer->is_valid()) {
kDebug() << " / / / / / / / / ERROR / / / / // CANNOT LOAD PRODUCER: ";
- emit removeInvalidClip(clipId);
+ emit removeInvalidClip(clipId, replaceProducer);
+ delete producer;
return;
}
/*if (context->duration == AV_NOPTS_VALUE) {
kDebug() << " / / / / / / / /ERROR / / / CLIP HAS UNKNOWN DURATION";
emit removeInvalidClip(clipId);
+ delete producer;
return;
}*/
// Get the video_index
emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap, replaceProducer);
kDebug() << "REquested fuile info for: " << url.path();
- if (frame) delete frame;
- //if (producer) delete producer;
+ delete frame;
+ // FIXME: should delete this to avoid a leak...
+ //delete producer;
}
{
if (m_winid == -1) return;
m_isBlocked = true;
+ qDeleteAll(m_slowmotionProducers.values());
m_slowmotionProducers.clear();
//kWarning() << "////// RENDER, SET SCENE LIST: " << playlist;
blockSignals(true);
char *tmp = decodedString(playlist);
m_mltProducer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
- delete[] tmp;
if (!m_mltProducer || !m_mltProducer->is_valid()) {
kDebug() << " WARNING - - - - -INVALID PLAYLIST: " << tmp;
+ m_mltProducer = m_blackClip->cut(0, 50);
}
+ delete[] tmp;
+
m_mltProducer->optimise();
/*if (KdenliveSettings::osdtimecode()) {
}
m_isBlocked = false;
blockSignals(false);
+ emit refreshDocumentProducers();
//kDebug()<<"// SETSCN LST, POS: "<<position;
//if (position != 0) emit rendererPosition(position);
}
/*
if (m_mltConsumer->start() == -1) {
KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
+ delete m_mltConsumer;
m_mltConsumer = NULL;
}
else {
if (m_mltProducer->attach(*m_osdInfo) == 1) kDebug()<<"////// error attaching filter";
}*/
refresh();
- osdTimer->setSingleShot(2500);
+ m_osdTimer->setSingleShot(2500);
}
void Render::slotOsdTimeout()
kDebug() << "----- MONITOR: " << m_name << " WAS STOPPED";
if (m_mltConsumer->start() == -1) {
KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
+ delete m_mltConsumer;
m_mltConsumer = NULL;
return;
} else {
void Render::askForRefresh()
{
// Use a Timer so that we don't refresh too much
- refreshTimer->start(200);
+ m_refreshTimer->start(200);
}
void Render::doRefresh()
{
if (!m_mltProducer || m_isBlocked)
return;
- refreshTimer->stop();
+ m_refreshTimer->stop();
if (m_mltConsumer) {
m_mltConsumer->set("refresh", 1);
}
Mlt::Tractor tractor(service);
int trackNb = tractor.count();
- double duration = 0;
- double trackDuration;
+ int duration = 0;
+ int trackDuration;
if (trackNb == 1) {
Mlt::Producer trackProducer(tractor.track(0));
duration = trackProducer.get_playtime() - 1;
m_mltProducer->set("out", duration);
- emit durationChanged((int) duration);
+ emit durationChanged(duration);
return;
}
while (trackNb > 1) {
}
Mlt::Producer blackTrackProducer(tractor.track(0));
- double blackDuration = blackTrackProducer.get_playtime() - 1;
+ int blackDuration = blackTrackProducer.get_playtime() - 1;
if (blackDuration != duration) {
Mlt::Playlist blackTrackPlaylist((mlt_playlist) blackTrackProducer.get_service());
blackTrackPlaylist.clear();
- int dur = (int)duration;
+ int dur = duration;
while (dur > 14000) {
blackTrackPlaylist.append(*m_blackClip, 0, 13999);
dur = dur - 14000;
blackTrackPlaylist.append(*m_blackClip, 0, dur);
}
m_mltProducer->set("out", duration);
- emit durationChanged((int)duration);
+ emit durationChanged(duration);
}
}
int ct = 0;
Mlt::Filter *filter = clipService.filter(ct);
while (filter) {
- if (filter->is_valid() && filter->get("kdenlive_id") != "") {
+ // Only duplicate Kdenlive filters, and skip the fade in effects
+ if (filter->is_valid() && strcmp(filter->get("kdenlive_id"), "") && strcmp(filter->get("kdenlive_id"), "fadein") && strcmp(filter->get("kdenlive_id"), "fade_from_black")) {
// looks like there is no easy way to duplicate a filter,
// so we will create a new one and duplicate its properties
Mlt::Filter *dup = new Mlt::Filter(*m_mltProfile, filter->get("mlt_service"));
int ct = 0;
Mlt::Filter *filter = clipService.filter(ct);
while (filter) {
- if ((index == "-1" && filter->get("kdenlive_id") != "") || filter->get("kdenlive_ix") == index) {// && filter->get("kdenlive_id") == id) {
+ if ((index == "-1" && strcmp(filter->get("kdenlive_id"), "")) || filter->get("kdenlive_ix") == index) {// && filter->get("kdenlive_id") == id) {
if (clipService.detach(*filter) == 0) success = true;
kDebug() << " / / / DLEETED EFFECT: " << ct;
} else if (updateIndex) {
kDebug() << "////// LOOKING FOR CLIP TO MOVE, INDEX: " << clipIndex;
bool checkLength = false;
if (endTrack == startTrack) {
- //mlt_service_lock(service.get_service());
Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer.is_blank()) {
// error, destination is not empty
+ if (!trackPlaylist.is_blank_at(moveEnd)) trackPlaylist.insert_at(moveStart, clipProducer, 1);
//int ix = trackPlaylist.get_clip_index_at(moveEnd);
kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
mlt_service_unlock(m_mltConsumer->get_service());
QString currentid = clipProducer.parent().get("id");
if (serv == "framebuffer" || currentid.endsWith("_video")) {
clip = &clipProducer;
- } else clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
+ } else {
+ if (prod == NULL) {
+ // Special case: prod is null when using placeholder clips.
+ // in that case, use the producer existing in playlist. Note that
+ // it will bypass the one producer per track logic and might cause
+ // Sound cracks if clip is moved so that it overlaps another copy of itself
+ clip = clipProducer.cut(clipProducer.get_in(), clipProducer.get_out());
+ } else clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
+ }
// move all effects to the correct producer
Mlt::Service clipService(clipProducer.get_service());
int trackNb = tractor.count();
for (int t = 1; t < trackNb; t++) {
- Mlt::Producer trackProducer(tractor.track(t));
+ Mlt::Producer *tt = tractor.track(t);
+ Mlt::Producer trackProducer(tt);
+ delete tt;
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipNb = trackPlaylist.count();
//kDebug() << "// PARSING SCENE TRACK: " << t << ", CLIPS: " << clipNb;
for (int i = 0; i < clipNb; i++) {
- Mlt::Producer *nprod = new Mlt::Producer(trackPlaylist.get_clip(i)->get_parent());
- if (nprod && !nprod->is_blank() && !ids.contains(nprod->get("id"))) {
- ids.append(nprod->get("id"));
- prods.append(nprod);
+ Mlt::Producer *c = trackPlaylist.get_clip(i);
+ Mlt::Producer *nprod = new Mlt::Producer(c->get_parent());
+ if (nprod) {
+ if (!nprod->is_blank() && !ids.contains(nprod->get("id"))) {
+ ids.append(nprod->get("id"));
+ prods.append(nprod);
+ } else delete nprod;
}
+ delete c;
}
}
return prods;
int trackNb = tractor.count();
for (int t = 1; t < trackNb; t++) {
- Mlt::Producer trackProducer(tractor.track(t));
+ Mlt::Producer *tt = tractor.track(t);
+ Mlt::Producer trackProducer(tt);
+ delete tt;
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
int clipNb = trackPlaylist.count();
for (int i = 0; i < clipNb; i++) {
- Mlt::Producer *nprod = new Mlt::Producer(trackPlaylist.get_clip(i)->get_parent());
- if (nprod && !nprod->is_blank()) {
+ Mlt::Producer *c = trackPlaylist.get_clip(i);
+ Mlt::Producer *nprod = new Mlt::Producer(c->get_parent());
+ if (nprod) {
QString id = nprod->get("id");
- if (id.startsWith("slowmotion:")) {
+ if (id.startsWith("slowmotion:") && !nprod->is_blank()) {
// this is a slowmotion producer, add it to the list
QString url = QString::fromUtf8(nprod->get("resource"));
if (!m_slowmotionProducers.contains(url)) {
m_slowmotionProducers.insert(url, nprod);
}
- }
+ } else delete nprod;
}
+ delete c;
}
}
}
Mlt::Tractor tractor(service);
- Mlt::Playlist playlist;// = new Mlt::Playlist();
+ Mlt::Playlist playlist;
int ct = tractor.count();
- // kDebug() << "// TRACK INSERT: " << ix << ", MAX: " << ct;
+ if (ix > ct) {
+ kDebug() << "// ERROR, TRYING TO insert TRACK " << ix << ", max: " << ct;
+ ix = ct;
+ }
+
int pos = ix;
if (pos < ct) {
Mlt::Producer *prodToMove = new Mlt::Producer(tractor.track(pos));
tractor.removeChild(track);
setSceneList(doc.toString(), m_framePosition);
mltCheckLength();
- return;
-
- blockSignals(true);
- m_isBlocked = true;
-
- m_mltConsumer->set("refresh", 0);
- mlt_service_lock(m_mltConsumer->get_service());
- Mlt::Service service(m_mltProducer->parent().get_service());
- if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
-
- /*Mlt::Tractor tractor(service);
-
-
- Mlt::Multitrack *multi = tractor.multitrack();
-
-
- int ct = tractor.count();
- kDebug() << "// TRACK REMOVE: " << ix << ", MAX: " << ct;
- int pos = ix;
- for (; pos < ct ; pos++) {
- Mlt::Service *lastTrack = new Mlt::Service(tractor.track(pos)->get_service());
- //mlt_service_close(lastTrack->get_service());
- delete lastTrack;
- Mlt::Producer *prodToMove = new Mlt::Producer(tractor.track(pos + 1));
- Mlt::Producer *prodToClose = new Mlt::Producer(tractor.track(pos));
- mlt_service_close(prodToMove->get_service());
- mlt_service_close(prodToClose->get_service());
- tractor.set_track(*prodToMove, pos);
- }*/
-
- // Move transitions
- /*mlt_service serv = m_mltProducer->parent().get_service();
- mlt_service nextservice = mlt_service_get_producer(serv);
- mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
- QString mlt_type = mlt_properties_get(properties, "mlt_type");
- QString resource = mlt_properties_get(properties, "mlt_service");
-
- while (mlt_type == "transition") {
- if (resource != "mix") {
- mlt_transition tr = (mlt_transition) nextservice;
- int currentTrack = mlt_transition_get_b_track(tr);
- int currentaTrack = mlt_transition_get_a_track(tr);
- mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
-
- if (currentTrack >= ix) {
- mlt_properties_set_int(properties, "b_track", currentTrack + 1);
- mlt_properties_set_int(properties, "a_track", currentaTrack + 1);
- }
- }
- nextservice = mlt_service_producer(nextservice);
- if (nextservice == NULL) break;
- properties = MLT_SERVICE_PROPERTIES(nextservice);
- mlt_type = mlt_properties_get(properties, "mlt_type");
- resource = mlt_properties_get(properties, "mlt_service");
- }
-
- // Add audio mix transition to last track
- Mlt::Field *field = tractor.field();
- Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "mix");
- //transition->set("mlt_service", "mix");
- transition->set("a_track", 1);
- transition->set("b_track", ct);
- transition->set("always_active", 1);
- transition->set("internal_added", 237);
- transition->set("combine", 1);
- field->plant_transition(*transition, 1, ct);
- */
-
- mlt_service_unlock(m_mltConsumer->get_service());
- m_isBlocked = false;
- blockSignals(false);
}