~ubuntu-branches/ubuntu/hardy/kdenlive/hardy

« back to all changes in this revision

Viewing changes to kdenlive/krender.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Albin Tonnerre
  • Date: 2008-01-30 17:07:51 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080130170751-lyc8p6xvd7o98ur5
Tags: 0.5.svn20071228-0.0ubuntu1
* Merge from debian-multimedia (LP: #150453). Remaining changes:
  - Bump compat to 5
  - Suggest dvgrab and ffmpeg (needed for firewire capture)
  - debian/{rules,control}: add a kdenlive-data package
  - Add .install files for kdenlive and kdenlive-data
  - debian/copyright: add some copyright information
  - Modify Maintainer value to match the DebianMaintainerField specification

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 *                                                                         *
23
23
 ***************************************************************************/
24
24
 
 
25
// ffmpeg Header files
 
26
 
25
27
extern "C" {
26
28
#include <ffmpeg/avformat.h>
27
29
}
28
30
 
29
31
#include <iostream>
30
32
 
31
 
// ffmpeg Header files
32
 
 
33
33
#include <mlt++/Mlt.h>
34
34
 
35
35
#include <qcolor.h>
177
177
    m_mltConsumer->set("frequency", 48000);
178
178
 
179
179
    m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
 
180
 
 
181
    //QTimer::singleShot(500, this, SLOT(initSceneList()));
 
182
    initSceneList();
180
183
//  m_mltConsumer->listen("consumer-stopped", this, (mlt_listener) consumer_stopped);
181
184
//  m_mltConsumer->set("buffer", 25);
182
185
}
288
291
    return pixmap;
289
292
}
290
293
 
291
 
QPixmap KRender::getVideoThumbnail(KURL url, int frame_position, int width, int height)
 
294
QPixmap KRender::getVideoThumbnail(QString file, int frame_position, int width, int height)
292
295
{
293
296
    QPixmap pix(width, height);
294
 
    char *tmp = decodedString(url.path());
 
297
    char *tmp = decodedString(file);
295
298
    Mlt::Producer m_producer(tmp);
296
299
    delete[] tmp;
297
300
    if (m_producer.is_blank()) {
312
315
}
313
316
 
314
317
 
315
 
void KRender::getImage(KURL url, int frame_position, int width, int height)
 
318
void KRender::getImage(KURL url, int frame_position, QPoint size)
316
319
{
317
320
    char *tmp = decodedString(url.path());
318
321
    Mlt::Producer m_producer(tmp);
328
331
    Mlt::Frame * frame = m_producer.get_frame();
329
332
 
330
333
    if (frame) {
331
 
        QPixmap pix = frameThumbnail(frame, width, height, true);
 
334
        QPixmap pix = frameThumbnail(frame, size.x(), size.y(), true);
332
335
        delete frame;
333
 
        emit replyGetImage(url, frame_position, pix, width, height);
 
336
        emit replyGetImage(url, frame_position, pix, size.x(), size.y());
334
337
    }
335
338
}
336
339
 
337
340
/* Create thumbnail for color */
338
 
void KRender::getImage(int id, QString color, int width, int height)
 
341
void KRender::getImage(int id, QString color, QPoint size)
339
342
{
340
 
    QPixmap pixmap(width-2, height-2);
 
343
    QPixmap pixmap(size.x() - 2, size.y() - 2);
341
344
    color = color.replace(0, 2, "#");
342
345
    color = color.left(7);
343
346
    pixmap.fill(QColor(color));
344
 
    QPixmap result(width, height);
 
347
    QPixmap result(size.x(), size.y());
345
348
    result.fill(Qt::black);
346
 
    copyBlt(&result, 1, 1, &pixmap, 0, 0, width - 2, height - 2);
347
 
    emit replyGetImage(id, result, width, height);
 
349
    copyBlt(&result, 1, 1, &pixmap, 0, 0, size.x() - 2, size.y() - 2);
 
350
    emit replyGetImage(id, result, size.x(), size.y());
348
351
 
349
352
}
350
353
 
351
354
/* Create thumbnail for image */
352
 
void KRender::getImage(KURL url, int width, int height)
 
355
void KRender::getImage(KURL url, QPoint size)
353
356
{
354
357
    QImage im;
355
358
    QPixmap pixmap;
370
373
    }
371
374
    else im.load(url.path());
372
375
 
373
 
    pixmap = im.smoothScale(width-2, height-2);
374
 
    QPixmap result(width, height);
 
376
    pixmap = im.smoothScale(size.x() - 2, size.y() - 2);
 
377
    QPixmap result(size.x(), size.y());
375
378
    result.fill(Qt::black);
376
 
    copyBlt(&result, 1, 1, &pixmap, 0, 0, width - 2, height - 2);
377
 
    emit replyGetImage(url, 1, result, width, height);
 
379
    copyBlt(&result, 1, 1, &pixmap, 0, 0, size.x() - 2, size.y() - 2);
 
380
    emit replyGetImage(url, 1, result, size.x(), size.y());
378
381
}
379
382
 
380
383
 
387
390
 
388
391
int KRender::getLength()
389
392
{
390
 
    if (m_mltProducer) return m_mltProducer->get_length();
 
393
 
 
394
    if (m_mltProducer) 
 
395
    {
 
396
        kdDebug()<<"//////  LENGTH: "<<mlt_producer_get_playtime(m_mltProducer->get_producer())<<endl;
 
397
        return mlt_producer_get_playtime(m_mltProducer->get_producer());
 
398
    }
391
399
    return 0;
392
400
}
393
401
 
