diff options
author | João Abecasis <joao.abecasis@nokia.com> | 2010-11-23 11:26:54 (GMT) |
---|---|---|
committer | João Abecasis <joao.abecasis@nokia.com> | 2010-11-23 11:26:54 (GMT) |
commit | 802498fcd43558a10bb7477d3957cdd27fd8ec09 (patch) | |
tree | c40ddd859b032ffa7ed9c6df1173312c0bb1947d /demos | |
parent | 901fee7e610ec53f744416aeeca89c4605923120 (diff) | |
parent | 538e7b8ddf45936bb274ed3230b591b3459edfa7 (diff) | |
download | Qt-802498fcd43558a10bb7477d3957cdd27fd8ec09.zip Qt-802498fcd43558a10bb7477d3957cdd27fd8ec09.tar.gz Qt-802498fcd43558a10bb7477d3957cdd27fd8ec09.tar.bz2 |
Merge remote branch 'qt/master' into file-engine-refactor
Conflicts:
demos/declarative/minehunt/minehunt.pro
src/corelib/io/io.pri
src/corelib/io/qfsfileengine.cpp
src/corelib/io/qfsfileengine_unix.cpp
src/corelib/io/qfsfileengine_win.cpp
src/s60installs/bwins/QtCoreu.def
src/s60installs/bwins/QtDeclarativeu.def
src/s60installs/bwins/QtGuiu.def
src/s60installs/eabi/QtCoreu.def
src/s60installs/eabi/QtDeclarativeu.def
src/s60installs/eabi/QtGuiu.def
tests/auto/qapplication/test/test.pro
tests/auto/qaudioinput/qaudioinput.pro
tests/auto/qaudiooutput/qaudiooutput.pro
tests/auto/qchar/qchar.pro
tests/auto/qdiriterator/qdiriterator.pro
tests/auto/qsound/qsound.pro
Diffstat (limited to 'demos')
53 files changed, 744 insertions, 703 deletions
diff --git a/demos/books/books.pro b/demos/books/books.pro index a5e44e5..06718d1 100644 --- a/demos/books/books.pro +++ b/demos/books/books.pro @@ -16,8 +16,8 @@ INSTALLS += target sources symbian: include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) wince*: { - CONFIG(debug, debug|release):sqlPlugins.sources = $$QT_BUILD_TREE/plugins/sqldrivers/*d4.dll - CONFIG(release, debug|release):sqlPlugins.sources = $$QT_BUILD_TREE/plugins/sqldrivers/*[^d]4.dll + CONFIG(debug, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*d4.dll + CONFIG(release, debug|release):sqlPlugins.files = $$QT_BUILD_TREE/plugins/sqldrivers/*[^d]4.dll sqlPlugins.path = sqldrivers DEPLOYMENT += sqlPlugins } diff --git a/demos/chip/view.cpp b/demos/chip/view.cpp index 7af3074..d6a641e 100644 --- a/demos/chip/view.cpp +++ b/demos/chip/view.cpp @@ -48,15 +48,29 @@ #include <qmath.h> +void GraphicsView::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() & Qt::ControlModifier) { + if (e->delta() > 0) + view->zoomIn(6); + else + view->zoomOut(6); + e->accept(); + } else { + QGraphicsView::wheelEvent(e); + } +} + View::View(const QString &name, QWidget *parent) : QFrame(parent) { setFrameStyle(Sunken | StyledPanel); - graphicsView = new QGraphicsView; + graphicsView = new GraphicsView(this); graphicsView->setRenderHint(QPainter::Antialiasing, false); graphicsView->setDragMode(QGraphicsView::RubberBandDrag); graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); QSize iconSize(size, size); @@ -111,6 +125,15 @@ View::View(const QString &name, QWidget *parent) // Label layout QHBoxLayout *labelLayout = new QHBoxLayout; label = new QLabel(name); + label2 = new QLabel(tr("Pointer Mode")); + selectModeButton = new QToolButton; + selectModeButton->setText(tr("Select")); + selectModeButton->setCheckable(true); + selectModeButton->setChecked(true); + dragModeButton = new QToolButton; + dragModeButton->setText(tr("Drag")); + dragModeButton->setCheckable(true); + dragModeButton->setChecked(false); antialiasButton = new QToolButton; antialiasButton->setText(tr("Antialiasing")); antialiasButton->setCheckable(true); @@ -126,8 +149,17 @@ View::View(const QString &name, QWidget *parent) printButton = new QToolButton; printButton->setIcon(QIcon(QPixmap(":/fileprint.png"))); + QButtonGroup *pointerModeGroup = new QButtonGroup; + pointerModeGroup->setExclusive(true); + pointerModeGroup->addButton(selectModeButton); + pointerModeGroup->addButton(dragModeButton); + labelLayout->addWidget(label); labelLayout->addStretch(); + labelLayout->addWidget(label2); + labelLayout->addWidget(selectModeButton); + labelLayout->addWidget(dragModeButton); + labelLayout->addStretch(); labelLayout->addWidget(antialiasButton); labelLayout->addWidget(openGlButton); labelLayout->addWidget(printButton); @@ -145,6 +177,8 @@ View::View(const QString &name, QWidget *parent) connect(rotateSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); connect(graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); connect(graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + connect(selectModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + connect(dragModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); connect(antialiasButton, SIGNAL(toggled(bool)), this, SLOT(toggleAntialiasing())); connect(openGlButton, SIGNAL(toggled(bool)), this, SLOT(toggleOpenGL())); connect(rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft())); @@ -158,7 +192,7 @@ View::View(const QString &name, QWidget *parent) QGraphicsView *View::view() const { - return graphicsView; + return static_cast<QGraphicsView *>(graphicsView); } void View::resetView() @@ -188,6 +222,14 @@ void View::setupMatrix() setResetButtonEnabled(); } +void View::togglePointerMode() +{ + graphicsView->setDragMode(selectModeButton->isChecked() + ? QGraphicsView::RubberBandDrag + : QGraphicsView::ScrollHandDrag); + graphicsView->setInteractive(selectModeButton->isChecked()); +} + void View::toggleOpenGL() { #ifndef QT_NO_OPENGL @@ -212,14 +254,14 @@ void View::print() #endif } -void View::zoomIn() +void View::zoomIn(int level) { - zoomSlider->setValue(zoomSlider->value() + 1); + zoomSlider->setValue(zoomSlider->value() + level); } -void View::zoomOut() +void View::zoomOut(int level) { - zoomSlider->setValue(zoomSlider->value() - 1); + zoomSlider->setValue(zoomSlider->value() - level); } void View::rotateLeft() diff --git a/demos/chip/view.h b/demos/chip/view.h index 8047b8b..67c7675 100644 --- a/demos/chip/view.h +++ b/demos/chip/view.h @@ -43,12 +43,27 @@ #define VIEW_H #include <QFrame> +#include <QGraphicsView> -QT_FORWARD_DECLARE_CLASS(QGraphicsView) QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QSlider) QT_FORWARD_DECLARE_CLASS(QToolButton) +class View; + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(View *v) : QGraphicsView(), view(v) { } + +protected: + void wheelEvent(QWheelEvent *); + +private: + View *view; +}; + class View : public QFrame { Q_OBJECT @@ -57,22 +72,27 @@ public: QGraphicsView *view() const; +public slots: + void zoomIn(int level = 1); + void zoomOut(int level = 1); + private slots: void resetView(); void setResetButtonEnabled(); void setupMatrix(); + void togglePointerMode(); void toggleOpenGL(); void toggleAntialiasing(); void print(); - - void zoomIn(); - void zoomOut(); void rotateLeft(); void rotateRight(); - + private: - QGraphicsView *graphicsView; + GraphicsView *graphicsView; QLabel *label; + QLabel *label2; + QToolButton *selectModeButton; + QToolButton *dragModeButton; QToolButton *openGlButton; QToolButton *antialiasButton; QToolButton *printButton; diff --git a/demos/declarative/minehunt/minehunt.cpp b/demos/declarative/minehunt/minehunt.cpp index 9c82f30..aaaaaac 100644 --- a/demos/declarative/minehunt/minehunt.cpp +++ b/demos/declarative/minehunt/minehunt.cpp @@ -195,6 +195,7 @@ bool MinehuntGame::flip(int row, int col) won = false; hasWonChanged(); setPlaying(false); + return true; } remaining--; @@ -202,6 +203,7 @@ bool MinehuntGame::flip(int row, int col) won = true; hasWonChanged(); setPlaying(false); + return true; } return true; } @@ -209,7 +211,7 @@ bool MinehuntGame::flip(int row, int col) bool MinehuntGame::flag(int row, int col) { TileData *t = tile(row, col); - if(!t) + if(!t || !playing || t->flipped()) return false; t->setHasFlag(!t->hasFlag()); diff --git a/demos/declarative/minehunt/minehunt.pro b/demos/declarative/minehunt/minehunt.pro index 4cf1441..d23bb05 100644 --- a/demos/declarative/minehunt/minehunt.pro +++ b/demos/declarative/minehunt/minehunt.pro @@ -1,7 +1,6 @@ TEMPLATE = app TARGET = minehunt QT += declarative -CONFIG += qt plugin # Input HEADERS += minehunt.h @@ -18,7 +17,7 @@ symbian:{ TARGET.EPOCALLOWDLLDATA = 1 TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) - qmlminehuntfiles.sources = MinehuntCore minehunt.qml + qmlminehuntfiles.files = MinehuntCore minehunt.qml DEPLOYMENT += qmlminehuntfiles } -
\ No newline at end of file + diff --git a/demos/declarative/samegame/SamegameCore/Button.qml b/demos/declarative/samegame/SamegameCore/Button.qml index 7fb7b65..140b196 100644 --- a/demos/declarative/samegame/SamegameCore/Button.qml +++ b/demos/declarative/samegame/SamegameCore/Button.qml @@ -48,7 +48,7 @@ Rectangle { signal clicked - width: buttonLabel.width + 20; height: buttonLabel.height + 6 + width: buttonLabel.width + 20; height: buttonLabel.height + 20 smooth: true border { width: 1; color: Qt.darker(activePalette.button) } radius: 8 @@ -70,6 +70,6 @@ Rectangle { MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() } Text { - id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText + id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText; font.pixelSize: 24 } } diff --git a/demos/declarative/samegame/SamegameCore/samegame.js b/demos/declarative/samegame/SamegameCore/samegame.js index 9266767..e618a10 100755 --- a/demos/declarative/samegame/SamegameCore/samegame.js +++ b/demos/declarative/samegame/SamegameCore/samegame.js @@ -9,12 +9,14 @@ var scoresURL = ""; var gameDuration; var component = Qt.createComponent(blockSrc); -//Index function used instead of a 2D array -function index(column,row) { - return column + (row * maxColumn); +// Index function used instead of a 2D array +function index(column, row) +{ + return column + row * maxColumn; } -function timeStr(msecs) { +function timeStr(msecs) +{ var secs = Math.floor(msecs/1000); var m = Math.floor(secs/60); var ret = "" + m + "m " + (secs%60) + "s"; @@ -23,47 +25,48 @@ function timeStr(msecs) { function startNewGame() { - //Delete blocks from previous game - for(var i = 0; i<maxIndex; i++){ - if(board[i] != null) + // Delete blocks from previous game + for (var i = 0; i < maxIndex; i++) { + if (board[i] != null) board[i].destroy(); } - //Calculate board size + // Calculate board size maxColumn = Math.floor(gameCanvas.width/gameCanvas.blockSize); maxRow = Math.floor(gameCanvas.height/gameCanvas.blockSize); - maxIndex = maxRow*maxColumn; + maxIndex = maxRow * maxColumn; - //Close dialogs + // Close dialogs nameInputDialog.forceClose(); dialog.forceClose(); - //Initialize Board + // Initialize Board board = new Array(maxIndex); gameCanvas.score = 0; - for(var column=0; column<maxColumn; column++){ - for(var row=0; row<maxRow; row++){ - board[index(column,row)] = null; - createBlock(column,row); + for (var column = 0; column < maxColumn; column++) { + for (var row = 0; row < maxRow; row++) { + board[index(column, row)] = null; + createBlock(column, row); } } gameDuration = new Date(); } -var fillFound;//Set after a floodFill call to the number of blocks found -var floodBoard;//Set to 1 if the floodFill reaches off that node -//NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope +var fillFound; // Set after a floodFill call to the number of blocks found +var floodBoard; // Set to 1 if the floodFill reaches off that node + +// NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope function handleClick(x,y) { var column = Math.floor(x/gameCanvas.blockSize); var row = Math.floor(y/gameCanvas.blockSize); - if(column >= maxColumn || column < 0 || row >= maxRow || row < 0) + if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return; - if(board[index(column, row)] == null) + if (board[index(column, row)] == null) return; - //If it's a valid block, remove it and all connected (does nothing if it's not connected) + // If it's a valid block, remove it and all connected (does nothing if it's not connected) floodFill(column,row, -1); - if(fillFound <= 0) + if (fillFound <= 0) return; gameCanvas.score += (fillFound - 1) * (fillFound - 1); shuffleDown(); @@ -72,65 +75,65 @@ function handleClick(x,y) function floodFill(column,row,type) { - if(board[index(column, row)] == null) + if (board[index(column, row)] == null) return; var first = false; - if(type == -1){ + if (type == -1) { first = true; type = board[index(column,row)].type; - - //Flood fill initialization + + // Flood fill initialization fillFound = 0; floodBoard = new Array(maxIndex); } - if(column >= maxColumn || column < 0 || row >= maxRow || row < 0) + if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return; - if(floodBoard[index(column, row)] == 1 || (!first && type != board[index(column,row)].type)) + if (floodBoard[index(column, row)] == 1 || (!first && type != board[index(column, row)].type)) return; floodBoard[index(column, row)] = 1; - floodFill(column+1,row,type); - floodFill(column-1,row,type); - floodFill(column,row+1,type); - floodFill(column,row-1,type); - if(first==true && fillFound == 0) - return;//Can't remove single blocks - board[index(column,row)].dying = true; - board[index(column,row)] = null; + floodFill(column + 1, row, type); + floodFill(column - 1, row, type); + floodFill(column, row + 1, type); + floodFill(column, row - 1, type); + if (first == true && fillFound == 0) + return; // Can't remove single blocks + board[index(column, row)].dying = true; + board[index(column, row)] = null; fillFound += 1; } function shuffleDown() { - //Fall down - for(var column=0; column<maxColumn; column++){ + // Fall down + for (var column = 0; column < maxColumn; column++) { var fallDist = 0; - for(var row=maxRow-1; row>=0; row--){ - if(board[index(column,row)] == null){ + for (var row = maxRow - 1; row >= 0; row--) { + if (board[index(column,row)] == null) { fallDist += 1; - }else{ - if(fallDist > 0){ - var obj = board[index(column,row)]; - obj.y = (row+fallDist) * gameCanvas.blockSize; - board[index(column,row+fallDist)] = obj; - board[index(column,row)] = null; + } else { + if (fallDist > 0) { + var obj = board[index(column, row)]; + obj.y = (row + fallDist) * gameCanvas.blockSize; + board[index(column, row + fallDist)] = obj; + board[index(column, row)] = null; } } } } - //Fall to the left + // Fall to the left fallDist = 0; - for(column=0; column<maxColumn; column++){ - if(board[index(column, maxRow - 1)] == null){ + for (column = 0; column < maxColumn; column++) { + if (board[index(column, maxRow - 1)] == null) { fallDist += 1; - }else{ - if(fallDist > 0){ - for(row=0; row<maxRow; row++){ - obj = board[index(column,row)]; - if(obj == null) + } else { + if (fallDist > 0) { + for (row = 0; row < maxRow; row++) { + obj = board[index(column, row)]; + if (obj == null) continue; - obj.x = (column-fallDist) * gameCanvas.blockSize; - board[index(column-fallDist,row)] = obj; - board[index(column,row)] = null; + obj.x = (column - fallDist) * gameCanvas.blockSize; + board[index(column - fallDist,row)] = obj; + board[index(column, row)] = null; } } } @@ -139,58 +142,59 @@ function shuffleDown() function victoryCheck() { - //awards bonuses for no blocks left + // Awards bonuses for no blocks left var deservesBonus = true; - for(var column=maxColumn-1; column>=0; column--) - if(board[index(column, maxRow - 1)] != null) + for (var column = maxColumn - 1; column >= 0; column--) + if (board[index(column, maxRow - 1)] != null) deservesBonus = false; - if(deservesBonus) + if (deservesBonus) gameCanvas.score += 500; - //Checks for game over - if(deservesBonus || !(floodMoveCheck(0,maxRow-1, -1))){ + // Checks for game over + if (deservesBonus || !(floodMoveCheck(0, maxRow - 1, -1))) { gameDuration = new Date() - gameDuration; nameInputDialog.show("You won! Please enter your name: "); nameInputDialog.initialWidth = nameInputDialog.text.width + 20; - if(nameInputDialog.name == "") + if (nameInputDialog.name == "") nameInputDialog.width = nameInputDialog.initialWidth; - nameInputDialog.text.opacity = 0;//Just a spacer + nameInputDialog.text.opacity = 0; // Just a spacer } } -//only floods up and right, to see if it can find adjacent same-typed blocks +// Only floods up and right, to see if it can find adjacent same-typed blocks function floodMoveCheck(column, row, type) { - if(column >= maxColumn || column < 0 || row >= maxRow || row < 0) + if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return false; - if(board[index(column, row)] == null) + if (board[index(column, row)] == null) return false; var myType = board[index(column, row)].type; - if(type == myType) + if (type == myType) return true; return floodMoveCheck(column + 1, row, myType) || - floodMoveCheck(column, row - 1, board[index(column,row)].type); + floodMoveCheck(column, row - 1, board[index(column, row)].type); } -function createBlock(column,row){ +function createBlock(column,row) +{ // Note that we don't wait for the component to become ready. This will // only work if the block QML is a local file. Otherwise the component will // not be ready immediately. There is a statusChanged signal on the // component you could use if you want to wait to load remote files. - if(component.status == Component.Ready){ + if (component.status == Component.Ready) { var dynamicObject = component.createObject(gameCanvas); - if(dynamicObject == null){ + if (dynamicObject == null) { console.log("error creating block"); console.log(component.errorString()); return false; } dynamicObject.type = Math.floor(Math.random() * 3); - dynamicObject.x = column*gameCanvas.blockSize; - dynamicObject.y = row*gameCanvas.blockSize; + dynamicObject.x = column * gameCanvas.blockSize; + dynamicObject.y = row * gameCanvas.blockSize; dynamicObject.width = gameCanvas.blockSize; dynamicObject.height = gameCanvas.blockSize; dynamicObject.spawned = true; - board[index(column,row)] = dynamicObject; - }else{ + board[index(column, row)] = dynamicObject; + } else { console.log("error loading block component"); console.log(component.errorString()); return false; @@ -198,23 +202,35 @@ function createBlock(column,row){ return true; } -function saveHighScore(name) { - if(scoresURL!="") +function saveHighScore(name) +{ + if (scoresURL != "") sendHighScore(name); - //OfflineStorage - var db = openDatabaseSync("SameGameScores", "1.0", "Local SameGame High Scores",100); + // Offline storage + var db = openDatabaseSync( + "SameGameScores", + "1.0", + "Local SameGame High Scores", + 100 + ); var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)"; - var data = [name, gameCanvas.score, maxColumn+"x"+maxRow ,Math.floor(gameDuration/1000)]; + var data = [ + name, + gameCanvas.score, + maxColumn + "x" + maxRow, + Math.floor(gameDuration / 1000) + ]; db.transaction( function(tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)'); tx.executeSql(dataStr, data); - //Only show results for the current grid size - var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "'+maxColumn+"x"+maxRow+'" ORDER BY score desc LIMIT 10'); + // Only show results for the current grid size + var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "' + + maxColumn + "x" + maxRow + '" ORDER BY score desc LIMIT 10'); var r = "\nHIGH SCORES for this grid size\n\n" - for(var i = 0; i < rs.rows.length; i++){ - r += (i+1)+". " + rs.rows.item(i).name +' got ' + for (var i = 0; i < rs.rows.length; i++) { + r += (i+1) + ". " + rs.rows.item(i).name + ' got ' + rs.rows.item(i).score + ' points in ' + rs.rows.item(i).time + ' seconds.\n'; } @@ -223,13 +239,15 @@ function saveHighScore(name) { ); } -function sendHighScore(name) { +function sendHighScore(name) +{ var postman = new XMLHttpRequest() - var postData = "name="+name+"&score="+gameCanvas.score - +"&gridSize="+maxColumn+"x"+maxRow +"&time="+Math.floor(gameDuration/1000); + var postData = "name=" + name + "&score=" + gameCanvas.score + + "&gridSize=" + maxColumn + "x" + maxRow + + "&time=" + Math.floor(gameDuration / 1000); postman.open("POST", scoresURL, true); postman.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - postman.onreadystatechange = function() { + postman.onreadystatechange = function() { if (postman.readyState == postman.DONE) { dialog.show("Your score has been uploaded."); } diff --git a/demos/declarative/samegame/samegame.qml b/demos/declarative/samegame/samegame.qml index f66c40e..ab49c04 100644 --- a/demos/declarative/samegame/samegame.qml +++ b/demos/declarative/samegame/samegame.qml @@ -92,9 +92,7 @@ Rectangle { enabled: nameInputDialog.initialWidth != 0 } - onOpened: nameInputText.focus = true; onClosed: { - nameInputText.focus = false; if (nameInputText.text != "") Logic.saveHighScore(nameInputText.text); } @@ -116,7 +114,7 @@ Rectangle { TextInput { id: nameInputText anchors { verticalCenter: parent.verticalCenter; left: dialogText.right } - focus: false + focus: visible autoScroll: false maximumLength: 24 onTextChanged: { @@ -133,7 +131,7 @@ Rectangle { Rectangle { id: toolBar - width: parent.width; height: 32 + width: parent.width; height: 58 color: activePalette.window anchors.bottom: screen.bottom @@ -156,6 +154,7 @@ Rectangle { anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter } text: "Score: " + gameCanvas.score font.bold: true + font.pixelSize: 24 color: activePalette.windowText } } diff --git a/demos/declarative/snake/content/pics/pause.png b/demos/declarative/snake/content/pics/pause.png Binary files differnew file mode 100644 index 0000000..056d97d --- /dev/null +++ b/demos/declarative/snake/content/pics/pause.png diff --git a/demos/declarative/snake/content/snake.js b/demos/declarative/snake/content/snake.js index 2a99aa8..837b82a 100644 --- a/demos/declarative/snake/content/snake.js +++ b/demos/declarative/snake/content/snake.js @@ -39,7 +39,7 @@ function startNewGame() return; } - if (heartbeat.running) { + if (activeGame) { endGame(); startNewGameTimer.running = true; return; @@ -93,7 +93,7 @@ function startNewGame() function endGame() { - heartbeat.running = false; + activeGame = false; for(var i in snake) snake[i].dying = true; if (cookie) { diff --git a/demos/declarative/snake/snake.qml b/demos/declarative/snake/snake.qml index 5cbf1be..585c0b2 100644 --- a/demos/declarative/snake/snake.qml +++ b/demos/declarative/snake/snake.qml @@ -47,6 +47,7 @@ Rectangle { id: screen; SystemPalette { id: activePalette } color: activePalette.window + property bool activeGame: false property int gridSize : 34 property int margin: 4 @@ -75,6 +76,7 @@ Rectangle { Timer { id: heartbeat; interval: heartbeatInterval; + running: activeGame && runtime.isActiveWindow repeat: true onTriggered: { Logic.move() } } @@ -94,7 +96,16 @@ Rectangle { Timer { id: startHeartbeatTimer; interval: 1000 ; - onTriggered: { state = "running"; heartbeat.running = true;} + onTriggered: { state = "running"; activeGame = true; } + } + + Image{ + id: pauseDialog + z: 1 + source: "content/pics/pause.png" + anchors.centerIn: parent; + //opacity is deliberately not animated + opacity: activeGame && !runtime.isActiveWindow } Image { diff --git a/demos/declarative/twitter/twitter.qml b/demos/declarative/twitter/twitter.qml index 4495523..74bab37 100644 --- a/demos/declarative/twitter/twitter.qml +++ b/demos/declarative/twitter/twitter.qml @@ -78,7 +78,7 @@ Item { id: views x: 2; width: parent.width - 4 y:60 //Below the title bars - height: 380 + height: parent.height - 100 Text { id:title diff --git a/demos/demos.pro b/demos/demos.pro index fdc1e4c..362a3bc 100644 --- a/demos/demos.pro +++ b/demos/demos.pro @@ -44,7 +44,7 @@ contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, SUBDIRS += demos_boxes } -mac*: SUBDIRS += demos_macmainwindow +mac* && !qpa: SUBDIRS += demos_macmainwindow wince*|symbian|embedded|x11: SUBDIRS += demos_embedded !contains(QT_EDITION, Console):!cross_compile:!embedded:!wince*:SUBDIRS += demos_arthurplugin diff --git a/demos/embedded/desktopservices/desktopservices.pro b/demos/embedded/desktopservices/desktopservices.pro index 94ddedd..e66db1c 100644 --- a/demos/embedded/desktopservices/desktopservices.pro +++ b/demos/embedded/desktopservices/desktopservices.pro @@ -7,8 +7,8 @@ SOURCES += desktopwidget.cpp contenttab.cpp linktab.cpp main.cpp RESOURCES += desktopservices.qrc -music.sources = data/*.mp3 data/*.wav -image.sources = data/*.png +music.files = data/*.mp3 data/*.wav +image.files = data/*.png target.path = $$[QT_INSTALL_DEMOS]/embedded/desktopservices sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro diff --git a/demos/embedded/fluidlauncher/fluidlauncher.pro b/demos/embedded/fluidlauncher/fluidlauncher.pro index ca74c38..0799ed9 100644 --- a/demos/embedded/fluidlauncher/fluidlauncher.pro +++ b/demos/embedded/fluidlauncher/fluidlauncher.pro @@ -33,7 +33,7 @@ wince*{ BUILD_DIR = debug } - executables.sources = \ + executables.files = \ $$QT_BUILD_TREE/demos/embedded/embeddedsvgviewer/$${BUILD_DIR}/embeddedsvgviewer.exe \ $$QT_BUILD_TREE/demos/embedded/styledemo/$${BUILD_DIR}/styledemo.exe \ $$QT_BUILD_TREE/demos/deform/$${BUILD_DIR}/deform.exe \ @@ -45,10 +45,10 @@ wince*{ executables.path = . - files.sources = $$PWD/screenshots $$PWD/slides $$PWD/../embeddedsvgviewer/shapes.svg + files.files = $$PWD/screenshots $$PWD/slides $$PWD/../embeddedsvgviewer/shapes.svg files.path = . - config.sources = $$PWD/config_wince/config.xml + config.files = $$PWD/config_wince/config.xml config.path = . DEPLOYMENT += config files executables @@ -79,7 +79,7 @@ symbian { } } - executables.sources = \ + executables.files = \ $$QT_BUILD_TREE/demos/embedded/styledemo/styledemo.exe \ $$QT_BUILD_TREE/demos/deform/deform.exe \ $$QT_BUILD_TREE/demos/pathstroke/pathstroke.exe \ @@ -97,7 +97,7 @@ symbian { executables.path = /sys/bin - reg_resource.sources = \ + reg_resource.files = \ $$regResourceDir(demos/embedded/styledemo/styledemo_reg.rsc) \ $$regResourceDir(demos/deform/deform_reg.rsc) \ $$regResourceDir(demos/pathstroke/pathstroke_reg.rsc) \ @@ -114,17 +114,17 @@ symbian { $$regResourceDir(demos/embedded/flightinfo/flightinfo_reg.rsc) contains(QT_CONFIG, phonon) { - reg_resource.sources += $$regResourceDir(demos/qmediaplayer/qmediaplayer_reg.rsc) + reg_resource.files += $$regResourceDir(demos/qmediaplayer/qmediaplayer_reg.rsc) } contains(QT_CONFIG, multimedia) { - reg_resource.sources += $$regResourceDir(demos/spectrum/app/spectrum_reg.rsc) + reg_resource.files += $$regResourceDir(demos/spectrum/app/spectrum_reg.rsc) } reg_resource.path = $$REG_RESOURCE_IMPORT_DIR - resource.sources = \ + resource.files = \ $$appResourceDir(demos/embedded/styledemo/styledemo.rsc) \ $$appResourceDir(demos/deform/deform.rsc) \ $$appResourceDir(demos/pathstroke/pathstroke.rsc) \ @@ -143,7 +143,7 @@ symbian { resource.path = $$APP_RESOURCE_DIR - mifs.sources = \ + mifs.files = \ $$appResourceDir(demos/embedded/fluidlauncher/fluidlauncher.mif) \ $$appResourceDir(demos/embedded/styledemo/styledemo.mif) \ $$appResourceDir(demos/deform/deform.mif) \ @@ -162,28 +162,28 @@ symbian { mifs.path = $$APP_RESOURCE_DIR contains(QT_CONFIG, svg) { - executables.sources += \ + executables.files += \ $$QT_BUILD_TREE/demos/embedded/embeddedsvgviewer/embeddedsvgviewer.exe \ $$QT_BUILD_TREE/demos/embedded/weatherinfo/weatherinfo.exe - reg_resource.sources += \ + reg_resource.files += \ $$regResourceDir(demos/embedded/embeddedsvgviewer/embeddedsvgviewer_reg.rsc) \ $$regResourceDir(demos/embedded/weatherinfo/weatherinfo_reg.rsc) - resource.sources += \ + resource.files += \ $$appResourceDir(demos/embedded/embeddedsvgviewer/embeddedsvgviewer.rsc) \ $$appResourceDir(demos/embedded/weatherinfo/weatherinfo.rsc) - mifs.sources += \ + mifs.files += \ $$appResourceDir(demos/embedded/embeddedsvgviewer/embeddedsvgviewer.mif) \ $$appResourceDir(demos/embedded/weatherinfo/weatherinfo.mif) } contains(QT_CONFIG, webkit) { - executables.sources += $$QT_BUILD_TREE/demos/embedded/anomaly/anomaly.exe - reg_resource.sources += $$regResourceDir(demos/embedded/anomaly/anomaly_reg.rsc) - resource.sources += $$appResourceDir(demos/embedded/anomaly/anomaly.rsc) - mifs.sources += \ + executables.files += $$QT_BUILD_TREE/demos/embedded/anomaly/anomaly.exe + reg_resource.files += $$regResourceDir(demos/embedded/anomaly/anomaly_reg.rsc) + resource.files += $$appResourceDir(demos/embedded/anomaly/anomaly.rsc) + mifs.files += \ $$appResourceDir(demos/embedded/anomaly/anomaly.mif) isEmpty(QT_LIBINFIX) { @@ -195,61 +195,61 @@ symbian { } contains(QT_CONFIG, phonon) { - executables.sources += $$QT_BUILD_TREE/demos/qmediaplayer/qmediaplayer.exe - resource.sources += $$appResourceDir(demos/qmediaplayer/qmediaplayer.rsc) - mifs.sources += \ + executables.files += $$QT_BUILD_TREE/demos/qmediaplayer/qmediaplayer.exe + resource.files += $$appResourceDir(demos/qmediaplayer/qmediaplayer.rsc) + mifs.files += \ $$appResourceDir(demos/qmediaplayer/qmediaplayer.mif) } contains(QT_CONFIG, multimedia) { - executables.sources += $$QT_BUILD_TREE/demos/spectrum/app/spectrum.exe - executables.sources += $$QT_BUILD_TREE/demos/spectrum/3rdparty/fftreal/fftreal.dll - resource.sources += $$appResourceDir(demos/spectrum/app/spectrum.rsc) - mifs.sources += \ + executables.files += $$QT_BUILD_TREE/demos/spectrum/app/spectrum.exe + executables.files += $$QT_BUILD_TREE/demos/spectrum/3rdparty/fftreal/fftreal.dll + resource.files += $$appResourceDir(demos/spectrum/app/spectrum.rsc) + mifs.files += \ $$appResourceDir(demos/spectrum/app/spectrum.mif) } contains(QT_CONFIG, script) { - executables.sources += $$QT_BUILD_TREE/examples/script/context2d/context2d.exe - reg_resource.sources += $$regResourceDir(examples/script/context2d/context2d_reg.rsc) - resource.sources += $$appResourceDir(examples/script/context2d/context2d.rsc) - mifs.sources += \ + executables.files += $$QT_BUILD_TREE/examples/script/context2d/context2d.exe + reg_resource.files += $$regResourceDir(examples/script/context2d/context2d_reg.rsc) + resource.files += $$appResourceDir(examples/script/context2d/context2d.rsc) + mifs.files += \ $$appResourceDir(examples/script/context2d/context2d.mif) } qmldemos = qmlcalculator qmlclocks qmldialcontrol qmleasing qmlflickr qmlphotoviewer qmltwitter contains(QT_CONFIG, declarative) { for(qmldemo, qmldemos) { - executables.sources += $$QT_BUILD_TREE/demos/embedded/$${qmldemo}/$${qmldemo}.exe - reg_resource.sources += $$regResourceDir(demos/embedded/$${qmldemo}/$${qmldemo}_reg.rsc) - resource.sources += $$appResourceDir(demos/embedded/$${qmldemo}/$${qmldemo}.rsc) - mifs.sources += $$appResourceDir(demos/embedded/$${qmldemo}/$${qmldemo}.mif) + executables.files += $$QT_BUILD_TREE/demos/embedded/$${qmldemo}/$${qmldemo}.exe + reg_resource.files += $$regResourceDir(demos/embedded/$${qmldemo}/$${qmldemo}_reg.rsc) + resource.files += $$appResourceDir(demos/embedded/$${qmldemo}/$${qmldemo}.rsc) + mifs.files += $$appResourceDir(demos/embedded/$${qmldemo}/$${qmldemo}.mif) } } - files.sources = $$PWD/screenshots $$PWD/slides + files.files = $$PWD/screenshots $$PWD/slides files.path = . - config.sources = $$PWD/config_s60/config.xml + config.files = $$PWD/config_s60/config.xml config.path = . - viewerimages.sources = $$PWD/../embeddedsvgviewer/shapes.svg + viewerimages.files = $$PWD/../embeddedsvgviewer/shapes.svg viewerimages.path = /data/images/qt/demos/embeddedsvgviewer # demos/mediaplayer make also use of these files. - desktopservices_music.sources = \ + desktopservices_music.files = \ $$PWD/../desktopservices/data/*.mp3 \ $$PWD/../desktopservices/data/*.wav desktopservices_music.path = /data/sounds - desktopservices_images.sources = $$PWD/../desktopservices/data/*.png + desktopservices_images.files = $$PWD/../desktopservices/data/*.png desktopservices_images.path = /data/images - saxbookmarks.sources = $$PWD/../../../examples/xml/saxbookmarks/frank.xbel - saxbookmarks.sources += $$PWD/../../../examples/xml/saxbookmarks/jennifer.xbel + saxbookmarks.files = $$PWD/../../../examples/xml/saxbookmarks/frank.xbel + saxbookmarks.files += $$PWD/../../../examples/xml/saxbookmarks/jennifer.xbel saxbookmarks.path = /data/qt/saxbookmarks - fluidbackup.sources = backup_registration.xml + fluidbackup.files = backup_registration.xml fluidbackup.path = /private/$$replace(TARGET.UID3, 0x,) DEPLOYMENT += config files executables viewerimages saxbookmarks reg_resource resource \ diff --git a/demos/embedded/qmlcalculator/deployment.pri b/demos/embedded/qmlcalculator/deployment.pri index a31303d..a97498e 100644 --- a/demos/embedded/qmlcalculator/deployment.pri +++ b/demos/embedded/qmlcalculator/deployment.pri @@ -4,5 +4,5 @@ symbian { qmlcalculator_uid3 = A000E3FB qmlcalculator_files.path = $$APP_PRIVATE_DIR_BASE/$$qmlcalculator_uid3 } -qmlcalculator_files.sources = $$qmlcalculator_src/calculator.qml $$qmlcalculator_src/Core +qmlcalculator_files.files = $$qmlcalculator_src/calculator.qml $$qmlcalculator_src/Core DEPLOYMENT += qmlcalculator_files diff --git a/demos/embedded/qmlclocks/deployment.pri b/demos/embedded/qmlclocks/deployment.pri index 0946733..6c6704c 100644 --- a/demos/embedded/qmlclocks/deployment.pri +++ b/demos/embedded/qmlclocks/deployment.pri @@ -4,5 +4,5 @@ symbian { qmlclocks_uid3 = A000E3FC qmlclocks_files.path = $$APP_PRIVATE_DIR_BASE/$$qmlclocks_uid3 } -qmlclocks_files.sources = $$qmlclocks_src/clocks.qml $$qmlclocks_src/content +qmlclocks_files.files = $$qmlclocks_src/clocks.qml $$qmlclocks_src/content DEPLOYMENT += qmlclocks_files diff --git a/demos/embedded/qmldialcontrol/deployment.pri b/demos/embedded/qmldialcontrol/deployment.pri index e0e72e6..a978443 100644 --- a/demos/embedded/qmldialcontrol/deployment.pri +++ b/demos/embedded/qmldialcontrol/deployment.pri @@ -4,5 +4,5 @@ symbian { qmldialcontrol_uid3 = A000E3FD qmldialcontrol_files.path = $$APP_PRIVATE_DIR_BASE/$$qmldialcontrol_uid3 } -qmldialcontrol_files.sources = $$qmldialcontrol_src/dialcontrol.qml $$qmldialcontrol_src/content +qmldialcontrol_files.files = $$qmldialcontrol_src/dialcontrol.qml $$qmldialcontrol_src/content DEPLOYMENT += qmldialcontrol_files diff --git a/demos/embedded/qmleasing/deployment.pri b/demos/embedded/qmleasing/deployment.pri index d3621cb..946fcd9 100644 --- a/demos/embedded/qmleasing/deployment.pri +++ b/demos/embedded/qmleasing/deployment.pri @@ -4,5 +4,5 @@ symbian { qmleasing_uid3 = A000E3FE qmleasing_files.path = $$APP_PRIVATE_DIR_BASE/$$qmleasing_uid3 } -qmleasing_files.sources = $$qmleasing_src/easing.qml $$qmleasing_src/content +qmleasing_files.files = $$qmleasing_src/easing.qml $$qmleasing_src/content DEPLOYMENT += qmleasing_files diff --git a/demos/embedded/qmlflickr/deployment.pri b/demos/embedded/qmlflickr/deployment.pri index b508292..a38dc95 100644 --- a/demos/embedded/qmlflickr/deployment.pri +++ b/demos/embedded/qmlflickr/deployment.pri @@ -4,5 +4,5 @@ symbian { qmlflickr_uid3 = A000E3FF qmlflickr_files.path = $$APP_PRIVATE_DIR_BASE/$$qmlflickr_uid3 } -qmlflickr_files.sources = $$qmlflickr_src/flickr.qml $$qmlflickr_src/common $$qmlflickr_src/mobile +qmlflickr_files.files = $$qmlflickr_src/flickr.qml $$qmlflickr_src/common $$qmlflickr_src/mobile DEPLOYMENT += qmlflickr_files diff --git a/demos/embedded/qmlphotoviewer/deployment.pri b/demos/embedded/qmlphotoviewer/deployment.pri index 35937a8..23882e3 100644 --- a/demos/embedded/qmlphotoviewer/deployment.pri +++ b/demos/embedded/qmlphotoviewer/deployment.pri @@ -4,5 +4,5 @@ symbian { qmlphotoviewer_uid3 = A000E400 qmlphotoviewer_files.path = $$APP_PRIVATE_DIR_BASE/$$qmlphotoviewer_uid3 } -qmlphotoviewer_files.sources = $$qmlphotoviewer_src/photoviewer.qml $$qmlphotoviewer_src/PhotoViewerCore +qmlphotoviewer_files.files = $$qmlphotoviewer_src/photoviewer.qml $$qmlphotoviewer_src/PhotoViewerCore DEPLOYMENT += qmlphotoviewer_files diff --git a/demos/embedded/qmltwitter/deployment.pri b/demos/embedded/qmltwitter/deployment.pri index 4404e33..3edc0e5 100644 --- a/demos/embedded/qmltwitter/deployment.pri +++ b/demos/embedded/qmltwitter/deployment.pri @@ -4,5 +4,5 @@ symbian { qmltwitter_uid3 = A000E401 qmltwitter_files.path = $$APP_PRIVATE_DIR_BASE/$$qmltwitter_uid3 } -qmltwitter_files.sources = $$qmltwitter_src/twitter.qml $$qmltwitter_src/TwitterCore +qmltwitter_files.files = $$qmltwitter_src/twitter.qml $$qmltwitter_src/TwitterCore DEPLOYMENT += qmltwitter_files diff --git a/demos/qmediaplayer/main.cpp b/demos/qmediaplayer/main.cpp index 02c579b..9f15e43 100644 --- a/demos/qmediaplayer/main.cpp +++ b/demos/qmediaplayer/main.cpp @@ -42,6 +42,8 @@ #include <QtGui> #include "mediaplayer.h" +const qreal DefaultVolume = -1.0; + int main (int argc, char *argv[]) { Q_INIT_RESOURCE(mediaplayer); @@ -50,36 +52,38 @@ int main (int argc, char *argv[]) app.setOrganizationName("Qt"); app.setQuitOnLastWindowClosed(true); - bool hasSmallScreen = + QString fileName; + qreal volume = DefaultVolume; + bool smallScreen = false; #ifdef Q_OS_SYMBIAN - /* On Symbian, we always want fullscreen. One reason is that it's not - * possible to launch any demos from the fluidlauncher due to a - * limitation in the emulator. */ - true -#else - false + smallScreen = true; #endif - ; - - QString fileString; - const QStringList args(app.arguments()); - /* We have a minor problem here, we accept two arguments, both are - * optional: - * - A file name - * - the option "-small-screen", so let's try to cope with that. - */ - for (int i = 0; i < args.count(); ++i) { - const QString &at = args.at(i); - if (at == QLatin1String("-small-screen")) - hasSmallScreen = true; - else if (i > 0) // We don't want the app name. - fileString = at; + QStringList args(app.arguments()); + args.removeFirst(); // remove name of executable + while (!args.empty()) { + const QString &arg = args.first(); + if (QLatin1String("-small-screen") == arg || QLatin1String("--small-screen") == arg) { + smallScreen = true; + } else if (QLatin1String("-volume") == arg || QLatin1String("--volume") == arg) { + if (!args.empty()) { + args.removeFirst(); + volume = qMax(qMin(args.first().toFloat(), float(1.0)), float(0.0)); + } + } else if (fileName.isNull()) { + fileName = arg; + } + args.removeFirst(); } - MediaPlayer player(fileString, hasSmallScreen); + MediaPlayer player; + player.setSmallScreen(smallScreen); + if (DefaultVolume != volume) + player.setVolume(volume); + if (!fileName.isNull()) + player.setFile(fileName); - if (hasSmallScreen) + if (smallScreen) player.showMaximized(); else player.show(); diff --git a/demos/qmediaplayer/mediaplayer.cpp b/demos/qmediaplayer/mediaplayer.cpp index 97a8e35..5bf7d6d 100644 --- a/demos/qmediaplayer/mediaplayer.cpp +++ b/demos/qmediaplayer/mediaplayer.cpp @@ -152,12 +152,10 @@ void MediaVideoWidget::dragEnterEvent(QDragEnterEvent *e) { } -MediaPlayer::MediaPlayer(const QString &filePath, - const bool hasSmallScreen) : +MediaPlayer::MediaPlayer() : playButton(0), nextEffect(0), settingsDialog(0), ui(0), m_AudioOutput(Phonon::VideoCategory), - m_videoWidget(new MediaVideoWidget(this)), - m_hasSmallScreen(hasSmallScreen) + m_videoWidget(new MediaVideoWidget(this)) { setWindowTitle(tr("Media Player")); setContextMenuPolicy(Qt::CustomContextMenu); @@ -346,8 +344,6 @@ MediaPlayer::MediaPlayer(const QString &filePath, m_audioOutputPath = Phonon::createPath(&m_MediaObject, &m_AudioOutput); Phonon::createPath(&m_MediaObject, m_videoWidget); - if (!filePath.isEmpty()) - setFile(filePath); resize(minimumSizeHint()); } @@ -358,7 +354,7 @@ void MediaPlayer::stateChanged(Phonon::State newstate, Phonon::State oldstate) if (oldstate == Phonon::LoadingState) { QRect videoHintRect = QRect(QPoint(0, 0), m_videoWindow.sizeHint()); QRect newVideoRect = QApplication::desktop()->screenGeometry().intersected(videoHintRect); - if (!m_hasSmallScreen) { + if (!m_smallScreen) { if (m_MediaObject.hasVideo()) { // Flush event que so that sizeHint takes the // recently shown/hidden m_videoWindow into account: @@ -466,6 +462,16 @@ void MediaPlayer::initSettingsDialog() } +void MediaPlayer::setVolume(qreal volume) +{ + m_AudioOutput.setVolume(volume); +} + +void MediaPlayer::setSmallScreen(bool smallScreen) +{ + m_smallScreen = smallScreen; +} + void MediaPlayer::effectChanged() { int currentIndex = ui->audioEffectsCombo->currentIndex(); @@ -589,7 +595,7 @@ void MediaPlayer::configureEffect() effectDialog.exec(); if (effectDialog.result() != QDialog::Accepted) { - //we need to restore the paramaters values + //we need to restore the parameters values int currentIndex = 0; foreach(Phonon::EffectParameter param, nextEffect->parameters()) { nextEffect->setParameterValue(param, savedParamValues.at(currentIndex++)); @@ -685,7 +691,7 @@ bool MediaPlayer::playPauseForDialog() // If we're running on a small screen, we want to pause the video when // popping up dialogs. We neither want to tamper with the state if the // user has paused. - if (m_hasSmallScreen && m_MediaObject.hasVideo()) { + if (m_smallScreen && m_MediaObject.hasVideo()) { if (Phonon::PlayingState == m_MediaObject.state()) { m_MediaObject.pause(); return true; diff --git a/demos/qmediaplayer/mediaplayer.h b/demos/qmediaplayer/mediaplayer.h index d6ae58b..73450fe 100644 --- a/demos/qmediaplayer/mediaplayer.h +++ b/demos/qmediaplayer/mediaplayer.h @@ -104,8 +104,7 @@ class MediaPlayer : { Q_OBJECT public: - MediaPlayer(const QString &, - const bool hasSmallScreen); + MediaPlayer(); void dragEnterEvent(QDragEnterEvent *e); void dragMoveEvent(QDragMoveEvent *e); @@ -115,6 +114,8 @@ public: void setLocation(const QString &location); void initVideoWindow(); void initSettingsDialog(); + void setVolume(qreal volume); + void setSmallScreen(bool smallScreen); public slots: void openFile(); @@ -171,7 +172,7 @@ private: Phonon::AudioOutput m_AudioOutput; MediaVideoWidget *m_videoWidget; Phonon::Path m_audioOutputPath; - const bool m_hasSmallScreen; + bool m_smallScreen; }; #endif //MEDIAPLAYER_H diff --git a/demos/qmediaplayer/qmediaplayer.pro b/demos/qmediaplayer/qmediaplayer.pro index 9407a81..8803d2e 100644 --- a/demos/qmediaplayer/qmediaplayer.pro +++ b/demos/qmediaplayer/qmediaplayer.pro @@ -27,7 +27,7 @@ DEPLOYMENT_PLUGIN += phonon_ds9 phonon_waveout symbian { TARGET.UID3 = 0xA000C613 - addFiles.sources = ../embedded/desktopservices/data/sax.mp3 + addFiles.files = ../embedded/desktopservices/data/sax.mp3 addFiles.path = /data/sounds/ DEPLOYMENT += addFiles diff --git a/demos/qtdemo/itemcircleanimation.h b/demos/qtdemo/itemcircleanimation.h index 425d2f5..7276f7f 100644 --- a/demos/qtdemo/itemcircleanimation.h +++ b/demos/qtdemo/itemcircleanimation.h @@ -61,7 +61,7 @@ public: ItemCircleAnimation(QGraphicsScene *scene = 0, QGraphicsItem *parent = 0); virtual ~ItemCircleAnimation(); - // overidden methods: + // overridden methods: QRectF boundingRect() const; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0); void hoverEnterEvent(QGraphicsSceneHoverEvent *event); diff --git a/demos/qtdemo/mainwindow.cpp b/demos/qtdemo/mainwindow.cpp index 16c5bf3..e39802a 100644 --- a/demos/qtdemo/mainwindow.cpp +++ b/demos/qtdemo/mainwindow.cpp @@ -388,7 +388,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event) s += "\nAdapt: "; s += Colors::noAdapt ? "off" : "on"; - s += "\nAdaption occured: "; + s += "\nAdaption occurred: "; s += Colors::adapted ? "yes" : "no"; s += "\nOpenGL version: "; s += Colors::glVersion; diff --git a/demos/qtdemo/mainwindow.h b/demos/qtdemo/mainwindow.h index b8cfda6..460f941 100644 --- a/demos/qtdemo/mainwindow.h +++ b/demos/qtdemo/mainwindow.h @@ -74,7 +74,7 @@ public: DemoTextItem *fpsLabel; protected: - // Overidden methods: + // Overridden methods: void showEvent(QShowEvent *event); void keyPressEvent(QKeyEvent *event); void resizeEvent(QResizeEvent *event); diff --git a/demos/qtdemo/qmlShell.qml b/demos/qtdemo/qmlShell.qml index 2764865..8ca06f1 100644 --- a/demos/qtdemo/qmlShell.qml +++ b/demos/qtdemo/qmlShell.qml @@ -85,7 +85,7 @@ Item { MouseArea{ anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton - onClicked: loader.focus=true;/* and don't propogate to the 'exit' area*/ + onClicked: loader.focus=true;/* and don't propagate to the 'exit' area*/ } Rectangle{ id: innerFrame diff --git a/demos/qtdemo/textbutton.h b/demos/qtdemo/textbutton.h index 55b4edc..039f923 100644 --- a/demos/qtdemo/textbutton.h +++ b/demos/qtdemo/textbutton.h @@ -61,7 +61,7 @@ public: QGraphicsScene *scene = 0, QGraphicsItem *parent = 0, BUTTONTYPE color = SIDEBAR); virtual ~TextButton(); - // overidden methods: + // overridden methods: virtual QRectF boundingRect() const; virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0){}; virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); diff --git a/demos/qtdemo/xml/examples.xml b/demos/qtdemo/xml/examples.xml index 27f72bb..b94d2b8 100644 --- a/demos/qtdemo/xml/examples.xml +++ b/demos/qtdemo/xml/examples.xml @@ -19,7 +19,6 @@ <example filename="sub-attaq" name="Sub-attaq" /> <example filename="spectrum" name="Spectrum Analyzer" /> <example filename="declarative/minehunt" name="Minehunt"/> - <example filename="declarative/snake" name="Snake" executable="false" qml="true"/> <example filename="deform" name="Vector Deformation" /> <example filename="books" name="Books" /> <example filename="mainwindow" name="Main Window" /> diff --git a/demos/spectrum/3rdparty/fftreal/fftreal.pro b/demos/spectrum/3rdparty/fftreal/fftreal.pro index 6305af4..e5093ba 100644 --- a/demos/spectrum/3rdparty/fftreal/fftreal.pro +++ b/demos/spectrum/3rdparty/fftreal/fftreal.pro @@ -40,7 +40,7 @@ symbian { macx { CONFIG += lib_bundle } else { - !symbian: DESTDIR = ../.. + !symbian: DESTDIR = ../..$${spectrum_build_dir} } # Install diff --git a/demos/spectrum/app/app.pro b/demos/spectrum/app/app.pro index 4fe8b6d..a75b41a 100644 --- a/demos/spectrum/app/app.pro +++ b/demos/spectrum/app/app.pro @@ -65,7 +65,7 @@ symbian { LIBS += -F$${fftreal_dir} LIBS += -framework fftreal } else { - LIBS += -L.. + LIBS += -L..$${spectrum_build_dir} LIBS += -lfftreal } } @@ -86,15 +86,13 @@ symbian { !contains(DEFINES, DISABLE_FFT) { # Include FFTReal DLL in the SIS file - fftreal.sources = ../fftreal.dll + fftreal.files = ../fftreal.dll fftreal.path = !:/sys/bin DEPLOYMENT += fftreal } } else { + DESTDIR = ..$${spectrum_build_dir} macx { - # Specify directory in which to create spectrum.app bundle - DESTDIR = .. - !contains(DEFINES, DISABLE_FFT) { # Relocate fftreal.framework into spectrum.app bundle framework_dir = ../spectrum.app/Contents/Frameworks @@ -110,10 +108,7 @@ symbian { ../spectrum.app/Contents/MacOS/spectrum } } else { - # Specify directory in which to create spectrum application - DESTDIR = .. - - unix: { + linux-g++*: { # Provide relative path from application to fftreal library QMAKE_LFLAGS += -Wl,--rpath=\\\$\$ORIGIN } diff --git a/demos/spectrum/app/engine.cpp b/demos/spectrum/app/engine.cpp index 119a0e3..cd847fe 100644 --- a/demos/spectrum/app/engine.cpp +++ b/demos/spectrum/app/engine.cpp @@ -85,6 +85,7 @@ Engine::Engine(QObject *parent) , m_state(QAudio::StoppedState) , m_generateTone(false) , m_file(0) + , m_analysisFile(0) , m_availableAudioInputDevices (QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) , m_audioInputDevice(QAudioDeviceInfo::defaultInputDevice()) @@ -96,15 +97,19 @@ Engine::Engine(QObject *parent) , m_audioOutputDevice(QAudioDeviceInfo::defaultOutputDevice()) , m_audioOutput(0) , m_playPosition(0) + , m_bufferPosition(0) + , m_bufferLength(0) , m_dataLength(0) + , m_levelBufferLength(0) , m_rmsLevel(0.0) , m_peakLevel(0.0) - , m_spectrumLengthBytes(0) + , m_spectrumBufferLength(0) , m_spectrumAnalyser() , m_spectrumPosition(0) , m_count(0) { qRegisterMetaType<FrequencySpectrum>("FrequencySpectrum"); + qRegisterMetaType<WindowFunction>("WindowFunction"); CHECKED_CONNECT(&m_spectrumAnalyser, SIGNAL(spectrumChanged(FrequencySpectrum)), this, @@ -132,34 +137,33 @@ Engine::~Engine() bool Engine::loadFile(const QString &fileName) { + reset(); bool result = false; - m_generateTone = false; - - Q_ASSERT(!fileName.isEmpty()); + Q_ASSERT(!m_generateTone); Q_ASSERT(!m_file); - m_file = new QFile(fileName, this); - m_file->setFileName(fileName); - Q_ASSERT(m_file->exists()); - if (m_file->open(QFile::ReadOnly)) { - m_wavFile.readHeader(*m_file); - if (isPCMS16LE(m_wavFile.format())) { + Q_ASSERT(!fileName.isEmpty()); + m_file = new WavFile(this); + if (m_file->open(fileName)) { + if (isPCMS16LE(m_file->fileFormat())) { result = initialize(); } else { emit errorMessage(tr("Audio format not supported"), - formatToString(m_wavFile.format())); + formatToString(m_file->fileFormat())); } } else { emit errorMessage(tr("Could not open file"), fileName); } - - delete m_file; - m_file = 0; - + if (result) { + m_analysisFile = new WavFile(this); + m_analysisFile->open(fileName); + } return result; } bool Engine::generateTone(const Tone &tone) { + reset(); + Q_ASSERT(!m_generateTone); Q_ASSERT(!m_file); m_generateTone = true; m_tone = tone; @@ -172,6 +176,7 @@ bool Engine::generateTone(const Tone &tone) bool Engine::generateSweptTone(qreal amplitude) { + Q_ASSERT(!m_generateTone); Q_ASSERT(!m_file); m_generateTone = true; m_tone.startFreq = 1; @@ -185,41 +190,18 @@ bool Engine::generateSweptTone(qreal amplitude) bool Engine::initializeRecord() { + reset(); ENGINE_DEBUG << "Engine::initializeRecord"; + Q_ASSERT(!m_generateTone); Q_ASSERT(!m_file); m_generateTone = false; m_tone = SweptTone(); return initialize(); } -qint64 Engine::bufferDuration() const -{ - return BufferDurationUs; -} - -qint64 Engine::dataDuration() const +qint64 Engine::bufferLength() const { - qint64 result = 0; - if (QAudioFormat() != m_format) - result = audioDuration(m_format, m_dataLength); - return result; -} - -qint64 Engine::audioBufferLength() const -{ - qint64 length = 0; - if (QAudio::ActiveState == m_state || QAudio::IdleState == m_state) { - Q_ASSERT(QAudioFormat() != m_format); - switch (m_mode) { - case QAudio::AudioInput: - length = m_audioInput->bufferSize(); - break; - case QAudio::AudioOutput: - length = m_audioOutput->bufferSize(); - break; - } - } - return length; + return m_file ? m_file->size() : m_bufferLength; } void Engine::setWindowFunction(WindowFunction type) @@ -252,7 +234,7 @@ void Engine::startRecording() this, SLOT(audioNotify())); m_count = 0; m_dataLength = 0; - emit dataDurationChanged(0); + emit dataLengthChanged(0); m_audioInputIODevice = m_audioInput->start(); CHECKED_CONNECT(m_audioInputIODevice, SIGNAL(readyRead()), this, SLOT(audioDataReady())); @@ -275,7 +257,6 @@ void Engine::startPlayback() } else { m_spectrumAnalyser.cancelCalculation(); spectrumChanged(0, 0, FrequencySpectrum()); - setPlayPosition(0, true); stopRecording(); m_mode = QAudio::AudioOutput; @@ -284,10 +265,17 @@ void Engine::startPlayback() CHECKED_CONNECT(m_audioOutput, SIGNAL(notify()), this, SLOT(audioNotify())); m_count = 0; - m_audioOutputIODevice.close(); - m_audioOutputIODevice.setBuffer(&m_buffer); - m_audioOutputIODevice.open(QIODevice::ReadOnly); - m_audioOutput->start(&m_audioOutputIODevice); + if (m_file) { + m_file->seek(0); + m_bufferPosition = 0; + m_dataLength = 0; + m_audioOutput->start(m_file); + } else { + m_audioOutputIODevice.close(); + m_audioOutputIODevice.setBuffer(&m_buffer); + m_audioOutputIODevice.open(QIODevice::ReadOnly); + m_audioOutput->start(&m_audioOutputIODevice); + } } } } @@ -332,40 +320,55 @@ void Engine::audioNotify() { switch (m_mode) { case QAudio::AudioInput: { - const qint64 recordPosition = - qMin(BufferDurationUs, m_audioInput->processedUSecs()); + const qint64 recordPosition = qMin(m_bufferLength, audioLength(m_format, m_audioInput->processedUSecs())); setRecordPosition(recordPosition); - - // Calculate level of most recently captured data - qint64 levelLength = audioLength(m_format, LevelWindowUs); - levelLength = qMin(m_dataLength, levelLength); - const qint64 levelPosition = m_dataLength - levelLength; - calculateLevel(levelPosition, levelLength); - - // Calculate spectrum of most recently captured data - if (m_dataLength >= m_spectrumLengthBytes) { - const qint64 spectrumPosition = m_dataLength - m_spectrumLengthBytes; + const qint64 levelPosition = m_dataLength - m_levelBufferLength; + if (levelPosition >= 0) + calculateLevel(levelPosition, m_levelBufferLength); + if (m_dataLength >= m_spectrumBufferLength) { + const qint64 spectrumPosition = m_dataLength - m_spectrumBufferLength; calculateSpectrum(spectrumPosition); } + emit bufferChanged(0, m_dataLength, m_buffer); } break; case QAudio::AudioOutput: { - const qint64 playPosition = - qMin(dataDuration(), m_audioOutput->processedUSecs()); - setPlayPosition(playPosition); - - qint64 analysisPosition = audioLength(m_format, playPosition); - - // Calculate level of data starting at current playback position - const qint64 levelLength = audioLength(m_format, LevelWindowUs); - if (analysisPosition + levelLength < m_dataLength) - calculateLevel(analysisPosition, levelLength); - - if (analysisPosition + m_spectrumLengthBytes < m_dataLength) - calculateSpectrum(analysisPosition); - - if (dataDuration() == playPosition) - stopPlayback(); + const qint64 playPosition = audioLength(m_format, m_audioOutput->processedUSecs()); + setPlayPosition(qMin(bufferLength(), playPosition)); + const qint64 levelPosition = playPosition - m_levelBufferLength; + const qint64 spectrumPosition = playPosition - m_spectrumBufferLength; + if (m_file) { + if (levelPosition > m_bufferPosition || + spectrumPosition > m_bufferPosition || + qMax(m_levelBufferLength, m_spectrumBufferLength) > m_dataLength) { + m_bufferPosition = 0; + m_dataLength = 0; + // Data needs to be read into m_buffer in order to be analysed + const qint64 readPos = qMax(qint64(0), qMin(levelPosition, spectrumPosition)); + const qint64 readEnd = qMin(m_analysisFile->size(), qMax(levelPosition + m_levelBufferLength, spectrumPosition + m_spectrumBufferLength)); + const qint64 readLen = readEnd - readPos + audioLength(m_format, WaveformWindowDuration); + qDebug() << "Engine::audioNotify [1]" + << "analysisFileSize" << m_analysisFile->size() + << "readPos" << readPos + << "readLen" << readLen; + if (m_analysisFile->seek(readPos + m_analysisFile->headerLength())) { + m_buffer.resize(readLen); + m_bufferPosition = readPos; + m_dataLength = m_analysisFile->read(m_buffer.data(), readLen); + qDebug() << "Engine::audioNotify [2]" << "bufferPosition" << m_bufferPosition << "dataLength" << m_dataLength; + } else { + qDebug() << "Engine::audioNotify [2]" << "file seek error"; + } + emit bufferChanged(m_bufferPosition, m_dataLength, m_buffer); + } + } else { + if (playPosition >= m_dataLength) + stopPlayback(); + } + if (levelPosition >= 0 && levelPosition + m_levelBufferLength < m_bufferPosition + m_dataLength) + calculateLevel(levelPosition, m_levelBufferLength); + if (spectrumPosition >= 0 && spectrumPosition + m_spectrumBufferLength < m_bufferPosition + m_dataLength) + calculateSpectrum(spectrumPosition); } break; } @@ -376,27 +379,32 @@ void Engine::audioStateChanged(QAudio::State state) ENGINE_DEBUG << "Engine::audioStateChanged from" << m_state << "to" << state; - if (QAudio::StoppedState == state) { - // Check error - QAudio::Error error = QAudio::NoError; - switch (m_mode) { - case QAudio::AudioInput: - error = m_audioInput->error(); - break; - case QAudio::AudioOutput: - error = m_audioOutput->error(); - break; - } - if (QAudio::NoError != error) { - reset(); - return; + if (QAudio::IdleState == state && m_file && m_file->pos() == m_file->size()) { + stopPlayback(); + } else { + if (QAudio::StoppedState == state) { + // Check error + QAudio::Error error = QAudio::NoError; + switch (m_mode) { + case QAudio::AudioInput: + error = m_audioInput->error(); + break; + case QAudio::AudioOutput: + error = m_audioOutput->error(); + break; + } + if (QAudio::NoError != error) { + reset(); + return; + } } + setState(state); } - setState(state); } void Engine::audioDataReady() { + Q_ASSERT(0 == m_bufferPosition); const qint64 bytesReady = m_audioInput->bytesReady(); const qint64 bytesSpace = m_buffer.size() - m_dataLength; const qint64 bytesToRead = qMin(bytesReady, bytesSpace); @@ -407,9 +415,7 @@ void Engine::audioDataReady() if (bytesRead) { m_dataLength += bytesRead; - - const qint64 duration = audioDuration(m_format, m_dataLength); - emit dataDurationChanged(duration); + emit dataLengthChanged(dataLength()); } if (m_buffer.size() == m_dataLength) @@ -419,9 +425,7 @@ void Engine::audioDataReady() void Engine::spectrumChanged(const FrequencySpectrum &spectrum) { ENGINE_DEBUG << "Engine::spectrumChanged" << "pos" << m_spectrumPosition; - const qint64 positionUs = audioDuration(m_format, m_spectrumPosition); - const qint64 lengthUs = audioDuration(m_format, m_spectrumLengthBytes); - emit spectrumChanged(positionUs, lengthUs, spectrum); + emit spectrumChanged(m_spectrumPosition, m_spectrumBufferLength, spectrum); } @@ -429,12 +433,8 @@ void Engine::spectrumChanged(const FrequencySpectrum &spectrum) // Private functions //----------------------------------------------------------------------------- -void Engine::reset() +void Engine::resetAudioDevices() { - stopRecording(); - stopPlayback(); - setState(QAudio::AudioInput, QAudio::StoppedState); - setFormat(QAudioFormat()); delete m_audioInput; m_audioInput = 0; m_audioInputIODevice = 0; @@ -442,55 +442,71 @@ void Engine::reset() delete m_audioOutput; m_audioOutput = 0; setPlayPosition(0); - m_buffer.clear(); - m_dataLength = 0; m_spectrumPosition = 0; - emit dataDurationChanged(0); setLevel(0.0, 0.0, 0); } +void Engine::reset() +{ + stopRecording(); + stopPlayback(); + setState(QAudio::AudioInput, QAudio::StoppedState); + setFormat(QAudioFormat()); + m_generateTone = false; + delete m_file; + m_file = 0; + delete m_analysisFile; + m_analysisFile = 0; + m_buffer.clear(); + m_bufferPosition = 0; + m_bufferLength = 0; + m_dataLength = 0; + emit dataLengthChanged(0); + resetAudioDevices(); +} + bool Engine::initialize() { bool result = false; - reset(); + QAudioFormat format = m_format; if (selectFormat()) { - const qint64 bufferLength = audioLength(m_format, BufferDurationUs); - m_buffer.resize(bufferLength); - m_buffer.fill(0); - emit bufferDurationChanged(BufferDurationUs); - - if (m_generateTone) { - if (0 == m_tone.endFreq) { - const qreal nyquist = nyquistFrequency(m_format); - m_tone.endFreq = qMin(qreal(SpectrumHighFreq), nyquist); - } - - // Call function defined in utils.h, at global scope - ::generateTone(m_tone, m_format, m_buffer); - m_dataLength = m_buffer.size(); - emit dataDurationChanged(bufferDuration()); - setRecordPosition(bufferDuration()); - result = true; - } else if (m_file) { - const qint64 length = m_wavFile.readData(*m_file, m_buffer, m_format); - if (length) { - m_dataLength = length; - emit dataDurationChanged(dataDuration()); - setRecordPosition(dataDuration()); + if (m_format != format) { + resetAudioDevices(); + if (m_file) { + emit bufferLengthChanged(bufferLength()); + emit dataLengthChanged(dataLength()); + emit bufferChanged(0, 0, m_buffer); + setRecordPosition(bufferLength()); result = true; + } else { + m_bufferLength = audioLength(m_format, BufferDurationUs); + m_buffer.resize(m_bufferLength); + m_buffer.fill(0); + emit bufferLengthChanged(bufferLength()); + if (m_generateTone) { + if (0 == m_tone.endFreq) { + const qreal nyquist = nyquistFrequency(m_format); + m_tone.endFreq = qMin(qreal(SpectrumHighFreq), nyquist); + } + // Call function defined in utils.h, at global scope + ::generateTone(m_tone, m_format, m_buffer); + m_dataLength = m_bufferLength; + emit dataLengthChanged(dataLength()); + emit bufferChanged(0, m_dataLength, m_buffer); + setRecordPosition(m_bufferLength); + result = true; + } else { + emit bufferChanged(0, 0, m_buffer); + m_audioInput = new QAudioInput(m_audioInputDevice, m_format, this); + m_audioInput->setNotifyInterval(NotifyIntervalMs); + result = true; + } } - } else { - m_audioInput = new QAudioInput(m_audioInputDevice, m_format, this); - m_audioInput->setNotifyInterval(NotifyIntervalMs); - result = true; + m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this); + m_audioOutput->setNotifyInterval(NotifyIntervalMs); } - - m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this); - m_audioOutput->setNotifyInterval(NotifyIntervalMs); - m_spectrumLengthBytes = SpectrumLengthSamples * - (m_format.sampleSize() / 8) * m_format.channels(); } else { if (m_file) emit errorMessage(tr("Audio format not supported"), @@ -501,6 +517,8 @@ bool Engine::initialize() emit errorMessage(tr("No common input / output format found"), ""); } + ENGINE_DEBUG << "Engine::initialize" << "m_bufferLength" << m_bufferLength; + ENGINE_DEBUG << "Engine::initialize" << "m_dataLength" << m_dataLength; ENGINE_DEBUG << "Engine::initialize" << "format" << m_format; return result; @@ -510,21 +528,15 @@ bool Engine::selectFormat() { bool foundSupportedFormat = false; - if (m_file) { - // Header is read from the WAV file; just need to check whether - // it is supported by the audio output device - QAudioFormat format = m_wavFile.format(); - if (m_audioOutputDevice.isFormatSupported(m_wavFile.format())) { - setFormat(m_wavFile.format()); + if (m_file || QAudioFormat() != m_format) { + QAudioFormat format = m_format; + if (m_file) + // Header is read from the WAV file; just need to check whether + // it is supported by the audio output device + format = m_file->fileFormat(); + if (m_audioOutputDevice.isFormatSupported(format)) { + setFormat(format); foundSupportedFormat = true; - } else { - // Try flipping mono <-> stereo - const int channels = (format.channels() == 1) ? 2 : 1; - format.setChannels(channels); - if (m_audioOutputDevice.isFormatSupported(format)) { - setFormat(format); - foundSupportedFormat = true; - } } } else { @@ -648,12 +660,12 @@ void Engine::calculateLevel(qint64 position, qint64 length) Q_UNUSED(position) Q_UNUSED(length) #else - Q_ASSERT(position + length <= m_dataLength); + Q_ASSERT(position + length <= m_bufferPosition + m_dataLength); qreal peakLevel = 0.0; qreal sum = 0.0; - const char *ptr = m_buffer.constData() + position; + const char *ptr = m_buffer.constData() + position - m_bufferPosition; const char *const end = ptr + length; while (ptr < end) { const qint16 value = *reinterpret_cast<const qint16*>(ptr); @@ -679,18 +691,18 @@ void Engine::calculateSpectrum(qint64 position) #ifdef DISABLE_SPECTRUM Q_UNUSED(position) #else - Q_ASSERT(position + m_spectrumLengthBytes <= m_dataLength); - Q_ASSERT(0 == m_spectrumLengthBytes % 2); // constraint of FFT algorithm + Q_ASSERT(position + m_spectrumBufferLength <= m_bufferPosition + m_dataLength); + Q_ASSERT(0 == m_spectrumBufferLength % 2); // constraint of FFT algorithm // QThread::currentThread is marked 'for internal use only', but // we're only using it for debug output here, so it's probably OK :) ENGINE_DEBUG << "Engine::calculateSpectrum" << QThread::currentThread() - << "count" << m_count << "pos" << position << "len" << m_spectrumLengthBytes + << "count" << m_count << "pos" << position << "len" << m_spectrumBufferLength << "spectrumAnalyser.isReady" << m_spectrumAnalyser.isReady(); if(m_spectrumAnalyser.isReady()) { - m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position, - m_spectrumLengthBytes); + m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position - m_bufferPosition, + m_spectrumBufferLength); m_spectrumPosition = position; m_spectrumAnalyser.calculate(m_spectrumBuffer, m_format); } @@ -701,6 +713,9 @@ void Engine::setFormat(const QAudioFormat &format) { const bool changed = (format != m_format); m_format = format; + m_levelBufferLength = audioLength(m_format, LevelWindowUs); + m_spectrumBufferLength = SpectrumLengthSamples * + (m_format.sampleSize() / 8) * m_format.channels(); if (changed) emit formatChanged(m_format); } diff --git a/demos/spectrum/app/engine.h b/demos/spectrum/app/engine.h index b6fe3ed..c97083e 100644 --- a/demos/spectrum/app/engine.h +++ b/demos/spectrum/app/engine.h @@ -91,12 +91,6 @@ public: QAudio::State state() const { return m_state; } /** - * \return Reference to internal audio buffer - * \note This reference is valid for the lifetime of the Engine - */ - const QByteArray& buffer() const { return m_buffer; } - - /** * \return Current audio format * \note May be QAudioFormat() if engine is not initialized */ @@ -129,7 +123,7 @@ public: /** * Position of the audio input device. - * \return Position in microseconds. + * \return Position in bytes. */ qint64 recordPosition() const { return m_recordPosition; } @@ -147,27 +141,21 @@ public: /** * Position of the audio output device. - * \return Position in microseconds. + * \return Position in bytes. */ qint64 playPosition() const { return m_playPosition; } /** * Length of the internal engine buffer. - * \return Buffer length in microseconds. + * \return Buffer length in bytes. */ - qint64 bufferDuration() const; + qint64 bufferLength() const; /** * Amount of data held in the buffer. - * \return Data duration in microseconds. + * \return Data length in bytes. */ - qint64 dataDuration() const; - - /** - * Returns the size of the underlying audio buffer in bytes. - * This should be an approximation of the capture latency. - */ - qint64 audioBufferLength() const; + qint64 dataLength() const { return m_dataLength; } /** * Set window function applied to audio data before spectral analysis. @@ -203,23 +191,23 @@ signals: * Length of buffer has changed. * \param duration Duration in microseconds */ - void bufferDurationChanged(qint64 duration); + void bufferLengthChanged(qint64 duration); /** * Amount of data in buffer has changed. - * \param duration Duration of data in microseconds + * \param Length of data in bytes */ - void dataDurationChanged(qint64 duration); + void dataLengthChanged(qint64 duration); /** * Position of the audio input device has changed. - * \param position Position in microseconds + * \param position Position in bytes */ void recordPositionChanged(qint64 position); /** * Position of the audio output device has changed. - * \param position Position in microseconds + * \param position Position in bytes */ void playPositionChanged(qint64 position); @@ -227,18 +215,25 @@ signals: * Level changed * \param rmsLevel RMS level in range 0.0 - 1.0 * \param peakLevel Peak level in range 0.0 - 1.0 - * \param numSamples Number of audio samples analysed + * \param numSamples Number of audio samples analyzed */ void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples); /** * Spectrum has changed. - * \param position Position of start of window in microseconds - * \param length Length of window in microseconds + * \param position Position of start of window in bytes + * \param length Length of window in bytes * \param spectrum Resulting frequency spectrum */ void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + /** + * Buffer containing audio data has changed. + * \param position Position of start of buffer in bytes + * \param buffer Buffer + */ + void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer); + private slots: void audioNotify(); void audioStateChanged(QAudio::State state); @@ -246,6 +241,7 @@ private slots: void spectrumChanged(const FrequencySpectrum &spectrum); private: + void resetAudioDevices(); bool initialize(); bool selectFormat(); void stopRecording(); @@ -275,8 +271,10 @@ private: bool m_generateTone; SweptTone m_tone; - QFile* m_file; - WavFile m_wavFile; + WavFile* m_file; + // We need a second file handle via which to read data into m_buffer + // for analysis + WavFile* m_analysisFile; QAudioFormat m_format; @@ -293,12 +291,15 @@ private: QBuffer m_audioOutputIODevice; QByteArray m_buffer; + qint64 m_bufferPosition; + qint64 m_bufferLength; qint64 m_dataLength; + int m_levelBufferLength; qreal m_rmsLevel; qreal m_peakLevel; - int m_spectrumLengthBytes; + int m_spectrumBufferLength; QByteArray m_spectrumBuffer; SpectrumAnalyser m_spectrumAnalyser; qint64 m_spectrumPosition; diff --git a/demos/spectrum/app/levelmeter.h b/demos/spectrum/app/levelmeter.h index 38d13b1..683dba7 100644 --- a/demos/spectrum/app/levelmeter.h +++ b/demos/spectrum/app/levelmeter.h @@ -46,7 +46,7 @@ /** * Widget which displays a vertical audio level meter, indicating the - * RMS and peak levels of the window of audio samples most recently analysed + * RMS and peak levels of the window of audio samples most recently analyzed * by the Engine. */ class LevelMeter : public QWidget { diff --git a/demos/spectrum/app/main.cpp b/demos/spectrum/app/main.cpp index 3bdfb7d..fb5183e 100644 --- a/demos/spectrum/app/main.cpp +++ b/demos/spectrum/app/main.cpp @@ -44,7 +44,7 @@ int main(int argc, char **argv) { QApplication app(argc, argv); - app.setApplicationName("QtMultimedia spectrum analyser"); + app.setApplicationName("QtMultimedia spectrum analyzer"); MainWidget w; #ifdef Q_OS_SYMBIAN diff --git a/demos/spectrum/app/mainwidget.cpp b/demos/spectrum/app/mainwidget.cpp index dd51a91..4b53bbe 100644 --- a/demos/spectrum/app/mainwidget.cpp +++ b/demos/spectrum/app/mainwidget.cpp @@ -65,7 +65,7 @@ MainWidget::MainWidget(QWidget *parent) , m_mode(NoMode) , m_engine(new Engine(this)) #ifndef DISABLE_WAVEFORM - , m_waveform(new Waveform(m_engine->buffer(), this)) + , m_waveform(new Waveform(this)) #endif , m_progressBar(new ProgressBar(this)) , m_spectrograph(new Spectrograph(this)) @@ -166,19 +166,18 @@ void MainWidget::timerEvent(QTimerEvent *event) m_infoMessage->setText(""); } -void MainWidget::positionChanged(qint64 positionUs) +void MainWidget::audioPositionChanged(qint64 position) { #ifndef DISABLE_WAVEFORM - qint64 positionBytes = audioLength(m_engine->format(), positionUs); - m_waveform->positionChanged(positionBytes); + m_waveform->audioPositionChanged(position); #else - Q_UNUSED(positionUs) + Q_UNUSED(position) #endif } -void MainWidget::bufferDurationChanged(qint64 durationUs) +void MainWidget::bufferLengthChanged(qint64 length) { - m_progressBar->bufferDurationChanged(durationUs); + m_progressBar->bufferLengthChanged(length); } @@ -186,33 +185,22 @@ void MainWidget::bufferDurationChanged(qint64 durationUs) // Private slots //----------------------------------------------------------------------------- -void MainWidget::dataDurationChanged(qint64 duration) -{ -#ifndef DISABLE_WAVEFORM - const qint64 dataLength = audioLength(m_engine->format(), duration); - m_waveform->dataLengthChanged(dataLength); -#else - Q_UNUSED(duration) -#endif - - updateButtonStates(); -} - void MainWidget::showFileDialog() { - reset(); const QString dir; const QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open WAV file"), dir, "*.wav"); if (fileNames.count()) { + reset(); setMode(LoadFileMode); m_engine->loadFile(fileNames.front()); updateButtonStates(); + } else { + updateModeMenu(); } } void MainWidget::showSettingsDialog() { - reset(); m_settingsDialog->exec(); if (m_settingsDialog->result() == QDialog::Accepted) { m_engine->setAudioInputDevice(m_settingsDialog->inputDevice()); @@ -223,9 +211,9 @@ void MainWidget::showSettingsDialog() void MainWidget::showToneGeneratorDialog() { - reset(); m_toneGeneratorDialog->exec(); if (m_toneGeneratorDialog->result() == QDialog::Accepted) { + reset(); setMode(GenerateToneMode); const qreal amplitude = m_toneGeneratorDialog->amplitude(); if (m_toneGeneratorDialog->isFrequencySweepEnabled()) { @@ -236,6 +224,8 @@ void MainWidget::showToneGeneratorDialog() m_engine->generateTone(tone); updateButtonStates(); } + } else { + updateModeMenu(); } } @@ -360,13 +350,13 @@ void MainWidget::connectUi() CHECKED_CONNECT(m_engine, SIGNAL(formatChanged(const QAudioFormat &)), this, SLOT(formatChanged(const QAudioFormat &))); - m_progressBar->bufferDurationChanged(m_engine->bufferDuration()); + m_progressBar->bufferLengthChanged(m_engine->bufferLength()); - CHECKED_CONNECT(m_engine, SIGNAL(bufferDurationChanged(qint64)), - this, SLOT(bufferDurationChanged(qint64))); + CHECKED_CONNECT(m_engine, SIGNAL(bufferLengthChanged(qint64)), + this, SLOT(bufferLengthChanged(qint64))); - CHECKED_CONNECT(m_engine, SIGNAL(dataDurationChanged(qint64)), - this, SLOT(dataDurationChanged(qint64))); + CHECKED_CONNECT(m_engine, SIGNAL(dataLengthChanged(qint64)), + this, SLOT(updateButtonStates())); CHECKED_CONNECT(m_engine, SIGNAL(recordPositionChanged(qint64)), m_progressBar, SLOT(recordPositionChanged(qint64))); @@ -375,10 +365,10 @@ void MainWidget::connectUi() m_progressBar, SLOT(playPositionChanged(qint64))); CHECKED_CONNECT(m_engine, SIGNAL(recordPositionChanged(qint64)), - this, SLOT(positionChanged(qint64))); + this, SLOT(audioPositionChanged(qint64))); CHECKED_CONNECT(m_engine, SIGNAL(playPositionChanged(qint64)), - this, SLOT(positionChanged(qint64))); + this, SLOT(audioPositionChanged(qint64))); CHECKED_CONNECT(m_engine, SIGNAL(levelChanged(qreal, qreal, int)), m_levelMeter, SLOT(levelChanged(qreal, qreal, int))); @@ -394,6 +384,11 @@ void MainWidget::connectUi() CHECKED_CONNECT(m_spectrograph, SIGNAL(infoMessage(QString, int)), this, SLOT(infoMessage(QString, int))); + +#ifndef DISABLE_WAVEFORM + CHECKED_CONNECT(m_engine, SIGNAL(bufferChanged(qint64, qint64, const QByteArray &)), + m_waveform, SLOT(bufferChanged(qint64, qint64, const QByteArray &))); +#endif } void MainWidget::createMenus() @@ -425,7 +420,7 @@ void MainWidget::updateButtonStates() QAudio::IdleState == m_engine->state()); m_pauseButton->setEnabled(pauseEnabled); - const bool playEnabled = (m_engine->dataDuration() && + const bool playEnabled = (/*m_engine->dataLength() &&*/ (QAudio::AudioOutput != m_engine->mode() || (QAudio::ActiveState != m_engine->state() && QAudio::IdleState != m_engine->state()))); @@ -445,10 +440,14 @@ void MainWidget::reset() void MainWidget::setMode(Mode mode) { - m_mode = mode; - m_loadFileAction->setChecked(LoadFileMode == mode); - m_generateToneAction->setChecked(GenerateToneMode == mode); - m_recordAction->setChecked(RecordMode == mode); + updateModeMenu(); +} + +void MainWidget::updateModeMenu() +{ + m_loadFileAction->setChecked(LoadFileMode == m_mode); + m_generateToneAction->setChecked(GenerateToneMode == m_mode); + m_recordAction->setChecked(RecordMode == m_mode); } diff --git a/demos/spectrum/app/mainwidget.h b/demos/spectrum/app/mainwidget.h index ddab8b7..13131c0 100644 --- a/demos/spectrum/app/mainwidget.h +++ b/demos/spectrum/app/mainwidget.h @@ -80,21 +80,21 @@ public slots: const FrequencySpectrum &spectrum); void infoMessage(const QString &message, int timeoutMs); void errorMessage(const QString &heading, const QString &detail); - void positionChanged(qint64 position); - void bufferDurationChanged(qint64 duration); + void audioPositionChanged(qint64 position); + void bufferLengthChanged(qint64 length); private slots: void showFileDialog(); void showSettingsDialog(); void showToneGeneratorDialog(); void initializeRecord(); - void dataDurationChanged(qint64 duration); + void updateModeMenu(); + void updateButtonStates(); private: void createUi(); void createMenus(); void connectUi(); - void updateButtonStates(); void reset(); enum Mode { @@ -111,7 +111,9 @@ private: Engine* m_engine; +#ifndef DISABLE_WAVEFORM Waveform* m_waveform; +#endif ProgressBar* m_progressBar; Spectrograph* m_spectrograph; LevelMeter* m_levelMeter; diff --git a/demos/spectrum/app/progressbar.cpp b/demos/spectrum/app/progressbar.cpp index 6bfc690..0ac76f1 100644 --- a/demos/spectrum/app/progressbar.cpp +++ b/demos/spectrum/app/progressbar.cpp @@ -44,7 +44,7 @@ ProgressBar::ProgressBar(QWidget *parent) : QWidget(parent) - , m_bufferDuration(0) + , m_bufferLength(0) , m_recordPosition(0) , m_playPosition(0) , m_windowPosition(0) @@ -64,7 +64,7 @@ ProgressBar::~ProgressBar() void ProgressBar::reset() { - m_bufferDuration = 0; + m_bufferLength = 0; m_recordPosition = 0; m_playPosition = 0; m_windowPosition = 0; @@ -86,26 +86,26 @@ void ProgressBar::paintEvent(QPaintEvent * /*event*/) painter.fillRect(rect(), Qt::black); #endif - if (m_bufferDuration) { + if (m_bufferLength) { QRect bar = rect(); - const qreal play = qreal(m_playPosition) / m_bufferDuration; + const qreal play = qreal(m_playPosition) / m_bufferLength; bar.setLeft(rect().left() + play * rect().width()); - const qreal record = qreal(m_recordPosition) / m_bufferDuration; + const qreal record = qreal(m_recordPosition) / m_bufferLength; bar.setRight(rect().left() + record * rect().width()); painter.fillRect(bar, bufferColor); QRect window = rect(); - const qreal windowLeft = qreal(m_windowPosition) / m_bufferDuration; + const qreal windowLeft = qreal(m_windowPosition) / m_bufferLength; window.setLeft(rect().left() + windowLeft * rect().width()); - const qreal windowWidth = qreal(m_windowLength) / m_bufferDuration; + const qreal windowWidth = qreal(m_windowLength) / m_bufferLength; window.setWidth(windowWidth * rect().width()); painter.fillRect(window, windowColor); } } -void ProgressBar::bufferDurationChanged(qint64 bufferSize) +void ProgressBar::bufferLengthChanged(qint64 bufferSize) { - m_bufferDuration = bufferSize; + m_bufferLength = bufferSize; m_recordPosition = 0; m_playPosition = 0; m_windowPosition = 0; @@ -116,7 +116,7 @@ void ProgressBar::bufferDurationChanged(qint64 bufferSize) void ProgressBar::recordPositionChanged(qint64 recordPosition) { Q_ASSERT(recordPosition >= 0); - Q_ASSERT(recordPosition <= m_bufferDuration); + Q_ASSERT(recordPosition <= m_bufferLength); m_recordPosition = recordPosition; repaint(); } @@ -124,7 +124,7 @@ void ProgressBar::recordPositionChanged(qint64 recordPosition) void ProgressBar::playPositionChanged(qint64 playPosition) { Q_ASSERT(playPosition >= 0); - Q_ASSERT(playPosition <= m_bufferDuration); + Q_ASSERT(playPosition <= m_bufferLength); m_playPosition = playPosition; repaint(); } @@ -132,8 +132,8 @@ void ProgressBar::playPositionChanged(qint64 playPosition) void ProgressBar::windowChanged(qint64 position, qint64 length) { Q_ASSERT(position >= 0); - Q_ASSERT(position <= m_bufferDuration); - Q_ASSERT(position + length <= m_bufferDuration); + Q_ASSERT(position <= m_bufferLength); + Q_ASSERT(position + length <= m_bufferLength); m_windowPosition = position; m_windowLength = length; repaint(); diff --git a/demos/spectrum/app/progressbar.h b/demos/spectrum/app/progressbar.h index 8514adb..e715cf5 100644 --- a/demos/spectrum/app/progressbar.h +++ b/demos/spectrum/app/progressbar.h @@ -57,13 +57,13 @@ public: void paintEvent(QPaintEvent *event); public slots: - void bufferDurationChanged(qint64 bufferSize); + void bufferLengthChanged(qint64 length); void recordPositionChanged(qint64 recordPosition); void playPositionChanged(qint64 playPosition); void windowChanged(qint64 position, qint64 length); private: - qint64 m_bufferDuration; + qint64 m_bufferLength; qint64 m_recordPosition; qint64 m_playPosition; qint64 m_windowPosition; diff --git a/demos/spectrum/app/spectrograph.h b/demos/spectrum/app/spectrograph.h index ce59d90..fa4a6cf 100644 --- a/demos/spectrum/app/spectrograph.h +++ b/demos/spectrum/app/spectrograph.h @@ -48,7 +48,7 @@ QT_FORWARD_DECLARE_CLASS(QMouseEvent) /** * Widget which displays a spectrograph showing the frequency spectrum - * of the window of audio samples most recently analysed by the Engine. + * of the window of audio samples most recently analyzed by the Engine. */ class Spectrograph : public QWidget { Q_OBJECT diff --git a/demos/spectrum/app/spectrumanalyser.cpp b/demos/spectrum/app/spectrumanalyser.cpp index c467f61..2fa17b1 100644 --- a/demos/spectrum/app/spectrumanalyser.cpp +++ b/demos/spectrum/app/spectrumanalyser.cpp @@ -64,6 +64,8 @@ SpectrumAnalyserThread::SpectrumAnalyserThread(QObject *parent) #endif { #ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD + // moveToThread() cannot be called on a QObject with a parent + setParent(0); moveToThread(m_thread); m_thread->start(); #endif @@ -124,7 +126,7 @@ void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer, // Calculate the FFT m_fft->calculateFFT(m_output.data(), m_input.data()); - // Analyse output to obtain amplitude and phase for each frequency + // Analyze output to obtain amplitude and phase for each frequency for (int i=2; i<=m_numSamples/2; ++i) { // Calculate frequency of this complex sample m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); diff --git a/demos/spectrum/app/utils.cpp b/demos/spectrum/app/utils.cpp index 4ead6c2..49a7626 100644 --- a/demos/spectrum/app/utils.cpp +++ b/demos/spectrum/app/utils.cpp @@ -49,8 +49,10 @@ qint64 audioDuration(const QAudioFormat &format, qint64 bytes) qint64 audioLength(const QAudioFormat &format, qint64 microSeconds) { - return (format.frequency() * format.channels() * (format.sampleSize() / 8)) + qint64 result = (format.frequency() * format.channels() * (format.sampleSize() / 8)) * microSeconds / 1000000; + result -= result % (format.channelCount() * format.sampleSize()); + return result; } qreal nyquistFrequency(const QAudioFormat &format) diff --git a/demos/spectrum/app/waveform.cpp b/demos/spectrum/app/waveform.cpp index 1f7d315..bd854c0 100644 --- a/demos/spectrum/app/waveform.cpp +++ b/demos/spectrum/app/waveform.cpp @@ -44,12 +44,18 @@ #include <QResizeEvent> #include <QDebug> - -Waveform::Waveform(const QByteArray &buffer, QWidget *parent) +//#define PAINT_EVENT_TRACE +#ifdef PAINT_EVENT_TRACE +# define WAVEFORM_PAINT_DEBUG qDebug() +#else +# define WAVEFORM_PAINT_DEBUG nullDebug() +#endif + +Waveform::Waveform(QWidget *parent) : QWidget(parent) - , m_buffer(buffer) - , m_dataLength(0) - , m_position(0) + , m_bufferPosition(0) + , m_bufferLength(0) + , m_audioPosition(0) , m_active(false) , m_tileLength(0) , m_tileArrayStart(0) @@ -72,19 +78,19 @@ void Waveform::paintEvent(QPaintEvent * /*event*/) painter.fillRect(rect(), Qt::black); if (m_active) { - WAVEFORM_DEBUG << "Waveform::paintEvent" - << "windowPosition" << m_windowPosition - << "windowLength" << m_windowLength; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" + << "windowPosition" << m_windowPosition + << "windowLength" << m_windowLength; qint64 pos = m_windowPosition; const qint64 windowEnd = m_windowPosition + m_windowLength; int destLeft = 0; int destRight = 0; while (pos < windowEnd) { const TilePoint point = tilePoint(pos); - WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos" << pos - << "tileIndex" << point.index - << "positionOffset" << point.positionOffset - << "pixelOffset" << point.pixelOffset; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos" << pos + << "tileIndex" << point.index + << "positionOffset" << point.positionOffset + << "pixelOffset" << point.pixelOffset; if (point.index != NullIndex) { const Tile &tile = m_tiles[point.index]; @@ -104,9 +110,9 @@ void Waveform::paintEvent(QPaintEvent * /*event*/) sourceRect.setLeft(point.pixelOffset); sourceRect.setRight(sourceRight); - WAVEFORM_DEBUG << "Waveform::paintEvent" << "tileIndex" << point.index - << "source" << point.pixelOffset << sourceRight - << "dest" << destLeft << destRight; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "tileIndex" << point.index + << "source" << point.pixelOffset << sourceRight + << "dest" << destLeft << destRight; painter.drawPixmap(destRect, *tile.pixmap, sourceRect); @@ -114,25 +120,25 @@ void Waveform::paintEvent(QPaintEvent * /*event*/) if (point.index < m_tiles.count()) { pos = tilePosition(point.index + 1); - WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos ->" << pos; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos ->" << pos; } else { // Reached end of tile array - WAVEFORM_DEBUG << "Waveform::paintEvent" << "reached end of tile array"; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "reached end of tile array"; break; } } else { // Passed last tile which is painted - WAVEFORM_DEBUG << "Waveform::paintEvent" << "tile" << point.index << "not painted"; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "tile" << point.index << "not painted"; break; } } else { // pos is past end of tile array - WAVEFORM_DEBUG << "Waveform::paintEvent" << "pos" << pos << "past end of tile array"; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "pos" << pos << "past end of tile array"; break; } } - WAVEFORM_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight; + WAVEFORM_PAINT_DEBUG << "Waveform::paintEvent" << "final pos" << pos << "final x" << destRight; } } @@ -146,7 +152,6 @@ void Waveform::initialize(const QAudioFormat &format, qint64 audioBufferSize, qi { WAVEFORM_DEBUG << "Waveform::initialize" << "audioBufferSize" << audioBufferSize - << "m_buffer.size()" << m_buffer.size() << "windowDurationUs" << windowDurationUs; reset(); @@ -186,8 +191,9 @@ void Waveform::reset() { WAVEFORM_DEBUG << "Waveform::reset"; - m_dataLength = 0; - m_position = 0; + m_bufferPosition = 0; + m_buffer = QByteArray(); + m_audioPosition = 0; m_format = QAudioFormat(); m_active = false; deletePixmaps(); @@ -198,30 +204,31 @@ void Waveform::reset() m_windowLength = 0; } -void Waveform::dataLengthChanged(qint64 length) +void Waveform::bufferChanged(qint64 position, qint64 length, const QByteArray &buffer) { - WAVEFORM_DEBUG << "Waveform::dataLengthChanged" << length; - const qint64 oldLength = m_dataLength; - m_dataLength = length; - - if (m_active) { - if (m_dataLength < oldLength) - positionChanged(m_dataLength); - else - paintTiles(); - } + WAVEFORM_DEBUG << "Waveform::bufferChanged" + << "audioPosition" << m_audioPosition + << "bufferPosition" << position + << "bufferLength" << length; + m_bufferPosition = position; + m_bufferLength = length; + m_buffer = buffer; + paintTiles(); } -void Waveform::positionChanged(qint64 position) +void Waveform::audioPositionChanged(qint64 position) { - WAVEFORM_DEBUG << "Waveform::positionChanged" << position; - - if (position + m_windowLength > m_dataLength) - position = m_dataLength - m_windowLength; - - m_position = position; - - setWindowPosition(position); + WAVEFORM_DEBUG << "Waveform::audioPositionChanged" + << "audioPosition" << position + << "bufferPosition" << m_bufferPosition + << "bufferLength" << m_bufferLength; + + if (position >= m_bufferPosition) { + if (position + m_windowLength > m_bufferPosition + m_bufferLength) + position = qMax(qint64(0), m_bufferPosition + m_bufferLength - m_windowLength); + m_audioPosition = position; + setWindowPosition(position); + } } void Waveform::deletePixmaps() @@ -255,8 +262,6 @@ void Waveform::createPixmaps(const QSize &widgetSize) m_tiles[i].pixmap = m_pixmaps[i]; m_tiles[i].painted = false; } - - paintTiles(); } void Waveform::setWindowPosition(qint64 position) @@ -327,8 +332,9 @@ bool Waveform::paintTiles() for (int i=0; i<m_tiles.count(); ++i) { const Tile &tile = m_tiles[i]; if (!tile.painted) { - const qint64 tileEnd = m_tileArrayStart + (i + 1) * m_tileLength; - if (m_dataLength >= tileEnd) { + const qint64 tileStart = m_tileArrayStart + i * m_tileLength; + const qint64 tileEnd = tileStart + m_tileLength; + if (m_bufferPosition <= tileStart && m_bufferPosition + m_bufferLength >= tileEnd) { paintTile(i); updateRequired = true; } @@ -343,16 +349,23 @@ bool Waveform::paintTiles() void Waveform::paintTile(int index) { - WAVEFORM_DEBUG << "Waveform::paintTile" << "index" << index; - const qint64 tileStart = m_tileArrayStart + index * m_tileLength; - Q_ASSERT(m_dataLength >= tileStart + m_tileLength); + + WAVEFORM_DEBUG << "Waveform::paintTile" + << "index" << index + << "bufferPosition" << m_bufferPosition + << "bufferLength" << m_bufferLength + << "start" << tileStart + << "end" << tileStart + m_tileLength; + + Q_ASSERT(m_bufferPosition <= tileStart); + Q_ASSERT(m_bufferPosition + m_bufferLength >= tileStart + m_tileLength); Tile &tile = m_tiles[index]; Q_ASSERT(!tile.painted); const qint16* base = reinterpret_cast<const qint16*>(m_buffer.constData()); - const qint16* buffer = base + (tileStart / 2); + const qint16* buffer = base + ((tileStart - m_bufferPosition) / 2); const int numSamples = m_tileLength / (2 * m_format.channels()); QPainter painter(tile.pixmap); @@ -376,6 +389,11 @@ void Waveform::paintTile(int index) for (int i=0; i<numSamples; ++i) { const qint16* ptr = buffer + i * m_format.channels(); + + const int offset = reinterpret_cast<const char*>(ptr) - m_buffer.constData(); + Q_ASSERT(offset >= 0); + Q_ASSERT(offset < m_bufferLength); + const qint16 pcmValue = *ptr; const qreal realValue = pcmToReal(pcmValue); diff --git a/demos/spectrum/app/waveform.h b/demos/spectrum/app/waveform.h index 57c9eec..1c54c86 100644 --- a/demos/spectrum/app/waveform.h +++ b/demos/spectrum/app/waveform.h @@ -60,7 +60,7 @@ QT_FORWARD_DECLARE_CLASS(QByteArray) class Waveform : public QWidget { Q_OBJECT public: - Waveform(const QByteArray &buffer, QWidget *parent = 0); + Waveform(QWidget *parent = 0); ~Waveform(); // QWidget @@ -73,8 +73,8 @@ public: void setAutoUpdatePosition(bool enabled); public slots: - void dataLengthChanged(qint64 length); - void positionChanged(qint64 position); + void bufferChanged(qint64 position, qint64 length, const QByteArray &buffer); + void audioPositionChanged(qint64 position); private: static const int NullIndex = -1; @@ -167,9 +167,11 @@ private: void resetTiles(qint64 newStartPos); private: - const QByteArray& m_buffer; - qint64 m_dataLength; - qint64 m_position; + qint64 m_bufferPosition; + qint64 m_bufferLength; + QByteArray m_buffer; + + qint64 m_audioPosition; QAudioFormat m_format; bool m_active; diff --git a/demos/spectrum/app/wavfile.cpp b/demos/spectrum/app/wavfile.cpp index b9467e3..44c3ac5 100644 --- a/demos/spectrum/app/wavfile.cpp +++ b/demos/spectrum/app/wavfile.cpp @@ -76,171 +76,76 @@ struct CombinedHeader { RIFFHeader riff; WAVEHeader wave; - DATAHeader data; }; -static const int HeaderLength = sizeof(CombinedHeader); - - -WavFile::WavFile(const QAudioFormat &format, qint64 dataLength) - : m_format(format) - , m_dataLength(dataLength) -{ - -} - -bool WavFile::readHeader(QIODevice &device) -{ - bool result = true; - - if (!device.isSequential()) - result = device.seek(0); - // else, assume that current position is the start of the header - - if (result) { - CombinedHeader header; - result = (device.read(reinterpret_cast<char *>(&header), HeaderLength) == HeaderLength); - if (result) { - if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 - || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) - && memcmp(&header.riff.type, "WAVE", 4) == 0 - && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 - && header.wave.audioFormat == 1 // PCM - ) { - if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) - m_format.setByteOrder(QAudioFormat::LittleEndian); - else - m_format.setByteOrder(QAudioFormat::BigEndian); - - m_format.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels)); - m_format.setCodec("audio/pcm"); - m_format.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate)); - m_format.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample)); - - switch(header.wave.bitsPerSample) { - case 8: - m_format.setSampleType(QAudioFormat::UnSignedInt); - break; - case 16: - m_format.setSampleType(QAudioFormat::SignedInt); - break; - default: - result = false; - } - - m_dataLength = device.size() - HeaderLength; - } else { - result = false; - } - } - } - - return result; -} - -bool WavFile::writeHeader(QIODevice &device) +WavFile::WavFile(QObject *parent) + : QFile(parent) + , m_headerLength(0) { - CombinedHeader header; - memset(&header, 0, HeaderLength); - - // RIFF header - if (m_format.byteOrder() == QAudioFormat::LittleEndian) - strncpy(&header.riff.descriptor.id[0], "RIFF", 4); - else - strncpy(&header.riff.descriptor.id[0], "RIFX", 4); - qToLittleEndian<quint32>(quint32(m_dataLength + HeaderLength - 8), - reinterpret_cast<unsigned char*>(&header.riff.descriptor.size)); - strncpy(&header.riff.type[0], "WAVE", 4); - - // WAVE header - strncpy(&header.wave.descriptor.id[0], "fmt ", 4); - qToLittleEndian<quint32>(quint32(16), - reinterpret_cast<unsigned char*>(&header.wave.descriptor.size)); - qToLittleEndian<quint16>(quint16(1), - reinterpret_cast<unsigned char*>(&header.wave.audioFormat)); - qToLittleEndian<quint16>(quint16(m_format.channels()), - reinterpret_cast<unsigned char*>(&header.wave.numChannels)); - qToLittleEndian<quint32>(quint32(m_format.frequency()), - reinterpret_cast<unsigned char*>(&header.wave.sampleRate)); - qToLittleEndian<quint32>(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8), - reinterpret_cast<unsigned char*>(&header.wave.byteRate)); - qToLittleEndian<quint16>(quint16(m_format.channels() * m_format.sampleSize() / 8), - reinterpret_cast<unsigned char*>(&header.wave.blockAlign)); - qToLittleEndian<quint16>(quint16(m_format.sampleSize()), - reinterpret_cast<unsigned char*>(&header.wave.bitsPerSample)); - - // DATA header - strncpy(&header.data.descriptor.id[0], "data", 4); - qToLittleEndian<quint32>(quint32(m_dataLength), - reinterpret_cast<unsigned char*>(&header.data.descriptor.size)); - - return (device.write(reinterpret_cast<const char *>(&header), HeaderLength) == HeaderLength); -} - -const QAudioFormat& WavFile::format() const -{ - return m_format; } -qint64 WavFile::dataLength() const +bool WavFile::open(const QString &fileName) { - return m_dataLength; + close(); + setFileName(fileName); + return QFile::open(QIODevice::ReadOnly) && readHeader(); } -qint64 WavFile::headerLength() +const QAudioFormat &WavFile::fileFormat() const { - return HeaderLength; + return m_fileFormat; } -bool WavFile::writeDataLength(QIODevice &device, qint64 dataLength) +qint64 WavFile::headerLength() const { - bool result = false; - if (!device.isSequential()) { - device.seek(40); - unsigned char dataLengthLE[4]; - qToLittleEndian<quint32>(quint32(dataLength), dataLengthLE); - result = (device.write(reinterpret_cast<const char *>(dataLengthLE), 4) == 4); - } - return result; +return m_headerLength; } -#include <QFile> -#include <QTextStream> - -qint64 WavFile::readData(QIODevice &device, QByteArray &buffer, - QAudioFormat outputFormat) +bool WavFile::readHeader() { - if (QAudioFormat() == outputFormat) - outputFormat = m_format; - - qint64 result = 0; - - QFile file("wav.txt"); - file.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream stream; - stream.setDevice(&file); - - if (isPCMS16LE(outputFormat) && isPCMS16LE(m_format)) { - QVector<char> inputSample(2 * m_format.channels()); - - qint16 *output = reinterpret_cast<qint16*>(buffer.data()); - - while (result < buffer.size()) { - if (device.read(inputSample.data(), inputSample.count())) { - int inputIdx = 0; - for (int outputIdx = 0; outputIdx < outputFormat.channels(); ++outputIdx) { - const qint16* input = reinterpret_cast<const qint16*>(inputSample.data() + 2 * inputIdx); - *output++ = qFromLittleEndian<qint16>(*input); - result += 2; - if (inputIdx < m_format.channels()) - ++inputIdx; - } - } else { - break; + seek(0); + CombinedHeader header; + bool result = read(reinterpret_cast<char *>(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader); + if (result) { + if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 + || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) + && memcmp(&header.riff.type, "WAVE", 4) == 0 + && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 + && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0)) { + + // Read off remaining header information + DATAHeader dataHeader; + + if (qFromLittleEndian<quint32>(header.wave.descriptor.size) > sizeof(WAVEHeader)) { + // Extended data available + quint16 extraFormatBytes; + if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16)) + return false; + const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian<quint16>(extraFormatBytes); + if (read(throwAwayBytes).size() != throwAwayBytes) + return false; } + + if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader)) + return false; + + // Establish format + if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) + m_fileFormat.setByteOrder(QAudioFormat::LittleEndian); + else + m_fileFormat.setByteOrder(QAudioFormat::BigEndian); + + int bps = qFromLittleEndian<quint16>(header.wave.bitsPerSample); + m_fileFormat.setChannels(qFromLittleEndian<quint16>(header.wave.numChannels)); + m_fileFormat.setCodec("audio/pcm"); + m_fileFormat.setFrequency(qFromLittleEndian<quint32>(header.wave.sampleRate)); + m_fileFormat.setSampleSize(qFromLittleEndian<quint16>(header.wave.bitsPerSample)); + m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); + } else { + result = false; } } + m_headerLength = pos(); return result; } - diff --git a/demos/spectrum/app/wavfile.h b/demos/spectrum/app/wavfile.h index f2f3304..935e935 100644 --- a/demos/spectrum/app/wavfile.h +++ b/demos/spectrum/app/wavfile.h @@ -46,37 +46,22 @@ #include <QtCore/qfile.h> #include <QtMultimedia/qaudioformat.h> -/** - * Helper class for reading WAV files - * - * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - */ -class WavFile +class WavFile : public QFile { public: - WavFile(const QAudioFormat &format = QAudioFormat(), - qint64 dataLength = 0); + WavFile(QObject *parent = 0); - // Reads WAV header and seeks to start of data - bool readHeader(QIODevice &device); + bool open(const QString &fileName); + const QAudioFormat &fileFormat() const; + qint64 headerLength() const; - // Writes WAV header - bool writeHeader(QIODevice &device); - - // Read PCM data - qint64 readData(QIODevice &device, QByteArray &buffer, - QAudioFormat outputFormat = QAudioFormat()); - - const QAudioFormat& format() const; - qint64 dataLength() const; - - static qint64 headerLength(); - - static bool writeDataLength(QIODevice &device, qint64 dataLength); +private: + bool readHeader(); private: - QAudioFormat m_format; - qint64 m_dataLength; + QAudioFormat m_fileFormat; + qint64 m_headerLength; + }; #endif diff --git a/demos/spectrum/spectrum.pri b/demos/spectrum/spectrum.pri index c09aa0d..5773900 100644 --- a/demos/spectrum/spectrum.pri +++ b/demos/spectrum/spectrum.pri @@ -35,3 +35,15 @@ DEFINES += SPECTRUM_ANALYSER_SEPARATE_THREAD # Suppress warnings about strncpy potentially being unsafe, emitted by MSVC win32: DEFINES += _CRT_SECURE_NO_WARNINGS +win32 { + # spectrum_build_dir is defined with a leading slash so that it can + # be used in contexts such as + # ..$${spectrum_build_dir} + # without the result having a trailing slash where spectrum_build_dir + # is undefined. + spectrum_build_dir = /release + if (!debug_and_release|build_pass): CONFIG(debug, debug|release) { + spectrum_build_dir = /debug + } +} + diff --git a/demos/spreadsheet/spreadsheet.cpp b/demos/spreadsheet/spreadsheet.cpp index f2a1738..519afe9 100644 --- a/demos/spreadsheet/spreadsheet.cpp +++ b/demos/spreadsheet/spreadsheet.cpp @@ -511,7 +511,7 @@ void SpreadSheet::setupContents() // column 2 table->setItem(0, 2, new SpreadSheetItem("Price")); table->item(0, 2)->setBackgroundColor(titleBackground); - table->item(0, 2)->setToolTip("This collumn shows the price of the purchase"); + table->item(0, 2)->setToolTip("This column shows the price of the purchase"); table->item(0, 2)->setFont(titleFont); table->setItem(1, 2, new SpreadSheetItem("150")); diff --git a/demos/symbianpkgrules.pri b/demos/symbianpkgrules.pri index 68a82cd..c9cc492 100644 --- a/demos/symbianpkgrules.pri +++ b/demos/symbianpkgrules.pri @@ -13,4 +13,6 @@ vendorinfo = \ demos_deployment.pkg_prerules += vendorinfo DEPLOYMENT += demos_deployment -isEmpty(ICON):ICON = $$QT_SOURCE_TREE/src/s60installs/qt.svg +isEmpty(ICON):contains(TEMPLATE, ".*app"):contains(QT, gui):contains(CONFIG, qt):!contains(CONFIG, "no_icon") { + ICON = $$QT_SOURCE_TREE/src/s60installs/qt.svg +} diff --git a/demos/textedit/textedit.qdoc b/demos/textedit/textedit.qdoc index f3ba4d7..c27589e 100644 --- a/demos/textedit/textedit.qdoc +++ b/demos/textedit/textedit.qdoc @@ -7,11 +7,11 @@ ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:FDL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in a -** written agreement between you and Nokia. +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. ** ** GNU Free Documentation License ** Alternatively, this file may be used under the terms of the GNU Free |