]> git.sesse.net Git - kdenlive/commitdiff
Add Mac OS X compatibility through new MLT sdl_audio consumer and a QTGLWidget!
authorDan Dennedy <dan@dennedy.org>
Thu, 27 Aug 2009 05:14:10 +0000 (05:14 +0000)
committerDan Dennedy <dan@dennedy.org>
Thu, 27 Aug 2009 05:14:10 +0000 (05:14 +0000)
svn path=/trunk/kdenlive/; revision=3839

src/CMakeLists.txt
src/kdenlivesettingsdialog.cpp
src/main.cpp
src/mainwindow.cpp
src/monitor.cpp
src/monitor.h
src/renderer.cpp
src/renderer.h
src/videoglwidget.cpp [new file with mode: 0644]
src/videoglwidget.h [new file with mode: 0644]

index bfd7c7dc3677bdf19198bf66c62f5564bc10350c..808819649b6e80cb537834eca5eddf0108e574f5 100644 (file)
@@ -1,9 +1,13 @@
-
 add_subdirectory( widgets )
 add_subdirectory( mimetypes )
 
 find_package(Nepomuk REQUIRED)
 
+if (APPLE)
+  find_package(OpenGL)
+  set(QT_USE_QTOPENGL TRUE)
+endif (APPLE)
+
 include_directories (
     ${KDE4_INCLUDE_DIR}
     ${KDE4_INCLUDE_DIR}/KDE
@@ -180,6 +184,10 @@ else(NO_JOGSHUTTLE)
   set(kdenlive_SRCS jogshuttle.cpp ${kdenlive_SRCS})
 endif(NO_JOGSHUTTLE)
 
+if (APPLE)
+  set(kdenlive_SRCS videoglwidget.cpp ${kdenlive_SRCS})
+endif (APPLE)
+
 kde4_add_kcfg_files(kdenlive_SRCS kdenlivesettings.kcfgc )
 QT4_ADD_DBUS_ADAPTOR(kdenlive_SRCS org.kdenlive.MainWindow.xml mainwindow.h MainWindow)
 kde4_add_executable(kdenlive ${kdenlive_SRCS} ${kdenlive_UI})
@@ -199,6 +207,8 @@ target_link_libraries(kdenlive
 if (APPLE)
   find_package(SDL REQUIRED)
   target_link_libraries(kdenlive ${SDL_LIBRARY})
+  target_link_libraries(kdenlive ${QT_QTOPENGL_LIBRARY})
+  target_link_libraries(kdenlive ${OPENGL_LIBRARIES})
 endif (APPLE)
 
 install(TARGETS kdenlive DESTINATION ${BIN_INSTALL_DIR})
index 2a1ccaa273666fa9a23532b041a4d6140d27720b..ff01bba2823e1d299f782a0f0d15609483e13548 100644 (file)
@@ -207,12 +207,14 @@ void KdenliveSettingsDialog::initDevices()
 {
     // Fill audio drivers
     m_configSdl.kcfg_audio_driver->addItem(i18n("Automatic"), QString());
+#ifndef Q_WS_MAC
     m_configSdl.kcfg_audio_driver->addItem(i18n("OSS"), "dsp");
     m_configSdl.kcfg_audio_driver->addItem(i18n("ALSA"), "alsa");
     m_configSdl.kcfg_audio_driver->addItem(i18n("PulseAudio"), "pulse");
     m_configSdl.kcfg_audio_driver->addItem(i18n("OSS with DMA access"), "dma");
     m_configSdl.kcfg_audio_driver->addItem(i18n("Esound daemon"), "esd");
     m_configSdl.kcfg_audio_driver->addItem(i18n("ARTS daemon"), "artsc");
+#endif
 
     if (!KdenliveSettings::audiodrivername().isEmpty())
         for (int i = 1; i < m_configSdl.kcfg_audio_driver->count(); i++) {
@@ -224,6 +226,7 @@ void KdenliveSettingsDialog::initDevices()
 
     // Fill video drivers
     m_configSdl.kcfg_video_driver->addItem(i18n("Automatic"), QString());
+#ifndef Q_WS_MAC
     m_configSdl.kcfg_video_driver->addItem(i18n("XVideo"), "x11");
     m_configSdl.kcfg_video_driver->addItem(i18n("X11"), "x11_noaccel");
     m_configSdl.kcfg_video_driver->addItem(i18n("XFree86 DGA 2.0"), "dga");
@@ -233,6 +236,7 @@ void KdenliveSettingsDialog::initDevices()
     m_configSdl.kcfg_video_driver->addItem(i18n("SVGAlib"), "svgalib");
     m_configSdl.kcfg_video_driver->addItem(i18n("General graphics interface"), "ggi");
     m_configSdl.kcfg_video_driver->addItem(i18n("Ascii art library"), "aalib");
+#endif
 
     // Fill the list of audio playback devices
     m_configSdl.kcfg_audio_device->addItem(i18n("Default"), QString());
index 817d072dc6c1c6540e309267514350874ceda1ed..369de55e840487e5046e24ece1aa014f7e4251c8 100644 (file)
 #include <KUrl> //new
 
 
-#if defined(__APPLE_KDE__) || defined(__DARWIN__)
-#include <SDL/SDL.h>
-#endif
-
 int main(int argc, char *argv[])
 {
     KAboutData aboutData(QByteArray("kdenlive"), QByteArray("kdenlive"),
index 6d86b82c321c9e0c3f41793d76ce794e6a52c487..8ce29546cdb344ef8ebab02f752969233383e854 100644 (file)
@@ -384,6 +384,8 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent
 void MainWindow::queryQuit()
 {
     if (queryClose()) {
+        if (m_projectMonitor) m_projectMonitor->stop();
+        if (m_clipMonitor) m_clipMonitor->stop();
         delete m_effectStack;
         delete m_activeTimeline;
         delete m_projectMonitor;
index ea0478e0731913124e64790c123ed4ff4491b0f4..88f35599e97e4afbd2467f511ee862fcfc677c8e 100644 (file)
@@ -122,10 +122,21 @@ Monitor::Monitor(QString name, MonitorManager *manager, QWidget *parent) :
 
     QVBoxLayout *rendererBox = new QVBoxLayout(m_ui.video_frame);
     rendererBox->setContentsMargins(0, 0, 0, 0);
+#ifdef Q_WS_MAC
+    m_glWidget = new VideoGLWidget(m_ui.video_frame);
+    rendererBox->addWidget(m_glWidget);
+    render = new Render(m_name, (int) m_ui.video_frame->winId(), -1, this);
+    m_glWidget->setImageAspectRatio(render->dar());
+    m_glWidget->setBackgroundColor(KdenliveSettings::window_background());
+    m_glWidget->resize(m_ui.video_frame->size());
+    connect(render, SIGNAL(showImageSignal(QImage)), m_glWidget, SLOT(showImage(QImage)));
+    m_monitorRefresh = 0;
+#else
     m_monitorRefresh = new MonitorRefresh(m_ui.video_frame);
     rendererBox->addWidget(m_monitorRefresh);
     render = new Render(m_name, (int) m_monitorRefresh->winId(), -1, this);
     m_monitorRefresh->setRenderer(render);
+#endif
 
     connect(m_ruler, SIGNAL(seekRenderer(int)), this, SLOT(slotSeek(int)));
     connect(render, SIGNAL(durationChanged(int)), this, SLOT(adjustRulerSize(int)));
@@ -142,7 +153,9 @@ Monitor::Monitor(QString name, MonitorManager *manager, QWidget *parent) :
     } else {
         connect(m_ruler, SIGNAL(zoneChanged(QPoint)), this, SLOT(setClipZone(QPoint)));
     }
+#ifndef Q_WS_MAC
     m_monitorRefresh->show();
+#endif
     kDebug() << "/////// BUILDING MONITOR, ID: " << m_ui.video_frame->winId();
 }
 
@@ -753,9 +766,13 @@ void Monitor::slotSwitchMonitorInfo(bool show)
     KdenliveSettings::setDisplayMonitorInfo(show);
     if (show) {
         if (m_overlay) return;
+#ifndef Q_WS_MAC
         m_overlay = new Overlay(m_monitorRefresh);
         m_overlay->raise();
         m_overlay->setHidden(true);
+#else
+        m_overlay = new Overlay(m_glWidget);
+#endif
     } else {
         delete m_overlay;
         m_overlay = NULL;
index 35b539e96ab48ba2d650413d324912ccd9217f87..9d7723f381bd69a0d5ef863400604385fa44e731 100644 (file)
@@ -30,6 +30,9 @@
 
 #include "gentime.h"
 #include "ui_monitor_ui.h"
+#ifdef Q_WS_MAC
+#include "videoglwidget.h"
+#endif
 
 class MonitorManager;
 class Render;
@@ -112,6 +115,9 @@ private:
     QMenu *m_configMenu;
     QMenu *m_playMenu;
     QPoint m_DragStartPosition;
+#ifdef Q_WS_MAC
+    VideoGLWidget *m_glWidget;
+#endif
     GenTime getSnapForPos(bool previous);
     bool m_frametimecode;
 
index 7b5ce6093db24085f57b304ea08c3e3e025a0fc6..7b4be874b81f173ff2d0b9bab45459fb1a0c8734 100644 (file)
@@ -56,7 +56,11 @@ 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?
     if (self->m_isBlocked) return;
-    if (mlt_properties_get_double(MLT_FRAME_PROPERTIES(frame_ptr), "_speed") == 0.0) {
+    Mlt::Frame frame(frame_ptr);
+#ifdef Q_WS_MAC
+    self->showFrame(frame);
+#endif
+    if (frame.get_double("_speed") == 0.0) {
         self->emitConsumerStopped();
     } else {
         self->emitFrameNumber(mlt_frame_get_position(frame_ptr));
@@ -76,6 +80,9 @@ Render::Render(const QString & rendererName, int winid, int /* extid */, QWidget
         m_isSplitView(false),
         m_blackClip(NULL),
         m_winid(winid)
+#ifdef Q_WS_MAC
+        , m_glWidget(0)
+#endif
 {
     kDebug() << "//////////  USING PROFILE: " << (char*)KdenliveSettings::current_profile().toUtf8().data();
 
@@ -166,7 +173,13 @@ void Render::buildConsumer()
     }
     setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 1);
 
+#ifdef Q_WS_MAC
+    m_mltConsumer = new Mlt::Consumer(*m_mltProfile , "sdl_audio");
+    m_mltConsumer->set("preview_off", 1);
+    m_mltConsumer->set("preview_format", mlt_image_rgb24a);
+#else
     m_mltConsumer = new Mlt::Consumer(*m_mltProfile , "sdl_preview");
+#endif
     m_mltConsumer->set("resize", 1);
     m_mltConsumer->set("window_id", m_winid);
     m_mltConsumer->set("terminate_on_pause", 1);
@@ -1431,6 +1444,19 @@ void Render::exportCurrentFrame(KUrl url, bool /*notify*/)
     //if (notify) QApplication::postEvent(qApp->activeWindow(), new UrlEvent(url, 10003));
 }
 
+#ifdef Q_WS_MAC
+void Render::showFrame(Mlt::Frame& frame)
+{
+    mlt_image_format format = mlt_image_rgb24a;
+    int width = 0;
+    int height = 0;
+    const uchar* image = frame.get_image(format, width, height);
+    QImage qimage(width, height, QImage::Format_ARGB32);
+    memcpy(qimage.scanLine(0), image, width * height * 4);
+    emit showImageSignal(qimage);
+}
+#endif
+
 /** MLT PLAYLIST DIRECT MANIPULATON  **/
 
 
index 71319916f36f6fdab030905687d3952dab7b3443..74011cb25802e6b1948c6024bf84274950abdc6b 100644 (file)
 #include <QList>
 #include <QEvent>
 
+#ifdef Q_WS_MAC
+#include "videoglwidget.h"
+#endif
+
 
 /**Render encapsulates the client side of the interface to a renderer.
 From Kdenlive's point of view, you treat the Render object as the
@@ -205,6 +209,9 @@ Q_OBJECT public:
     const QList <Mlt::Producer *> producersList();
     void updatePreviewSettings();
     void setDropFrames(bool show);
+#ifdef Q_WS_MAC
+    void showFrame(Mlt::Frame&);
+#endif
 
 private:   // Private attributes & methods
     /** The name of this renderer - useful to identify the renderes by what they do - e.g. background rendering, workspace monitor, etc... */
@@ -232,6 +239,10 @@ private:   // Private attributes & methods
     /** A human-readable description of this renderer. */
     int m_winid;
 
+#ifdef Q_WS_MAC
+    VideoGLWidget *m_glWidget;
+#endif
+
     /** Sets the description of this renderer to desc. */
     void closeMlt();
     void mltCheckLength(Mlt::Tractor *tractor);
@@ -274,6 +285,8 @@ signals:   // Signals
     void removeInvalidClip(const QString &, bool replaceProducer);
     void refreshDocumentProducers();
     void blockMonitors();
+    /** Used on OS X - emitted when a frame's image is to be shown. */
+    void showImageSignal(QImage);
 
 public slots:  // Public slots
     /** Start Consumer */
diff --git a/src/videoglwidget.cpp b/src/videoglwidget.cpp
new file mode 100644 (file)
index 0000000..8fa6b34
--- /dev/null
@@ -0,0 +1,117 @@
+
+#include <QtGui>
+#include <QtOpenGL>
+#include "videoglwidget.h"
+
+#ifndef GL_TEXTURE_RECTANGLE_EXT
+#define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV
+#endif
+
+VideoGLWidget::VideoGLWidget(QWidget *parent)
+ : QGLWidget(parent)
+ , m_image_width(0)
+ , m_image_height(0)
+ , m_texture(0)
+ , m_display_ratio(4.0/3.0)
+ , m_backgroundColor(Qt::gray)
+{
+}
+
+VideoGLWidget::~VideoGLWidget()
+{
+    makeCurrent();
+    if (m_texture)
+        glDeleteTextures(1, &m_texture);
+}
+
+QSize VideoGLWidget::minimumSizeHint() const
+{
+    return QSize(40, 30);
+}
+
+QSize VideoGLWidget::sizeHint() const
+{
+    return QSize(400, 300);
+}
+
+void VideoGLWidget::initializeGL()
+{
+    qglClearColor(m_backgroundColor);
+    glShadeModel(GL_FLAT);
+    glDisable(GL_DEPTH_TEST);
+    glDisable(GL_CULL_FACE);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_DITHER);
+    glDisable(GL_BLEND);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+}
+
+void VideoGLWidget::resizeGL(int width, int height)
+{
+    double this_aspect = (double) width / height;
+
+    // Special case optimisation to negate odd effect of sample aspect ratio
+    // not corresponding exactly with image resolution.
+    if ((int)(this_aspect * 1000) == (int)(m_display_ratio * 1000))
+    {
+        w = width;
+        h = height;
+    }
+    // Use OpenGL to normalise sample aspect ratio
+    else if (height * m_display_ratio > width)
+    {
+        w = width;
+        h = width / m_display_ratio;
+    }
+    else
+    {
+        w = height * m_display_ratio;
+        h = height;
+    }
+    x = (width - w) / 2;
+    y = (height - h) / 2;
+
+    glViewport(0, 0, width, height);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluOrtho2D(0, width, height, 0);
+    glMatrixMode(GL_MODELVIEW);
+}
+
+void VideoGLWidget::paintGL()
+{
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    if (m_texture)
+    {
+        glEnable(GL_TEXTURE_RECTANGLE_EXT);
+        glBegin(GL_QUADS);
+            glTexCoord2i(0, 0);
+            glVertex2i(x, y);
+            glTexCoord2i(m_image_width, 0);
+            glVertex2i(x + w, y);
+            glTexCoord2i(m_image_width, m_image_height);
+            glVertex2i(x + w, y + h);
+            glTexCoord2i(0, m_image_height);
+            glVertex2i(x, y + h);
+        glEnd();
+        glDisable(GL_TEXTURE_RECTANGLE_EXT);
+    }
+}
+
+void VideoGLWidget::showImage(QImage image)
+{
+    m_image_width = image.width();
+    m_image_height = image.height();
+
+    makeCurrent();
+    if (m_texture)
+        glDeleteTextures(1, &m_texture);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image_width);
+    glGenTextures(1, &m_texture);
+    glBindTexture(GL_TEXTURE_RECTANGLE_EXT, m_texture);
+    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA8, m_image_width, m_image_height, 0, GL_RGBA,
+        GL_UNSIGNED_BYTE, image.bits());
+    updateGL();
+}
diff --git a/src/videoglwidget.h b/src/videoglwidget.h
new file mode 100644 (file)
index 0000000..9b089da
--- /dev/null
@@ -0,0 +1,40 @@
+
+#ifndef VIDEOGLWIDGET_H
+#define VIDEOGLWIDGET_H
+
+#include <QGLWidget>
+
+class VideoGLWidget : public QGLWidget
+{
+    Q_OBJECT
+
+public:
+    VideoGLWidget(QWidget *parent = 0);
+    ~VideoGLWidget();
+
+    QSize minimumSizeHint() const;
+    QSize sizeHint() const;
+    void setImageAspectRatio(double ratio) {
+        m_display_ratio = ratio;
+    }
+    void setBackgroundColor(QColor color) {
+        m_backgroundColor = color;
+    }
+
+private:
+    int x, y, w, h;
+    int m_image_width, m_image_height;
+    GLuint m_texture;
+    double m_display_ratio;
+    QColor m_backgroundColor;
+
+public slots:
+    void showImage(QImage image);
+
+protected:
+    void initializeGL();
+    void resizeGL(int width, int height);
+    void paintGL();
+};
+
+#endif