406
414
void KRender::getFileProperties(KURL url, uint framenb)
407
415
{
408
416
        int height = 40;
409
 
        int width = 50;
 
417
        int width = height * KdenliveSettings::displayratio();
410
418
        char *tmp = decodedString(url.path());
411
419
        Mlt::Producer producer(tmp);
412
420
        delete[] tmp;
420
428
        QMap < QString, QString > metadataPropertyMap;
421
429
 
422
430
        filePropertyMap["filename"] = url.path();
423
 
        filePropertyMap["duration"] = QString::number(producer.get_length());
 
431
        filePropertyMap["duration"] = QString::number(producer.get_playtime());
424
432
        
425
433
        Mlt::Filter m_convert("avcolour_space");
426
434
        m_convert.set("forced", mlt_image_rgb24a);
430
438
 
431
439
        if (frame->is_valid()) {
432
440
            filePropertyMap["fps"] =
433
 
                QString::number(frame->get_double("fps"));
 
441
                QString::number(mlt_producer_get_fps( producer.get_producer() ));
434
442
            filePropertyMap["width"] =
435
443
                QString::number(frame->get_int("width"));
436
444
            filePropertyMap["height"] =
472
480
            }
473
481
 
474
482
            if (frame->get_int("test_image") == 0) {
475
 
                if (frame->get_int("test_audio") == 0)
 
483
                if (url.path().endsWith(".westley") || url.path().endsWith(".kdenlive")) {
 
484
                    filePropertyMap["type"] = "playlist";
 
485
                    metadataPropertyMap["comment"] = QString::fromUtf8(mlt_properties_get( MLT_SERVICE_PROPERTIES( producer.get_service() ), "title"));
 
486
                }
 
487
                else if (frame->get_int("test_audio") == 0)
476
488
                    filePropertyMap["type"] = "av";
477
489
                else
478
490
                    filePropertyMap["type"] = "video";
498
510
}
499
511
 
500
512
/** Create the producer from the Westley QDomDocument */
 
513
void KRender::initSceneList()
 
514
{
 
515
    kdDebug()<<"--------  INIT SCENE LIST ------_"<<endl;
 
516
    QDomDocument doc;
 
517
    QDomElement westley = doc.createElement("westley");
 
518
    doc.appendChild(westley);
 
519
    QDomElement prod = doc.createElement("producer");
 
520
    prod.setAttribute("resource", "colour");
 
521
    prod.setAttribute("colour", "black");
 
522
    prod.setAttribute("id", "black");
 
523
    prod.setAttribute("in", "0");
 
524
    prod.setAttribute("out", "0");
 
525
 
 
526
    QDomElement tractor = doc.createElement("tractor");
 
527
    QDomElement multitrack = doc.createElement("multitrack"); 
 
528
 
 
529
    QDomElement playlist1 = doc.createElement("playlist");
 
530
    playlist1.appendChild(prod);
 
531
    multitrack.appendChild(playlist1);
 
532
    QDomElement playlist2 = doc.createElement("playlist");
 
533
    multitrack.appendChild(playlist2);
 
534
    QDomElement playlist3 = doc.createElement("playlist");
 
535
    multitrack.appendChild(playlist3);
 
536
    QDomElement playlist4 = doc.createElement("playlist");
 
537
    multitrack.appendChild(playlist4);
 
538
    QDomElement playlist5 = doc.createElement("playlist");
 
539
    multitrack.appendChild(playlist5);
 
540
    tractor.appendChild(multitrack);
 
541
    westley.appendChild(tractor);
 
542
    kdDebug()<<doc.toString()<<endl;
 
543
/*
 
544
   QString tmp = QString("<westley><producer resource=\"colour\" colour=\"red\" id=\"red\" /><tractor><multitrack><playlist></playlist><playlist></playlist><playlist /><playlist /><playlist></playlist></multitrack></tractor></westley>");*/
 
545
    setSceneList(doc, 0);
 
546
}
 
547
 
 
548
 
 
549
/** Create the producer from the Westley QDomDocument */
501
550
void KRender::setSceneList(QDomDocument list, int position)
502
551
{
503
552
    if (!m_winid == -1) return;
504
553
    m_generateScenelist = true;
505
554
 
506
 
    m_sceneList = list;
 
555
    kdWarning()<<"//////  RENDER, SET SCENE LIST"<<endl;
507
556
 
508
557
    Mlt::Playlist track;
509
558
    char *tmp = decodedString(list.toString());
528
577
 
529
578
    if (m_mltProducer) {
530
579
        m_mltProducer->set_speed(0.0);
 
580
 
531
581
        if (KdenliveSettings::osdtimecode() && m_osdInfo) m_mltProducer->detach(*m_osdInfo);
532
582
        //mlt_producer_clear(m_mltProducer->get_producer());
533
583
        delete m_mltProducer;
535
585
        emit stopped();
536
586
    }
537
587
 
538
 
    m_mltProducer = track.current();
 
588
    m_mltProducer = new Mlt::Producer(clip); //track.current();
539
589
    m_mltProducer->optimise();
540
590
    if (position != 0) m_mltProducer->seek(position);
541
591
 
567
617
            restartConsumer();
568
618
        }
569
619
 
570
 
        m_connectTimer->start(100, TRUE);
 
620
        m_connectTimer->start( 500, TRUE);
571
621
        m_generateScenelist = false;
572
 
    
 
622
  
573
623
}
574
624
 
575
625
 
580
630
        }
581
631
        else {
582
632
            m_mltConsumer->connect(*m_mltProducer);
 
633
            m_mltProducer->set_speed(0.0);
583
634
            refresh();
584
635
        }
