Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial checkin

  • Loading branch information...
commit d1c0583837ec3c927932eb350fb8aeceb1046ca4 0 parents
@RJ authored
12 README
@@ -0,0 +1,12 @@
+Musickit
+========
+
+An experiment in building a container app using Qt and Webkit that exposes a
+JS api for audio playback, using phonon, and potentially some other APIs
+(XMPP etc) so that a music player can be written in JS/html and not suck.
+
+--
+
+I used QT Creator 4.6, it rocks, but I had to symlink my phonon qt plugin
+dir into the place where creator got installed. Packaging/distro bug.
+
74 WebkitApi.cpp
@@ -0,0 +1,74 @@
+
+#include <qdebug.h>
+#include <qwebview.h>
+#include <qwebframe.h>
+#include <QMessageBox>
+#include "WebkitApi.h"
+
+WebkitApi::WebkitApi( QObject *parent )
+ : QObject( parent )
+{
+ qDebug() << "WebkitAPI CTOR";
+}
+
+void WebkitApi::setWebView( QWebView *view )
+{
+ QWebPage *page = view->page();
+ frame = page->mainFrame();
+ attachObject();
+ connect( frame, SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(attachObject()) );
+
+}
+
+void WebkitApi::attachObject()
+{
+ frame->addToJavaScriptWindowObject( QString("MK"), this );
+}
+
+void WebkitApi::emitTick(qint64 i64, qint64 i64rem)
+{
+ int el = i64 / 1000;
+ int rem = i64rem / 1000;
+ emit(elapsed(el, rem));
+}
+
+void WebkitApi::emitStateChange(QString newstate)
+{
+ emit(stateChange(newstate));
+}
+
+void WebkitApi::emitBufferPercent(int pc)
+{
+ emit(bufferPercent(pc));
+}
+
+void WebkitApi::emitTogglePause()
+{
+ emit(pauseToggled());
+}
+
+void WebkitApi::emitVolumeChanged(int v)
+{
+ emit(volumeChanged(v));
+}
+
+void WebkitApi::setVolume(int i)
+{
+ if(i<0) i = 0; else if(i>100) i = 100;
+ emit(volumeChanged(i));
+}
+
+void WebkitApi::togglePause()
+{
+ emitTogglePause();
+}
+
+void WebkitApi::play(QString s)
+{
+ emit(playRequested(s));
+}
+
+void WebkitApi::stop()
+{
+ emit(stopRequested());
+}
46 WebkitApi.h
@@ -0,0 +1,46 @@
+#ifndef WEBKITAPI_H
+#define WEBKITAPI_H
+
+#include <qobject.h>
+
+class QWebView;
+class QWebFrame;
+
+class WebkitApi : public QObject
+{
+ Q_OBJECT
+public:
+ WebkitApi( QObject *parent );
+
+ void setWebView( QWebView *view );
+
+ void emitTick(qint64, qint64);
+ void emitStateChange(QString);
+ void emitBufferPercent(int);
+ void emitTogglePause();
+ void emitVolumeChanged(int);
+
+signals:
+ void elapsed(int, int);
+ void stateChange(QString);
+ void bufferPercent(int);
+ void volumeChanged(int);
+ void pauseToggled();
+ void playRequested(QString);
+ void stopRequested();
+
+public slots:
+ void togglePause();
+ void setVolume(int);
+ void play(QString);
+ void stop();
+
+private slots:
+ void attachObject();
+
+private:
+ QWebFrame *frame;
+};
+
+
+#endif // WEBKITAPI_H
12 main.cpp
@@ -0,0 +1,12 @@
+#include <QtGui/QApplication>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ a.setApplicationName("MusicKit");
+ a.setQuitOnLastWindowClosed(true);
+ MainWindow w;
+ w.show();
+ return a.exec();
+}
228 mainwindow.cpp
@@ -0,0 +1,228 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QDesktopServices>
+#include <QTime>
+#include <QWebFrame>
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ source = 0;
+ audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
+ mediaObject = new Phonon::MediaObject(this);
+ metaInformationResolver = new Phonon::MediaObject(this);
+
+ mediaObject->setTickInterval(1000);
+ connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
+ connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
+ this, SLOT(stateChanged(Phonon::State, Phonon::State)));
+ connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
+ this, SLOT(metaStateChanged(Phonon::State, Phonon::State)));
+ connect(mediaObject, SIGNAL(currentSourceChanged(const Phonon::MediaSource &)),
+ this, SLOT(sourceChanged(const Phonon::MediaSource &)));
+ connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
+
+ connect(mediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferPercent(int)));
+
+ Phonon::createPath(mediaObject, audioOutput);
+
+ webkitApi = new WebkitApi(this);
+ ui->setupUi(this);
+ webkitApi->setWebView(ui->webView);
+
+ connect(webkitApi, SIGNAL(pauseToggled()), this, SLOT(togglePause()));
+ connect(webkitApi, SIGNAL(volumeChanged(int)), this, SLOT(setVolume(int)));
+ connect(webkitApi, SIGNAL(playRequested(QString)), this, SLOT(play(QString)));
+ connect(webkitApi, SIGNAL(stopRequested()), this, SLOT(stop()));
+ connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal)));
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::volumeChanged(qreal vr)
+{
+ int v = (int) vr*100;
+ webkitApi->emitVolumeChanged(v);
+}
+
+void MainWindow::setVolume(int v)
+{
+ if((int)audioOutput->volume() == v) return;
+ qDebug() << "Request to set volume to " << v;
+ audioOutput->setVolume((qreal)v/100);
+}
+
+void MainWindow::togglePause()
+{
+ switch( mediaObject->state() )
+ {
+ case Phonon::PausedState:
+ mediaObject->play();
+ break;
+
+ case Phonon::PlayingState: // fallthrus - states that we are allowed to pause
+ case Phonon::LoadingState:
+ case Phonon::BufferingState:
+ mediaObject->pause();
+ break;
+ default: ;
+ }
+}
+
+void MainWindow::play(QString s)
+{
+ play(QUrl(s));
+}
+
+void MainWindow::play(QUrl url)
+{
+ mediaObject->stop();
+ mediaObject->clearQueue();
+ if(source) free(source);
+
+ if( (source = new Phonon::MediaSource(url)))
+ {
+ webkitApi->emitStateChange("loading");
+ metaInformationResolver->setCurrentSource(*source);
+ mediaObject->setCurrentSource(url);
+ mediaObject->play();
+ } else {
+ log("Error: Failed to create source");
+ webkitApi->emitStateChange("fatalerror");
+ }
+}
+
+void MainWindow::stop()
+{
+ mediaObject->stop();
+}
+
+void MainWindow::bufferPercent(int pc)
+{
+ // perhaps some logic that decides if we should abort due to slowness?
+ webkitApi->emitBufferPercent(pc);
+}
+
+void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
+ {
+ switch (newState) {
+ case Phonon::ErrorState:
+ if (mediaObject->errorType() == Phonon::FatalError) {
+ webkitApi->emitStateChange("fatalerror");
+ log("StateChanged: Fatal error: " + mediaObject->errorString());
+ } else {
+ webkitApi->emitStateChange("error");
+ log("StateChanged: error: " + mediaObject->errorString());
+ }
+ break;
+ case Phonon::PlayingState:
+ webkitApi->emitStateChange("playing");
+ break;
+ case Phonon::StoppedState:
+ webkitApi->emitStateChange("stopped");
+ break;
+ case Phonon::PausedState:
+ webkitApi->emitStateChange("paused");
+ break;
+ case Phonon::BufferingState:
+ webkitApi->emitStateChange("buffering");
+ break;
+ case Phonon::LoadingState:
+ webkitApi->emitStateChange("loading");
+ break;
+ default:
+ webkitApi->emitStateChange("unhandledstate");
+ ;
+ }
+ }
+
+void MainWindow::sourceChanged(const Phonon::MediaSource & source)
+{
+ log("Source changed: " + source.url().toString());
+// musicTable->selectRow(sources.indexOf(source));
+// timeLcd->display("00:00");
+}
+
+void MainWindow::metaStateChanged(Phonon::State newState, Phonon::State /* oldState */)
+ {
+ if (newState == Phonon::ErrorState) {
+ log("ERROR opening files: " + metaInformationResolver->errorString());
+ //QMessageBox::warning(this, tr("Error opening files"),
+ // metaInformationResolver->errorString());
+ return;
+ }
+
+ if (newState != Phonon::StoppedState && newState != Phonon::PausedState)
+ return;
+
+ if (metaInformationResolver->currentSource().type() == Phonon::MediaSource::Invalid)
+ return;
+ }
+
+
+ void MainWindow::tick(qint64 time)
+ {
+
+ QTime displayTime(0, (int)((time / 60000) % 60), (int)((time / 1000) % 60), 0);
+ QString prog = displayTime.toString("mm:ss");
+ setWindowTitle(prog);
+
+ webkitApi->emitTick(time, mediaObject->remainingTime());
+ //int secs = time / 1000;
+ //jseval(QString("Musickit.tick(%1); null").arg(secs));
+ }
+
+ void MainWindow::aboutToFinish()
+ {
+ }
+
+ void MainWindow::log(QString str)
+ {
+ QString js("mk_log(\"" + str.replace("\"","\\\"") + "\"); null");
+ jseval(js);
+ }
+
+ void MainWindow::jseval(QString str)
+{
+ qDebug() << str ;
+ ui->webView->page()->currentFrame()->evaluateJavaScript(str);
+}
+
+
+
+
+
+
+
+void MainWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void MainWindow::on_pushButton_clicked()
+{
+ QString file = QFileDialog::getOpenFileName(this, "Select Audio File", QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
+ if(!file.isEmpty())
+ {
+ play( QUrl::fromLocalFile("file://"+file) );
+ }
+}
+
+void MainWindow::on_pushButton_2_clicked()
+{
+ play(QUrl("http://www.playdar.org/hiding.mp3"));
+}
63 mainwindow.h
@@ -0,0 +1,63 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+
+#include <Phonon/AudioOutput>
+#include <Phonon/SeekSlider>
+#include <Phonon/MediaObject>
+#include <Phonon/VolumeSlider>
+#include <Phonon/BackendCapabilities>
+#include <QString>
+#include <QUrl>
+
+#include "WebkitApi.h"
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow {
+ Q_OBJECT
+public:
+ MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+protected:
+ void changeEvent(QEvent *e);
+
+private slots:
+ void on_pushButton_2_clicked();
+ void on_pushButton_clicked();
+ void stateChanged(Phonon::State newState, Phonon::State oldState);
+ void tick(qint64 time);
+ void sourceChanged(const Phonon::MediaSource &source);
+ void metaStateChanged(Phonon::State newState, Phonon::State oldState);
+ void aboutToFinish();
+ void bufferPercent(int);
+ void volumeChanged(qreal);
+
+ void togglePause();
+ void setVolume(int);
+ void play(QString);
+ void stop();
+
+private:
+
+ WebkitApi * webkitApi;
+
+ Ui::MainWindow *ui;
+
+ void play(QUrl);
+
+ Phonon::MediaObject *mediaObject;
+ Phonon::MediaObject *metaInformationResolver;
+ Phonon::AudioOutput *audioOutput;
+ Phonon::MediaSource *source;
+
+ void log(QString);
+ void jseval(QString);
+
+};
+
+#endif // MAINWINDOW_H
71 mainwindow.ui
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>400</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MusicKit Experiment</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <widget class="QWebView" name="webView">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>581</width>
+ <height>311</height>
+ </rect>
+ </property>
+ <property name="url">
+ <url>
+ <string>file:///home/rj/src/musickit/www/index.html</string>
+ </url>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="pushButton">
+ <property name="geometry">
+ <rect>
+ <x>410</x>
+ <y>340</y>
+ <width>83</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Play File</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="pushButton_2">
+ <property name="geometry">
+ <rect>
+ <x>500</x>
+ <y>340</y>
+ <width>83</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Play URL</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+ <customwidget>
+ <class>QWebView</class>
+ <extends>QWidget</extends>
+ <header>QtWebKit/QWebView</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
155 moc_WebkitApi.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'WebkitApi.h'
+**
+** Created: Wed Dec 23 13:49:07 2009
+** by: The Qt Meta Object Compiler version 62 (Qt 4.6.0)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "WebkitApi.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'WebkitApi.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 62
+#error "This file was generated using the moc from 4.6.0. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_WebkitApi[] = {
+
+ // content:
+ 4, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 12, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 7, // signalCount
+
+ // signals: signature, parameters, type, tag, flags
+ 13, 11, 10, 10, 0x05,
+ 30, 10, 10, 10, 0x05,
+ 51, 10, 10, 10, 0x05,
+ 70, 10, 10, 10, 0x05,
+ 89, 10, 10, 10, 0x05,
+ 104, 10, 10, 10, 0x05,
+ 127, 10, 10, 10, 0x05,
+
+ // slots: signature, parameters, type, tag, flags
+ 143, 10, 10, 10, 0x0a,
+ 157, 10, 10, 10, 0x0a,
+ 172, 10, 10, 10, 0x0a,
+ 186, 10, 10, 10, 0x0a,
+ 193, 10, 10, 10, 0x08,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_WebkitApi[] = {
+ "WebkitApi\0\0,\0elapsed(int,int)\0"
+ "stateChange(QString)\0bufferPercent(int)\0"
+ "volumeChanged(int)\0pauseToggled()\0"
+ "playRequested(QString)\0stopRequested()\0"
+ "togglePause()\0setVolume(int)\0play(QString)\0"
+ "stop()\0attachObject()\0"
+};
+
+const QMetaObject WebkitApi::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_WebkitApi,
+ qt_meta_data_WebkitApi, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &WebkitApi::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *WebkitApi::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *WebkitApi::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_WebkitApi))
+ return static_cast<void*>(const_cast< WebkitApi*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int WebkitApi::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: elapsed((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;
+ case 1: stateChange((*reinterpret_cast< QString(*)>(_a[1]))); break;
+ case 2: bufferPercent((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 3: volumeChanged((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 4: pauseToggled(); break;
+ case 5: playRequested((*reinterpret_cast< QString(*)>(_a[1]))); break;
+ case 6: stopRequested(); break;
+ case 7: togglePause(); break;
+ case 8: setVolume((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 9: play((*reinterpret_cast< QString(*)>(_a[1]))); break;
+ case 10: stop(); break;
+ case 11: attachObject(); break;
+ default: ;
+ }
+ _id -= 12;
+ }
+ return _id;
+}
+
+// SIGNAL 0
+void WebkitApi::elapsed(int _t1, int _t2)
+{
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
+ QMetaObject::activate(this, &staticMetaObject, 0, _a);
+}
+
+// SIGNAL 1
+void WebkitApi::stateChange(QString _t1)
+{
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
+ QMetaObject::activate(this, &staticMetaObject, 1, _a);
+}
+
+// SIGNAL 2
+void WebkitApi::bufferPercent(int _t1)
+{
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
+ QMetaObject::activate(this, &staticMetaObject, 2, _a);
+}
+
+// SIGNAL 3
+void WebkitApi::volumeChanged(int _t1)
+{
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
+ QMetaObject::activate(this, &staticMetaObject, 3, _a);
+}
+
+// SIGNAL 4
+void WebkitApi::pauseToggled()
+{
+ QMetaObject::activate(this, &staticMetaObject, 4, 0);
+}
+
+// SIGNAL 5
+void WebkitApi::playRequested(QString _t1)
+{
+ void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
+ QMetaObject::activate(this, &staticMetaObject, 5, _a);
+}
+
+// SIGNAL 6
+void WebkitApi::stopRequested()
+{
+ QMetaObject::activate(this, &staticMetaObject, 6, 0);
+}
+QT_END_MOC_NAMESPACE
111 moc_mainwindow.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+** Meta object code from reading C++ file 'mainwindow.h'
+**
+** Created: Wed Dec 23 14:07:59 2009
+** by: The Qt Meta Object Compiler version 62 (Qt 4.6.0)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "mainwindow.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'mainwindow.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 62
+#error "This file was generated using the moc from 4.6.0. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_MainWindow[] = {
+
+ // content:
+ 4, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 13, 14, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+ 0, // flags
+ 0, // signalCount
+
+ // slots: signature, parameters, type, tag, flags
+ 12, 11, 11, 11, 0x08,
+ 38, 11, 11, 11, 0x08,
+ 80, 62, 11, 11, 0x08,
+ 127, 122, 11, 11, 0x08,
+ 147, 140, 11, 11, 0x08,
+ 182, 62, 11, 11, 0x08,
+ 228, 11, 11, 11, 0x08,
+ 244, 11, 11, 11, 0x08,
+ 263, 11, 11, 11, 0x08,
+ 284, 11, 11, 11, 0x08,
+ 298, 11, 11, 11, 0x08,
+ 313, 11, 11, 11, 0x08,
+ 327, 11, 11, 11, 0x08,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_MainWindow[] = {
+ "MainWindow\0\0on_pushButton_2_clicked()\0"
+ "on_pushButton_clicked()\0newState,oldState\0"
+ "stateChanged(Phonon::State,Phonon::State)\0"
+ "time\0tick(qint64)\0source\0"
+ "sourceChanged(Phonon::MediaSource)\0"
+ "metaStateChanged(Phonon::State,Phonon::State)\0"
+ "aboutToFinish()\0bufferPercent(int)\0"
+ "volumeChanged(qreal)\0togglePause()\0"
+ "setVolume(int)\0play(QString)\0stop()\0"
+};
+
+const QMetaObject MainWindow::staticMetaObject = {
+ { &QMainWindow::staticMetaObject, qt_meta_stringdata_MainWindow,
+ qt_meta_data_MainWindow, 0 }
+};
+
+#ifdef Q_NO_DATA_RELOCATION
+const QMetaObject &MainWindow::getStaticMetaObject() { return staticMetaObject; }
+#endif //Q_NO_DATA_RELOCATION
+
+const QMetaObject *MainWindow::metaObject() const
+{
+ return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
+}
+
+void *MainWindow::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_MainWindow))
+ return static_cast<void*>(const_cast< MainWindow*>(this));
+ return QMainWindow::qt_metacast(_clname);
+}
+
+int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QMainWindow::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: on_pushButton_2_clicked(); break;
+ case 1: on_pushButton_clicked(); break;
+ case 2: stateChanged((*reinterpret_cast< Phonon::State(*)>(_a[1])),(*reinterpret_cast< Phonon::State(*)>(_a[2]))); break;
+ case 3: tick((*reinterpret_cast< qint64(*)>(_a[1]))); break;
+ case 4: sourceChanged((*reinterpret_cast< const Phonon::MediaSource(*)>(_a[1]))); break;
+ case 5: metaStateChanged((*reinterpret_cast< Phonon::State(*)>(_a[1])),(*reinterpret_cast< Phonon::State(*)>(_a[2]))); break;
+ case 6: aboutToFinish(); break;
+ case 7: bufferPercent((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 8: volumeChanged((*reinterpret_cast< qreal(*)>(_a[1]))); break;
+ case 9: togglePause(); break;
+ case 10: setVolume((*reinterpret_cast< int(*)>(_a[1]))); break;
+ case 11: play((*reinterpret_cast< QString(*)>(_a[1]))); break;
+ case 12: stop(); break;
+ default: ;
+ }
+ _id -= 13;
+ }
+ return _id;
+}
+QT_END_MOC_NAMESPACE
17 musickit.pro
@@ -0,0 +1,17 @@
+# -------------------------------------------------
+# Project created by QtCreator 2009-12-22T13:28:55
+# -------------------------------------------------
+QT += network \
+ script \
+ scripttools \
+ webkit \
+ xml \
+ phonon
+TARGET = musickit
+TEMPLATE = app
+SOURCES += main.cpp \
+ mainwindow.cpp \
+ WebkitApi.cpp
+HEADERS += mainwindow.h \
+ WebkitApi.h
+FORMS += mainwindow.ui
77 ui_mainwindow.h
@@ -0,0 +1,77 @@
+/********************************************************************************
+** Form generated from reading UI file 'mainwindow.ui'
+**
+** Created: Wed Dec 23 13:37:37 2009
+** by: Qt User Interface Compiler version 4.6.0
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_MAINWINDOW_H
+#define UI_MAINWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QHeaderView>
+#include <QtGui/QMainWindow>
+#include <QtGui/QPushButton>
+#include <QtGui/QStatusBar>
+#include <QtGui/QWidget>
+#include <QtWebKit/QWebView>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_MainWindow
+{
+public:
+ QWidget *centralWidget;
+ QWebView *webView;
+ QPushButton *pushButton;
+ QPushButton *pushButton_2;
+ QStatusBar *statusBar;
+
+ void setupUi(QMainWindow *MainWindow)
+ {
+ if (MainWindow->objectName().isEmpty())
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
+ MainWindow->resize(600, 400);
+ centralWidget = new QWidget(MainWindow);
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
+ webView = new QWebView(centralWidget);
+ webView->setObjectName(QString::fromUtf8("webView"));
+ webView->setGeometry(QRect(10, 10, 581, 311));
+ webView->setUrl(QUrl("file:///home/rj/src/musickit/www/index.html"));
+ pushButton = new QPushButton(centralWidget);
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
+ pushButton->setGeometry(QRect(410, 340, 83, 26));
+ pushButton_2 = new QPushButton(centralWidget);
+ pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));
+ pushButton_2->setGeometry(QRect(500, 340, 83, 26));
+ MainWindow->setCentralWidget(centralWidget);
+ statusBar = new QStatusBar(MainWindow);
+ statusBar->setObjectName(QString::fromUtf8("statusBar"));
+ MainWindow->setStatusBar(statusBar);
+
+ retranslateUi(MainWindow);
+
+ QMetaObject::connectSlotsByName(MainWindow);
+ } // setupUi
+
+ void retranslateUi(QMainWindow *MainWindow)
+ {
+ MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MusicKit Experiment", 0, QApplication::UnicodeUTF8));
+ pushButton->setText(QApplication::translate("MainWindow", "Play File", 0, QApplication::UnicodeUTF8));
+ pushButton_2->setText(QApplication::translate("MainWindow", "Play URL", 0, QApplication::UnicodeUTF8));
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class MainWindow: public Ui_MainWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_MAINWINDOW_H
73 www/index.html
@@ -0,0 +1,73 @@
+<html>
+<head><title>my title</title>
+</head>
+<body>
+<h1>Musickit test page</h1>
+<script type="text/javascript">
+
+var $ = function(x){return document.getElementById(x);}
+
+function mmss(secs) {
+ var s = secs % 60;
+ if (s < 10) {
+ s = "0" + s;
+ }
+ return Math.floor(secs/60) + ":" + s;
+}
+
+
+function mk_log(txt)
+{
+ var d = document.getElementById('log');
+ d.innerHTML = txt + "<br/>" + d.innerHTML;
+}
+
+// Wire up signals emitted by the Musickit API to JS functions:
+// TODO to onpageloaded/ready instead of a fixed timeout:
+setTimeout(function(){
+ try {
+ // i: seconds played so far, emitted every second
+ MK.elapsed.connect(function(elapsed, remaining){
+ $('progress').innerHTML = mmss(elapsed) + " / " + mmss(remaining);
+ });
+
+ // one of: playing stopped paused buffering loading
+ MK.stateChange.connect(function(state){
+ mk_log("js state callback: " + state);
+ });
+
+ // if there's any buffering, pc: 0-100 % of stream loaded.
+ MK.bufferPercent.connect(function(pc){
+ $('bufferpc').innerHTML = "Buffering: " + pc +"%";
+ });
+
+ MK.volumeChanged.connect(function(v){
+ mk_log('volume set to ' + v);
+ });
+
+
+ }
+ catch(e) {
+ alert(e);
+ }
+ }, 100);
+
+</script>
+<a href="#" onclick="MK.togglePause(); return false;">togglePause</a> |
+<a href="#" onclick="MK.stop(); return false;">stop</a><br/>
+
+<input type="text" value="50" id="vol"/><input type="button" value="setvol" onclick="MK.setVolume(parseInt($('vol').value)); return false;"><br/>
+
+<input type="text" id="playurl"/>
+<input type="button" value="&lt;-- play url" onclick="MK.play($('playurl').value)"/><br/>
+<div id="np">
+<span id="artist">???</span> - <span id="track">???</span>
+<br/>
+<span id="progress">XXX</span>
+ [<span id="bufferpc"></span>]
+</div>
+
+<div id="log" style="font:fixed; border:1px solid red;">
+</div>
+</body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.