diff --git a/DestinationGLCanvas.cpp b/DestinationGLCanvas.cpp index ee6646d..5f8e1d2 100644 --- a/DestinationGLCanvas.cpp +++ b/DestinationGLCanvas.cpp @@ -22,7 +22,8 @@ #include "MainWindow.h" DestinationGLCanvas::DestinationGLCanvas(MainWindow* mainWindow, QWidget* parent, const QGLWidget * shareWidget) -: MapperGLCanvas(mainWindow, parent, shareWidget) +: MapperGLCanvas(mainWindow, parent, shareWidget), + _displayCrosshair(false) { } @@ -58,5 +59,19 @@ void DestinationGLCanvas::doDraw(QPainter* painter) } glPopMatrix(); + + // Display crosshair cursor. + if (_displayCrosshair) + { + const QPoint& cursorPosition = QCursor::pos(); + const QRect& geo = geometry(); + if (geo.contains(cursorPosition)) + { + painter->setPen(MM::CONTROL_COLOR); + painter->drawLine(cursorPosition.x(), 0, cursorPosition.x(), geo.height()); + painter->drawLine(0, cursorPosition.y(), geo.width(), cursorPosition.y()); + } + } + } diff --git a/DestinationGLCanvas.h b/DestinationGLCanvas.h index cfd270a..bbd5d45 100644 --- a/DestinationGLCanvas.h +++ b/DestinationGLCanvas.h @@ -36,8 +36,14 @@ public: virtual Shape* getShapeFromMappingId(uid mappingId); + void setDisplayCrosshair(bool displayCrosshair) { + _displayCrosshair = displayCrosshair; + } + private: virtual void doDraw(QPainter* painter); + + bool _displayCrosshair; }; #endif /* DESTINATIONGLCANVAS_H_ */ diff --git a/MM.cpp b/MM.cpp index 5dbd57f..7ce372d 100644 --- a/MM.cpp +++ b/MM.cpp @@ -32,7 +32,7 @@ const QColor MM::WHITE("#f6f5f5"); const QColor MM::BLUE_GRAY("#323541"); const QColor MM::DARK_GRAY("#272a36"); -const QColor MM::CONTROL_COLOR(BLUE_GRAY); +const QColor MM::CONTROL_COLOR(WHITE); const QBrush MM::VERTEX_BACKGROUND(QColor(CONTROL_COLOR.red(), CONTROL_COLOR.green(), CONTROL_COLOR.blue(), 63)); const QPen MM::SHAPE_STROKE(QBrush(CONTROL_COLOR), SHAPE_STROKE_WIDTH); const QPen MM::SHAPE_INNER_STROKE(QBrush(CONTROL_COLOR), SHAPE_INNER_STROKE_WIDTH); diff --git a/MainWindow.cpp b/MainWindow.cpp index bcdd54d..de0d506 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -651,7 +651,7 @@ bool MainWindow::clearProject() } uid MainWindow::createMediaPaint(uid paintId, QString uri, float x, float y, - bool isImage, bool live) + bool isImage, bool live, double rate) { // Cannot create image with already existing id. if (Paint::getUidAllocator().exists(paintId)) @@ -662,8 +662,9 @@ uid MainWindow::createMediaPaint(uid paintId, QString uri, float x, float y, Texture* tex = 0; if (isImage) tex = new Image(uri, paintId); - else - tex = new Media(uri, live, paintId); + else { + tex = new Media(uri, live, rate, paintId); + } // Create new image with corresponding ID. tex->setPosition(x, y); @@ -2262,3 +2263,28 @@ bool MainWindow::setTextureUri(int texture_id, const std::string &uri) return success; } +bool MainWindow::setTextureRate(int texture_id, double rate) +{ + Paint::ptr paint = this->mappingManager->getPaintById(texture_id); + if (paint.get() == NULL) + { + std::cout << "No such texture paint id " << texture_id << std::endl; + return false; + } + else + { + if (paint->getType() == "media") + { + Media *media = (Media *) paint.get(); // FIXME: use sharedptr cast + videoTimer->stop(); + media->setRate(rate); + videoTimer->start(); + } + else + { + std::cout << "Paint id " << texture_id << " is not a media texture." << std::endl; + return false; + } + } + return true; +} diff --git a/MainWindow.h b/MainWindow.h index b25d46b..92775af 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -118,7 +118,7 @@ public slots: bool clearProject(); /// Create or replace a media paint (or image). - uid createMediaPaint(uid paintId, QString uri, float x, float y, bool isImage, bool live); + uid createMediaPaint(uid paintId, QString uri, float x, float y, bool isImage, bool live=false, double rate=1.0); /// Create or replace a color paint. uid createColorPaint(uid paintId, QColor color); @@ -174,6 +174,7 @@ public slots: public: bool setTextureUri(int texture_id, const std::string &uri); + bool setTextureRate(int texture_id, double rate); private: // Internal methods. ////////////////////////////////////////////////////////////////////////////////////// diff --git a/MediaImpl.cpp b/MediaImpl.cpp index d3f3506..748414a 100644 --- a/MediaImpl.cpp +++ b/MediaImpl.cpp @@ -635,6 +635,7 @@ void MediaImpl::_checkMessages() // Pipeline has prerolled/ready to play /////////////// case GST_MESSAGE_ASYNC_DONE: + if (!_isMovieReady()) { // Check if seeking is allowed. gint64 start, end; @@ -647,8 +648,6 @@ void MediaImpl::_checkMessages() g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (start), GST_TIME_ARGS (end)); - // Update playback rate. - _updateRate(); } else { diff --git a/OscInterface.cpp b/OscInterface.cpp index 131e936..34146d4 100644 --- a/OscInterface.cpp +++ b/OscInterface.cpp @@ -218,6 +218,13 @@ void OscInterface::applyOscCommand(MainWindow &main_window, QVariantList & comma //std::cout << "load /mapmap/paint/media/load " << paint_id << " " << image_uri << std::endl; main_window.setTextureUri(paint_id, image_uri); } + else if (path == "/mapmap/paint/media/rate" && typetags == "if") + { + int paint_id = command.at(2).toInt(); + float rate = command.at(3).toDouble(); + //std::cout << "load /mapmap/paint/media/load " << paint_id << " " << image_uri << std::endl; + main_window.setTextureRate(paint_id, rate); + } else { std::cout << "Unhandled OSC message: "; diff --git a/OutputGLWindow.cpp b/OutputGLWindow.cpp index 2b68991..d39ac6c 100644 --- a/OutputGLWindow.cpp +++ b/OutputGLWindow.cpp @@ -89,6 +89,10 @@ void OutputGLWindow::keyPressEvent(QKeyEvent *event) void OutputGLWindow::setFullScreen(bool fullscreen) { + // Activate crosshair in fullscreen mode. + setCursorVisible(!fullscreen); + canvas->setDisplayCrosshair(fullscreen); + // NOTE: The showFullScreen() method does not work well under Ubuntu Linux. The code below fixes the issue. // Notice that there might be problems with the fullscreen in other OS / window managers. If so, please add // the code to fix those issues here. diff --git a/Paint.cpp b/Paint.cpp index 47a6c69..2b76099 100644 --- a/Paint.cpp +++ b/Paint.cpp @@ -51,12 +51,13 @@ bool Image::setUri(const QString &uri) /* Implementation of the Video class */ -Media::Media(const QString uri_, bool live, uid id): +Media::Media(const QString uri_, bool live, double rate, uid id): Texture(id), uri(uri_), impl_(NULL) { impl_ = new MediaImpl(uri_, live); + setRate(rate); } // vertigo @@ -122,12 +123,12 @@ bool Media::bitsHaveChanged() const void Media::setRate(double rate) { - impl_->setRate(rate); + impl_->setRate(rate / 100.0); } double Media::getRate() const { - return impl_->getRate(); + return impl_->getRate() * 100.0; } bool Media::hasVideoSupport() diff --git a/Paint.h b/Paint.h index 0dc5057..19b69f6 100644 --- a/Paint.h +++ b/Paint.h @@ -203,7 +203,7 @@ class Media : public Texture protected: QString uri; public: - Media(const QString uri_, bool live, uid id=NULL_UID); + Media(const QString uri_, bool live, double rate, uid id=NULL_UID); virtual ~Media(); const QString getUri() const { @@ -237,7 +237,10 @@ public: virtual bool bitsHaveChanged() const; - virtual void setRate(double rate=1.0); + /// Sets playback rate (in %). Negative values mean reverse playback. + virtual void setRate(double rate=100.0); + + /// Returns playback rate. double getRate() const; diff --git a/PaintGui.cpp b/PaintGui.cpp index cf197d9..9e4059c 100644 --- a/PaintGui.cpp +++ b/PaintGui.cpp @@ -109,9 +109,10 @@ MediaGui::MediaGui(Paint::ptr paint) _mediaRateItem = _variantManager->addProperty(QVariant::Double, tr("Speed (%)")); - _mediaRateItem->setAttribute("minimum", 0.1); + double rate = media->getRate(); // we need to save it because the call to setAttribute will set it to minimum + _mediaRateItem->setAttribute("minimum", 1); _mediaRateItem->setAttribute("decimals", 1); - _mediaRateItem->setValue(100.0); + _mediaRateItem->setValue(rate); // _mediaReverseItem = _variantManager->addProperty(QVariant::Bool, // tr("Reverse")); @@ -133,7 +134,7 @@ void MediaGui::setValue(QtProperty* property, const QVariant& value) if (property == _mediaRateItem) { double rateSign = (media->getRate() <= 0 ? -1 : +1); - media->setRate(value.toDouble() / 100.0 * rateSign); + media->setRate(value.toDouble()); emit valueChanged(_paint); } // else if (property == _mediaReverseItem) diff --git a/ProjectReader.cpp b/ProjectReader.cpp index 5023c77..18809de 100644 --- a/ProjectReader.cpp +++ b/ProjectReader.cpp @@ -92,11 +92,12 @@ void ProjectReader::parsePaint(const QDomElement& paint) if (paintAttrType == "media" || paintAttrType == "image") { - QString uri = paint.firstChildElement("uri").text(); - QString x = paint.firstChildElement("x").text(); - QString y = paint.firstChildElement("y").text(); + QString uri = paint.firstChildElement("uri").text(); + QString x = paint.firstChildElement("x").text(); + QString y = paint.firstChildElement("y").text(); + QString rate = paint.firstChildElement("rate").text(); - uid id = _window->createMediaPaint(paintAttrId.toInt(), uri, x.toFloat(), y.toFloat(), paintAttrType == "image", false); + uid id = _window->createMediaPaint(paintAttrId.toInt(), uri, x.toFloat(), y.toFloat(), paintAttrType == "image", false, rate.toDouble()); if (id == NULL_UID) _xml.raiseError(QObject::tr("Cannot create media with uri %1.").arg(uri)); } diff --git a/ProjectWriter.cpp b/ProjectWriter.cpp index 3c5790e..5dcaeca 100644 --- a/ProjectWriter.cpp +++ b/ProjectWriter.cpp @@ -75,6 +75,12 @@ void ProjectWriter::writeItem(Paint *item) _xml.writeTextElement("y", os.str().c_str()); } + { + std::ostringstream os; + os << media->getRate(); + _xml.writeTextElement("rate", os.str().c_str()); + } + _xml.writeEndElement(); //_xml.writeEmptyElement("hello"); }