585
636
}
695
746
{
696
747
    if (!m_mltProducer)
697
748
        return;
698
 
    m_mltProducer->set("out", m_mltProducer->get_length() - 1);
 
749
    // m_mltProducer->set("out", m_mltProducer->get_length() - 1);
699
750
    m_mltProducer->set_speed(speed);
700
751
    /*if (speed == 0.0) {
701
752
        m_mltProducer->seek((int) m_framePosition + 1);
708
759
{
709
760
    if (!m_mltProducer)
710
761
        return;
711
 
    m_mltProducer->set("out", m_mltProducer->get_length() - 1);
 
762
    // m_mltProducer->set("out", m_mltProducer->get_length() - 1);
712
763
    m_mltProducer->set_speed(speed);
713
764
    m_mltProducer->seek((int) (startTime.frames(m_fps)));
714
765
    m_mltConsumer->purge();
739
790
{
740
791
    if (!m_mltProducer)
741
792
        return;
 
793
    //kdDebug()<<"//////////  KDENLIVE SEEK: "<<(int) (time.frames(m_fps))<<endl;
742
794
    m_mltProducer->seek((int) (time.frames(m_fps)));
743
795
    refresh();
744
796
}
751
803
 
752
804
void KRender::refresh()
753
805
{
754
 
 
755
806
    if (!m_mltProducer)
756
807
        return;
757
808
    refreshTimer->stop();
796
847
{
797
848
        if (m_generateScenelist) return;
798
849
        m_framePosition = position;
799
 
        QApplication::postEvent(qApp->mainWidget(), new PositionChangeEvent( GenTime((int) position, m_fps), m_monitorId));
 
850
        if (qApp->mainWidget()) QApplication::postEvent(qApp->mainWidget(), new PositionChangeEvent( GenTime((int) position, m_fps), m_monitorId));
800
851
}
801
852
 
802
853
void KRender::emitConsumerStopped()
804
855
    // This is used to know when the playing stopped
805
856
    if (m_mltProducer && !m_generateScenelist) {
806
857
        double pos = m_mltProducer->position();
807
 
        QApplication::postEvent(qApp->mainWidget(), new PositionChangeEvent(GenTime((int) pos, m_fps), m_monitorId + 100));
 
858
        if (qApp->mainWidget()) QApplication::postEvent(qApp->mainWidget(), new PositionChangeEvent(GenTime((int) pos, m_fps), m_monitorId + 100));
808
859
        //new QCustomEvent(10002));
809
860
    }
810
861
}
811
862
 
812
863
 
813
 
/*                           FILE RENDERING STUFF                     */
814
 
 
815
 
#ifdef ENABLE_FIREWIRE
816
 
int readCount = 1;
817
 
int fileSize = 0;
818
 
int fileProgress = 0;
819
 
int droppedFrames = 0;
820
 
 
821
 
//  FIREWIRE EXPORT, REQUIRES LIBIECi61883
822
 
static int read_frame (unsigned char *data, int n, unsigned int dropped, void *callback_data)
823
 
{
824
 
    FILE *f = (FILE*) callback_data;
825
 
 
826
 
 
827
 
    if (n == 1)
828
 
        if (fread (data, 480, 1, f) < 1) {
829
 
        return -1;
830
 
        } else {
831
 
            //long int position = ftell(f);
832
 
            readCount++;
833
 
            return 0;
834
 
        }
835
 
            else {
836
 
                return 0;
837
 
            }
838
 
}
839
 
 
840
 
static int g_done = 0;
841
 
 
842
 
static void sighandler (int sig)
843
 
{
844
 
    g_done = 1;
845
 
}
846
 
 
847
 
void KRender::dv_transmit( raw1394handle_t handle, FILE *f, int channel)
848
 
{       
849
 
    iec61883_dv_t dv;
850
 
    unsigned char data[480];
851
 
    int ispal;
852
 
        
853
 
    fread (data, 480, 1, f);
854
 
    ispal = (data[ 3 ] & 0x80) != 0;
855
 
    dv = iec61883_dv_xmit_init (handle, ispal, read_frame, (void *)f );
856
 
 
857
 
    if (dv) iec61883_dv_set_synch( dv, 1 );
858
 
        
859
 
    if (dv && iec61883_dv_xmit_start (dv, channel) == 0)
860
 
    {
861
 
        int fd = raw1394_get_fd (handle);
862
 
        struct timeval tv;
863
 
        fd_set rfds;
864
 
        int result = 0;
865
 
                
866
 
        signal (SIGINT, sighandler);
867
 
        signal (SIGPIPE, sighandler);
868
 
        fprintf (stderr, "Starting to transmit %s\n", ispal ? "PAL" : "NTSC");
869
 
 
870
 
        do {
871
 
            FD_ZERO (&rfds);
872
 
            FD_SET (fd, &rfds);
873
 
            tv.tv_sec = 0;
874
 
            tv.tv_usec = 20000;
875
 
            if (select (fd + 1, &rfds, NULL, NULL, &tv) > 0) {
876
 
                result = raw1394_loop_iterate (handle);
877
 
                if (((int)(readCount * 100 / fileSize )) != fileProgress) {
878
 
                        fileProgress = readCount * 100 / fileSize;
879
 
                        //kdDebug()<<"++ FRAME READ2: "<<fileProgress<<endl;
880
 
                        QApplication::postEvent(qApp->mainWidget(), new ProgressEvent(fileProgress, 10006));
881
 
                        qApp->processEvents();
882
 
                }
883
 
            }
884
 
                        
885
 
        } while (g_done == 0 && result == 0);
886
 
        iec61883_dv_xmit_stop (dv);
887
 
        droppedFrames = iec61883_dv_get_dropped(dv);
888
 
        fprintf (stderr, "done.\n");
889
 
    }
890
 
    iec61883_dv_close (dv);
891
 
}
892
 
#endif
893
864
 
894
865
void KRender::exportFileToFirewire(QString srcFileName, int port, GenTime startTime, GenTime endTime)
895
866
{
896
 
#ifdef ENABLE_FIREWIRE
897
 
    //exportTimeline(QString::null);
898
 
    kdDebug()<<"START DV EXPORT ++++++++++++++: "<<srcFileName<<endl;
899
 
 
900
 
    fileSize = QFile(srcFileName).size() / 480;
901
 
    readCount = 1;
902
 
    fileProgress = 0;
903
 
 
904
 
    FILE *f = NULL;
905
 
    int oplug = -1, iplug = -1;
906
 
    f = fopen (decodedString(srcFileName), "rb");
907
 
    raw1394handle_t handle = raw1394_new_handle_on_port (port);
908
 
    if (f == NULL) {
909
 
        KMessageBox::sorry(0,i18n("Cannot open file: ")+srcFileName.ascii());
910
 
        return;
911
 
    }
912
 
    if (handle == NULL) {
913
 
        KMessageBox::sorry(0,i18n("NO firewire access on that port\nMake sure you have loaded the raw1394 module and that you have write access on /dev/raw1394..."));
914
 
        return;
915
 
    }
916
 
    nodeid_t node = 0xffc0;
917
 
    int bandwidth = -1;
918
 
    int channel = iec61883_cmp_connect (handle, raw1394_get_local_id (handle), &oplug, node, &iplug, &bandwidth);
919
 
    if (channel > -1)
920
 
    {
921
 
        dv_transmit (handle, f, channel);
922
 
        iec61883_cmp_disconnect (handle, raw1394_get_local_id (handle), oplug, node, iplug, channel, bandwidth);
923
 
    }
924
 
    else KMessageBox::sorry(0,i18n("NO DV device found"));
925
 
    fclose (f);
926
 
    raw1394_destroy_handle (handle);
927
 
    QApplication::postEvent(qApp->mainWidget(), new QCustomEvent(10003));
928
 
    if (droppedFrames > 0) KMessageBox::sorry(0, i18n("Transmission of dv file is finished.\n%1 frames were dropped during transfer.").arg(droppedFrames));
929
 
    else KMessageBox::information(0, i18n("Transmission of dv file finished successfully."));
930
 
#else
931
867
KMessageBox::sorry(0, i18n("Firewire is not enabled on your system.\n Please install Libiec61883 and recompile Kdenlive"));
932
 
#endif
933
868
}
934
869
 
935
870
 
939
874
        return;
940
875
    }
