Permalink
Browse files

initial checkin

  • Loading branch information...
0 parents commit d1c0583837ec3c927932eb350fb8aeceb1046ca4 @RJ committed Dec 23, 2009
Showing with 939 additions and 0 deletions.
  1. +12 −0 README
  2. +74 −0 WebkitApi.cpp
  3. +46 −0 WebkitApi.h
  4. +12 −0 main.cpp
  5. +228 −0 mainwindow.cpp
  6. +63 −0 mainwindow.h
  7. +71 −0 mainwindow.ui
  8. +155 −0 moc_WebkitApi.cpp
  9. +111 −0 moc_mainwindow.cpp
  10. +17 −0 musickit.pro
  11. +77 −0 ui_mainwindow.h
  12. +73 −0 www/index.html
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.
+
@@ -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());
+}
@@ -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
@@ -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();
+}
@@ -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"));
+}
Oops, something went wrong.

0 comments on commit d1c0583

Please sign in to comment.