941
876
 
 
877
    int height = KdenliveSettings::defaultheight();
942
878
    int width = KdenliveSettings::displaywidth();
943
 
    int height = KdenliveSettings::defaultheight();
944
879
 
945
880
    QPixmap pix(width, height);
946
881
 
954
889
        delete frame;
955
890
    }
956
891
    pix.save(url.path(), "PNG");
957
 
    QApplication::postEvent(qApp->mainWidget(), new UrlEvent(url, 10003));
958
 
}
959
 
 
 
892
    if (notify) QApplication::postEvent(qApp->mainWidget(), new UrlEvent(url, 10003));
 
893
}
 
894
 
 
895
/**     MLT PLAYLIST DIRECT MANIPULATON         **/
 
896
 
 
897
 
 
898
void KRender::mltCheckLength()
 
899
{
 
900
    //kdDebug()<<"checking track length: "<<track<<".........."<<endl;
 
901
    Mlt::Service service(m_mltProducer->get_service());
 
902
    Mlt::Tractor tractor(service);
 
903
 
 
904
    int trackNb = tractor.count( );
 
905
    double duration = 0;
 
906
    double trackDuration;
 
907
    if (trackNb == 1) {
 
908
        Mlt::Producer trackProducer(tractor.track(0));
 
909
        Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
910
        duration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
 
911
        m_mltProducer->set("out", duration);
 
912
        emit durationChanged();
 
913
        return;
 
914
    }
 
915
    while (trackNb > 1) {
 
916
        Mlt::Producer trackProducer(tractor.track(trackNb - 1));
 
917
        Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
918
        trackDuration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
 
919
 
 
920
        kdDebug()<<" / / /DURATON FOR TRACK "<<trackNb - 1<<" = "<<trackDuration<<endl;
 
921
        if (trackDuration > duration) duration = trackDuration;
 
922
        trackNb--;
 
923
    }
 
924
 
 
925
    Mlt::Producer blackTrackProducer(tractor.track(0));
 
926
    Mlt::Playlist blackTrackPlaylist(( mlt_playlist ) blackTrackProducer.get_service());
 
927
    double blackDuration = Mlt::Producer(blackTrackPlaylist.get_producer()).get_playtime() - 1;
 
928
        kdDebug()<<" / / /DURATON FOR TRACK 0 = "<<blackDuration<<endl;
 
929
    if (blackDuration != duration) {
 
930
        blackTrackPlaylist.remove_region( 0, blackDuration );
 
931
        int i = 0;
 
932
        int dur = duration;
 
933
        
 
934
        while (dur > 14000) { // <producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"13999\" />
 
935
            mltInsertClip(0, GenTime(i * 14000, m_fps), QString("<westley><producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"13999\" /></westley>"));
 
936
            dur = dur - 14000;
 
937
            i++;
 
938
        }
 
939
 
 
940
        mltInsertClip(0, GenTime(), QString("<westley><producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"" + QString::number(dur) + "\" /></westley>"));
 
941
 
 
942
        m_mltProducer->set("out", duration);
 
943
        emit durationChanged();
 
944
    }
 
945
}
 
946
 
 
947
 
 
948
void KRender::mltInsertClip(int track, GenTime position, QString resource)
 
949
{
 
950
    if (!m_mltProducer) {
 
951
        kdDebug()<<"PLAYLIST NOT INITIALISED //////"<<endl;
 
952
        return;
 
953
    }
 
954
    Mlt::Producer parentProd(m_mltProducer->parent());
 
955
    if (parentProd.get_producer() == NULL) {
 
956
        kdDebug()<<"PLAYLIST BROKEN, CANNOT INSERT CLIP //////"<<endl;
 
957
        return;
 
958
    }
 
959
    Mlt::Service service(parentProd.get_service());
 
960
    Mlt::Tractor tractor(service);
 
961
 
 
962
    Mlt::Producer trackProducer(tractor.track(track));
 
963
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
964
    char *tmp = decodedString(resource);
 
965
    Mlt::Producer clip("westley-xml", tmp);
 
966
    //clip.set_in_and_out(in.frames(m_fps), out.frames(m_fps));
 
967
    delete[] tmp;
 
968
 
 
969
    trackPlaylist.insert_at(position.frames(m_fps), clip, 1);
 
970
    tractor.multitrack()->refresh();
 
971
    tractor.refresh();
 
972
    if (track != 0) mltCheckLength();
 
973
    double duration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime();
 
974
    kdDebug()<<"// +  +INSERTING CLIP: "<<resource<<" AT: "<<position.frames(m_fps)<<" on track: "<<track<<", DURATION: "<<duration<<endl;
 
975
 
 
976
 
 
977
}
 
978
 
 
979
void KRender::mltCutClip(int track, GenTime position)
 
980
{
 
981
    Mlt::Service service(m_mltProducer->parent().get_service());
 
982
    if (service.type() == playlist_type) kdDebug()<<"// PLAYLIST TYPE"<<endl;
 
983
    if (service.type() == tractor_type) kdDebug()<<"// TRACOT TYPE"<<endl;
 
984
    if (service.type() == multitrack_type) kdDebug()<<"// MULTITRACK TYPE"<<endl;
 
985
    if (service.type() == producer_type) kdDebug()<<"// PROD TYPE"<<endl;
 
986
 
 
987
    Mlt::Tractor tractor(service);
 
988
    Mlt::Producer trackProducer(tractor.track(track));
 
989
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
990
    trackPlaylist.split_at(position.frames(m_fps));
 
991
    trackPlaylist.consolidate_blanks(0);
 
992
    kdDebug()<<"/ / / /CUTTING CLIP AT: "<<position.frames(m_fps)<<endl;
 
993
}
 
994
 
 
995
 
 
996
void KRender::mltRemoveClip(int track, GenTime position)
 
997
{
 
998
    Mlt::Service service(m_mltProducer->parent().get_service());
 
999
    if (service.type() == playlist_type) kdDebug()<<"// PLAYLIST TYPE"<<endl;
 
1000
    if (service.type() == tractor_type) kdDebug()<<"// TRACOT TYPE"<<endl;
 
1001
    if (service.type() == multitrack_type) kdDebug()<<"// MULTITRACK TYPE"<<endl;
 
1002
    if (service.type() == producer_type) kdDebug()<<"// PROD TYPE"<<endl;
 
1003
 
 
1004
    Mlt::Tractor tractor(service);
 
1005
    Mlt::Producer trackProducer(tractor.track(track));
 
1006
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1007
    int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
 
1008
    //trackPlaylist.remove(clipIndex);
 
1009
    trackPlaylist.replace_with_blank(clipIndex);
 
1010
    trackPlaylist.consolidate_blanks(0);
 
1011
    if (track != 0) mltCheckLength();
 
1012
    //emit durationChanged();
 
1013
}
 
1014
 
 
1015
void KRender::mltRemoveEffect(int track, GenTime position, QString id, QString tag, int index)
 
1016
{
 
1017
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1018
 
 
1019
    Mlt::Tractor tractor(service);
 
1020
    Mlt::Producer trackProducer(tractor.track(track));
 
1021
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1022
    //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
 
1023
    Mlt::Producer *clip = trackPlaylist.get_clip_at(position.frames(m_fps));
 
1024
    if (!clip) {
 
1025
        kdDebug()<<" / / / CANNOT FIND CLIP TO REMOVE EFFECT"<<endl;
 
1026
        return;
 
1027
    }
 
1028
    Mlt::Service clipService(clip->get_service());
 
1029
 
 
1030
    if (tag.startsWith("ladspa")) tag = "ladspa";
 
1031
 
 
1032
    if (index == -1) {
 
1033
        int ct = 0;
 
1034
        Mlt::Filter *filter = clipService.filter( ct );
 
1035
        while (filter) {
 
1036
            if (filter->get("mlt_service") == tag && filter->get("kdenlive_id") == id) {
 
1037
                clipService.detach(*filter);
 
1038
                kdDebug()<<" / / / DLEETED EFFECT: "<<ct<<endl;
 
1039
            }
 
1040
            else ct++;
 
1041
            filter = clipService.filter( ct );
 
1042
        }
 
1043
    }
 
1044
    else {
 
1045
        Mlt::Filter *filter = clipService.filter( index );
 
1046
        if (filter && filter->get("mlt_service") == tag && filter->get("kdenlive_id") == id) clipService.detach(*filter);
 
1047
        else {
 
1048
            kdDebug()<<"WARINIG, FILTER "<<id<<" NOT FOUND!!!!!"<<endl;
 
1049
        }
 
1050
    }
 
1051
    refresh();
 
1052
}
 
1053
 
 
1054
 
 
1055
void KRender::mltAddEffect(int track, GenTime position, QString id, QString tag, QMap <QString, QString> args)
 
1056
{
 
1057
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1058
 
 
1059
    Mlt::Tractor tractor(service);
 
1060
    Mlt::Producer trackProducer(tractor.track(track));
 
1061
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1062
 
 
1063
    Mlt::Producer *clip = trackPlaylist.get_clip_at(position.frames(m_fps));
 
1064
 
 
1065
    if (!clip) {
 
1066
        kdDebug()<<"**********  CANNOT FIND CLIP TO APPLY EFFECT-----------"<<endl;
 
1067
        return;
 
1068
    }
 
1069
    Mlt::Service clipService(clip->get_service());
 
1070
 
 
1071
    // create filter
 
1072
    kdDebug()<<" / / INSERTING EFFECT: "<<id<<endl;
 
1073
    if (tag.startsWith("ladspa")) tag = "ladspa";
 
1074
    char *filterId = decodedString(tag);
 
1075
    Mlt::Filter *filter = new Mlt::Filter(filterId);
 
1076
    filter->set("kdenlive_id", id);
 
1077
 
 
1078
    QMap<QString, QString>::Iterator it;
 
1079
    QString keyFrameNumber = "#0";
 
1080
 
 
1081
    for ( it = args.begin(); it != args.end(); ++it ) {
 
1082
    kdDebug()<<" / / INSERTING EFFECT ARGS: "<<it.key()<<": "<<it.data()<<endl;
 
1083
        QString key;
 
1084
        QString currentKeyFrameNumber;
 
1085
        if (it.key().startsWith("#")) {
 
1086
            currentKeyFrameNumber = it.key().section(":", 0, 0);
 
1087
            if (currentKeyFrameNumber != keyFrameNumber) {
 
1088
                // attach filter to the clip
 
1089
                clipService.attach(*filter);
 
1090
                filter = new Mlt::Filter(filterId);
 
1091
                filter->set("kdenlive_id", id);
 
1092
                keyFrameNumber = currentKeyFrameNumber;
 
1093
            }
 
1094
            key = it.key().section(":", 1);
 
1095
        }
 
1096
        else key = it.key();
 
1097
        char *name = decodedString(key);
 
1098
        char *value = decodedString(it.data());
 
1099
        filter->set(name, value);
 
1100
        delete[] name;
 
1101
        delete[] value;
 
1102
    }
 
1103
    // attach filter to the clip
 
1104
    clipService.attach(*filter);
 
1105
    delete[] filterId;
 
1106
    refresh();
 
1107
 
 
1108
}
 
1109
 
 
1110
void KRender::mltEditEffect(int track, GenTime position, int index, QString id, QString tag, QMap <QString, QString> args)
 
1111
{
 
1112
    QMap<QString, QString>::Iterator it = args.begin();
 
1113
    if (it.key().startsWith("#") || tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle") {
 
1114
        // This is a keyframe effect, to edit it, we remove it and re-add it.
 
1115
        mltRemoveEffect(track, position, id, tag, -1);
 
1116
        mltAddEffect(track, position, id, tag, args);
 
1117
        return;
 
1118
    }
 
1119
 
 
1120
    // create filter
 
1121
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1122
 
 
1123
    Mlt::Tractor tractor(service);
 
1124
    Mlt::Producer trackProducer(tractor.track(track));
 
1125
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1126
    //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
 
1127
    Mlt::Producer *clip = trackPlaylist.get_clip_at(position.frames(m_fps));
 
1128
    Mlt::Service clipService(clip->get_service());
 
1129
    Mlt::Filter *filter = clipService.filter( index );
 
1130
 
 
1131
 
 
1132
    if (!filter || filter->get("mlt_service") != tag) {
 
1133
        kdDebug()<<"WARINIG, FILTER NOT FOUND!!!!!"<<endl;
 
1134
        int index = 0;
 
1135
        filter = clipService.filter( index );
 
1136
        while (filter) {
 
1137
            if (filter->get("mlt_service") == tag && filter->get("kdenlive_id") == id) break;
 
1138
            index++;
 
1139
            filter = clipService.filter( index );
 
1140
        }
 
1141
    }
 
1142
    if (!filter) {
 
1143
        kdDebug()<<"WARINIG, FILTER "<<id<<" NOT FOUND!!!!!"<<endl;
 
1144
        return;
 
1145
    }
 
1146
 
 
1147
    for ( it = args.begin(); it != args.end(); ++it ) {
 
1148
    kdDebug()<<" / / INSERTING EFFECT ARGS: "<<it.key()<<": "<<it.data()<<endl;
 
1149
        char *name = decodedString(it.key());
 
1150
        char *value = decodedString(it.data());
 
1151
        filter->set(name, value);
 
1152
        delete[] name;
 
1153
        delete[] value;
 
1154
    }
 
1155
    refresh();
 
1156
}
 
1157
 
 
1158
void KRender::mltResizeClipEnd(int track, GenTime pos, GenTime in, GenTime out)
 
1159
{
 
1160
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1161
 
 
1162
    Mlt::Tractor tractor(service);
 
1163
    Mlt::Producer trackProducer(tractor.track(track));
 
1164
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1165
    if (trackPlaylist.is_blank_at(pos.frames(m_fps) + 1)) 
 
1166
        kdDebug()<<"////////  ERROR RSIZING BLANK CLIP!!!!!!!!!!!"<<endl;
 
1167
    int clipIndex = trackPlaylist.get_clip_index_at(pos.frames(m_fps) + 1);
 
1168
 
 
1169
    int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
 
1170
    int newDuration = out.frames(m_fps) - 1;
 
1171
 
 
1172
    kdDebug()<<" ** RESIZING CLIP END:" << clipIndex << " on track:"<< track <<", mid pos: "<<pos.frames(25)<<", in: "<<in.frames(25)<<", out: "<<out.frames(25)<<", PREVIOUS duration: "<<previousDuration<<endl;
 
1173
    trackPlaylist.resize_clip(clipIndex, in.frames(m_fps), newDuration);
 
1174
    trackPlaylist.consolidate_blanks(0);
 
1175
    if (previousDuration < newDuration) {
 
1176
        // clip was made longer, trim next blank if there is one.
 
1177
        if (trackPlaylist.is_blank(clipIndex + 1)) {
 
1178
            trackPlaylist.split(clipIndex + 1, newDuration - previousDuration);
 
1179
            trackPlaylist.remove(clipIndex + 1);
 
1180
        }
 
1181
    }
 
1182
    else trackPlaylist.insert_blank(clipIndex + 1, previousDuration - newDuration - 1);
 
1183
 
 
1184
    trackPlaylist.consolidate_blanks(0);
 
1185
    tractor.multitrack()->refresh();
 
1186
    tractor.refresh();
 
1187
    if (track != 0) mltCheckLength();
 
1188
 
 
1189
}
 
1190
 
 
1191
void KRender::mltChangeTrackState(int track, bool mute, bool blind)
 
1192
{
 
1193
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1194
 
 
1195
    Mlt::Tractor tractor(service);
 
1196
    Mlt::Producer trackProducer(tractor.track(track));
 
1197
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1198
    if (mute) {
 
1199
        if (blind) trackProducer.set("hide", 3);
 
1200
        else trackProducer.set("hide", 2);
 
1201
    }
 
1202
    else if (blind) {
 
1203
        trackProducer.set("hide", 1);
 
1204
    }
 
1205
    else {
 
1206
        trackProducer.set("hide", 0);
 
1207
    }
 
1208
    tractor.multitrack()->refresh();
 
1209
    tractor.refresh();
 
1210
    refresh();
 
1211
}
 
1212
 
 
1213
void KRender::mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out)
 
1214
{
 
1215
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1216
    if (service.type() == playlist_type) kdDebug()<<"// PLAYLIST TYPE"<<endl;
 
1217
    if (service.type() == tractor_type) kdDebug()<<"// TRACOT TYPE"<<endl;
 
1218
    if (service.type() == multitrack_type) kdDebug()<<"// MULTITRACK TYPE"<<endl;
 
1219
    if (service.type() == producer_type) kdDebug()<<"// PROD TYPE"<<endl;
 
1220
 
 
1221
    int moveFrame = (moveEnd - moveStart).frames(m_fps);
 
1222
 
 
1223
    Mlt::Tractor tractor(service);
 
1224
    Mlt::Producer trackProducer(tractor.track(track));
 
1225
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1226
    if (trackPlaylist.is_blank_at(pos.frames(m_fps) - 1)) 
 
1227
        kdDebug()<<"////////  ERROR RSIZING BLANK CLIP!!!!!!!!!!!"<<endl;
 
1228
    int clipIndex = trackPlaylist.get_clip_index_at(pos.frames(m_fps) - 1);
 
1229
    kdDebug()<<" ** RESIZING CLIP START:" << clipIndex << " on track:"<< track <<", mid pos: "<<pos.frames(25)<<", moving: "<<moveFrame<<", in: "<<in.frames(25)<<", out: "<<out.frames(25)<<endl;
 
1230
 
 
1231
    trackPlaylist.resize_clip(clipIndex, in.frames(m_fps), out.frames(m_fps));
 
1232
    if (moveFrame > 0) trackPlaylist.insert_blank(clipIndex, moveFrame - 1);
 
1233
    else {
 
1234
        int midpos = moveStart.frames(m_fps) - 1; //+ (moveFrame / 2)
 
1235
        int blankIndex = trackPlaylist.get_clip_index_at(midpos);
 
1236
        int blankLength = trackPlaylist.clip_length(blankIndex);
 
1237
 
 
1238
        kdDebug()<<" + resizing blank: "<<blankIndex<<", Mid: "<<midpos<<", Length: "<<blankLength<< ", SIZE DIFF: "<<moveFrame<<endl;
 
1239
 
 
1240
        
 
1241
        if (blankLength + moveFrame == 0) trackPlaylist.remove(blankIndex);
 
1242
        else trackPlaylist.resize_clip(blankIndex, 0, blankLength + moveFrame -1);
 
1243
    }
 
1244
    trackPlaylist.consolidate_blanks(0);
 
1245
 
 
1246
    kdDebug()<<"-----------------\n"<<"CLIP 0: "<<trackPlaylist.clip_start(0)<<", LENGT: "<<trackPlaylist.clip_length(0)<<endl;
 
1247
    kdDebug()<<"CLIP 1: "<<trackPlaylist.clip_start(1)<<", LENGT: "<<trackPlaylist.clip_length(1)<<endl;
 
1248
    kdDebug()<<"CLIP 2: "<<trackPlaylist.clip_start(2)<<", LENGT: "<<trackPlaylist.clip_length(2)<<endl;
 
1249
    kdDebug()<<"CLIP 3: "<<trackPlaylist.clip_start(3)<<", LENGT: "<<trackPlaylist.clip_length(3)<<endl;
 
1250
   kdDebug()<<"CLIP 4: "<<trackPlaylist.clip_start(4)<<", LENGT: "<<trackPlaylist.clip_length(4)<<endl;
 
1251
}
 
1252
 
 
1253
void KRender::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd)
 
1254
{
 
1255
    mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps));
 
1256
}
 
1257
 
 
1258
 
 
1259
void KRender::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd)
 
1260
{
 
1261
    m_mltConsumer->set("refresh", 0);
 
1262
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1263
 
 
1264
    Mlt::Tractor tractor(service);
 
1265
    Mlt::Producer trackProducer(tractor.track(startTrack));
 
1266
    Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
 
1267
    int clipIndex = trackPlaylist.get_clip_index_at(moveStart + 1);
 
1268
 
 
1269
 
 
1270
    mlt_field field = mlt_tractor_field(tractor.get_tractor());
 
1271
 
 
1272
    mlt_multitrack multitrack = mlt_field_multitrack(field); //mlt_tractor_multitrack(tractor.get_tractor());
 
1273
    kdDebug()<<" --  CURRENT MULTIOTRACK HAS: "<<mlt_multitrack_count(multitrack)<<" tracks"<<endl;;
 
1274
    mlt_service multiprod = mlt_multitrack_service( multitrack );
 
1275
 
 
1276
    Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
 
1277
    trackPlaylist.consolidate_blanks(0);
 
1278
    mlt_events_block( MLT_PRODUCER_PROPERTIES(clipProducer.get_producer()), NULL );
 
1279
 
 
1280
    if (endTrack == startTrack) {
 
1281
        if (!trackPlaylist.is_blank_at(moveEnd)) {
 
1282
            kdWarning()<<"// ERROR, CLIP COLLISION----------"<<endl;
 
1283
            int ix = trackPlaylist.get_clip_index_at(moveEnd);
 
1284
                kdDebug()<<"BAD CLIP STARTS AT: "<<trackPlaylist.clip_start(ix)<<", LENGT: "<<trackPlaylist.clip_length(ix)<<endl;
 
1285
        }
 
1286
        trackPlaylist.insert_at(moveEnd, clipProducer, 1);
 
1287
        trackPlaylist.consolidate_blanks(0);
 
1288
    }
 
1289
    else {
 
1290
        trackPlaylist.consolidate_blanks(0);
 
1291
        Mlt::Producer destTrackProducer(tractor.track(endTrack));
 
1292
        Mlt::Playlist destTrackPlaylist(( mlt_playlist ) destTrackProducer.get_service());
 
1293
        destTrackPlaylist.consolidate_blanks(1);
 
1294
        destTrackPlaylist.insert_at(moveEnd, clipProducer, 1);
 
1295
        destTrackPlaylist.consolidate_blanks(0);
 
1296
    }
 
1297
 
 
1298
    mltCheckLength();
 
1299
    mlt_events_unblock( MLT_PRODUCER_PROPERTIES(clipProducer.get_producer()), NULL );
 
1300
}
 
1301
 
 
1302
void KRender::mltMoveTransition(QString type, int startTrack, int trackOffset, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut)
 
1303
{
 
1304
    m_mltConsumer->set("refresh", 0);
 
1305
    mlt_service serv = m_mltProducer->parent().get_service();
 
1306
 
 
1307
    mlt_service nextservice = mlt_service_get_producer(serv);
 
1308
    mlt_properties properties = MLT_SERVICE_PROPERTIES( nextservice );
 
1309
    QString mlt_type = mlt_properties_get( properties, "mlt_type" );
 
1310
    QString resource = mlt_properties_get( properties, "mlt_service");
 
1311
    int old_pos = (oldIn.frames(m_fps) + oldOut.frames(m_fps)) / 2;
 
1312
 
 
1313
    int new_in = newIn.frames(m_fps);
 
1314
    int new_out = newOut.frames(m_fps) - 1;
 
1315
    while (mlt_type == "transition") {
 
1316
        mlt_transition tr = (mlt_transition) nextservice;
 
1317
        int currentTrack = mlt_transition_get_b_track(tr);
 
1318
        int currentIn = (int) mlt_transition_get_in(tr);
 
1319
        int currentOut = (int) mlt_transition_get_out(tr);
 
1320
        kdDebug()<<"// FOUND EXISTING TRANS, IN: "<<currentIn<<", OUT: "<<currentOut<<", TRACK: "<<currentTrack<<endl;
 
1321
        //kdDebug()<<"// LOOKING FOR IN: "<<old_in<<", OUT: "<<old_out<<endl;
 
1322
        kdDebug()<<"// OLD IN: "<<oldIn.frames(m_fps)<<" // OLD OUT: "<<oldOut.frames(m_fps)<<", TRACK: "<<startTrack<<", MID POS: "<<old_pos<<endl;
 
1323
        if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
 
1324
            mlt_transition_set_in_and_out(tr, new_in, new_out);
 
1325
            if (trackOffset != 0) {
 
1326
                mlt_properties properties = MLT_TRANSITION_PROPERTIES( tr );
 
1327
                mlt_properties_set_int( properties, "a_track", mlt_transition_get_a_track(tr) + trackOffset );
 
1328
                mlt_properties_set_int( properties, "b_track", mlt_transition_get_b_track(tr) + trackOffset );
 
1329
            }
 
1330
            break;
 
1331
        }
 
1332
        nextservice = mlt_service_producer(nextservice);
 
1333
        properties = MLT_SERVICE_PROPERTIES( nextservice );
 
1334
        mlt_type = mlt_properties_get( properties, "mlt_type" );
 
1335
        resource = mlt_properties_get( properties, "mlt_service" );
 
1336
    }
 
1337
}
 
1338
 
 
1339
void KRender::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args)
 
1340
{
 
1341
    Mlt::Service service(m_mltProducer->parent().get_service());
 
1342
 
 
1343
    Mlt::Tractor tractor(service);
 
1344
    Mlt::Field *field = tractor.field();
 
1345
 
 
1346
    char *transId = decodedString(tag);
 
1347
    Mlt::Transition *transition = new Mlt::Transition(transId);
 
1348
    transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps));
 
1349
    QMap<QString, QString>::Iterator it;
 
1350
    QString key;
 
1351
 
 
1352
    kdDebug()<<" ------  ADDING TRANSITION PARAMs: "<<args.count()<<endl;
 
1353
 
 
1354
    for ( it = args.begin(); it != args.end(); ++it ) {
 
1355
        key = it.key();
 
1356
        char *name = decodedString(key);
 
1357
        char *value = decodedString(it.data());
 
1358
        transition->set(name, value);
 
1359
        kdDebug()<<" ------  ADDING TRANS PARAM: "<<name<<": "<<value<<endl;
 
1360
        //filter->set("kdenlive_id", id);
 
1361
        delete[] name;
 
1362
        delete[] value;
 
1363
    }
 
1364
    // attach filter to the clip
 
1365
    field->plant_transition(*transition, a_track, b_track);
 
1366
    delete[] transId;
 
1367
    refresh();
 
1368
 
 
1369
}
 
1370
 
 
1371
void KRender::mltSavePlaylist()
 
1372
{
 
1373
    kdWarning()<<"// UPDATING PLAYLIST TO DISK++++++++++++++++"<<endl;
 
1374
    Mlt::Consumer *fileConsumer = new Mlt::Consumer("westley");
 
1375
    fileConsumer->set("resource", "/home/one/playlist.xml");
 
1376
 
 
1377
    Mlt::Service service(m_mltProducer->get_service());
 
1378
    Mlt::Tractor tractor(service);
 
1379
 
 
1380
    fileConsumer->connect(service);
 
1381
    fileConsumer->start();
 
1382
 
 
1383
}
960
1384