A web service to remotely control the presets over HTTP from e.g. a smartphone. Screenshot:

http://sven.killig.de/projectM/HTTPRemoteControl.png

Usage:
[HTTP_PORT=<HTTP port> [HTTP_NAME=<HTML title>]] ./projectM-jack

Requires LibQxt. Unfortunately, cmake doesn't come with a FindQxt.cmake yet. I modified the one available at
http://dev.libqxt.org/libqxt/src
in the folder "features" to work with Ubuntu 12.10:
http://sven.killig.de/projectM/FindQxt.cmake
Put it to /usr/share/cmake-2.8/Modules

I first tried to start my web service in projectM-qt, but somehow it didn't work, so for now it's only available in projectM-jack. Perhaps someone more experienced with Q[x]t can fix this.
This commit is contained in:
Sven
2013-01-21 22:06:48 +01:00
parent acc0cf1bb7
commit 3d85aea13e
4 changed files with 131 additions and 4 deletions

View File

@ -8,6 +8,7 @@ INCLUDE(cmake/CPack-projectM.cmake)
OPTION(QT_JACK_SUPPORT "Enable Qt4 GUI Support for the projectM jack port" ON)
OPTION(BUILD_PROJECTM_JACK_STATIC "Build a binary that only depends on jack and stnadard MACOSX libraries" OFF)
OPTION(HTTP_REMOTE_CONTROL "Enable HTTP remote control" OFF)
if (QT_JACK_SUPPORT)
@ -55,17 +56,25 @@ MESSAGE( "JACK is NOT found. Please install jack from http://www.jackaudio.org."
endif(JACK_FOUND)
if(HTTP_REMOTE_CONTROL)
set(projectM_jack_SRCS
qprojectM-jack.cpp ConfigFile.h ConfigFile.cpp HTTPRemoteControl.cpp
)
else(HTTP_REMOTE_CONTROL)
set(projectM_jack_SRCS
qprojectM-jack.cpp ConfigFile.h ConfigFile.cpp
)
endif(HTTP_REMOTE_CONTROL)
if(HTTP_REMOTE_CONTROL)
set(projectM_jack_MOC_HDRS
HTTPRemoteControl.h
)
endif(HTTP_REMOTE_CONTROL)
# After this call, foo_MOC_SRCS = moc_Class1.cxx moc_Class2.cxx moc_Class3.cxx.
qt4_wrap_cpp(projectM_jack_MOC_SRCS ${projectM_MOC_HDRS})
qt4_wrap_cpp(projectM_jack_MOC_SRCS ${projectM_jack_MOC_HDRS})
ADD_DEFINITIONS(-DLINUX)
@ -73,6 +82,14 @@ ADD_DEFINITIONS(${QT_DEFINITIONS})
ADD_DEFINITIONS(-DQT_NO_DEBUG)
if(HTTP_REMOTE_CONTROL)
ADD_DEFINITIONS(-DHTTP_REMOTE_CONTROL)
SET(QXT_USE_QXTWEB TRUE)
SET(QXT_USE_QXTCORE TRUE)
find_package(Qxt REQUIRED)
endif(HTTP_REMOTE_CONTROL)
if (${CMAKE_PROJECT_NAME} MATCHES "projectM-complete")
set(PROJECTM_INCLUDE ${PROJECTM_ROOT_SOURCE_DIR}/libprojectM ${PROJECTM_ROOT_SOURCE_DIR}/projectM-qt)
set(PROJECTM_LINK ${PROJECTM_ROOT_BINARY_DIR}/libprojectM ${PROJECTM_ROOT_BINARY_DIR}/projectM-qt)
@ -84,7 +101,7 @@ elseif (${CMAKE_PROJECT_NAME} MATCHES ${PROJECT_NAME})
endif (${CMAKE_PROJECT_NAME} MATCHES "projectM-complete")
INCLUDE_DIRECTORIES(${PROJECTM_INCLUDE} ${JACK_INCLUDEDIR} ${SDL_INCLUDE_DIR} ${QT_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} ${QT_QTOPENGL_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${PROJECTM_INCLUDE} ${JACK_INCLUDEDIR} ${SDL_INCLUDE_DIR} ${QT_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} ${QT_QTOPENGL_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR} ${QXT_INCLUDE_DIRS} ${QT_QTNETWORK_INCLUDE_DIR})
LINK_DIRECTORIES(${PROJECTM_LINK})
@ -104,7 +121,7 @@ else (BUILD_PROJECTM_JACK_STATIC)
SET(PACKAGED_LIBRARIES projectM-qt projectM)
endif (BUILD_PROJECTM_JACK_STATIC)
TARGET_LINK_LIBRARIES(projectM-jack ${PACKAGED_LIBRARIES} jack ${QT_QTGUI_LIBRARIES} ${QT_QTOPENGL_LIBRARIES} ${QT_QTCORE_LIBRARIES} ${QT_LIBRARIES} ${OPENGL_LIBRARIES} ${QT_QTXML_LIBRARIES})
TARGET_LINK_LIBRARIES(projectM-jack ${PACKAGED_LIBRARIES} jack ${QT_QTGUI_LIBRARIES} ${QT_QTOPENGL_LIBRARIES} ${QT_QTCORE_LIBRARIES} ${QT_LIBRARIES} ${OPENGL_LIBRARIES} ${QT_QTXML_LIBRARIES} ${QXT_LIBRARIES})
INSTALL(TARGETS projectM-jack DESTINATION ${CMAKE_INSTALL_PREFIX}/bin )
install(FILES "projectM-jack.desktop" DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)

View File

@ -0,0 +1,59 @@
#include "HTTPRemoteControl.h"
#include <sstream>
#define HARDCUT true
void HTTPRemoteControl::selectPrevious(QxtWebRequestEvent* event) {
postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "selectPrevious"));
parent3->selectPrevious(HARDCUT);
}
void HTTPRemoteControl::selectNext(QxtWebRequestEvent* event) {
postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "selectNext"));
parent3->selectNext(HARDCUT);
}
void HTTPRemoteControl::selectRandom(QxtWebRequestEvent* event) {
postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "selectRandom"));
parent3->selectRandom(HARDCUT);
}
void HTTPRemoteControl::index(QxtWebRequestEvent* event) {
QString s="";
std::stringstream convert, convert2;
s=s+"<html>";
s=s+"<head><title>"+qgetenv("HTTP_NAME")+"</title><base target='datatransfer'></head>";
s=s+"<body bgcolor='black' text='white' link='#9999FF' alink='#AAAAFF' vlink='#EE88EE'>";
s=s+"<iframe name='datatransfer' style='display:none'></iframe>";
s=s+"<a href='/selectPrevious'>&uarr;</a> <a href='/selectNext'>&darr;</a> <a href='/selectRandom'>Random</a> ";
for(int i=1; i<=6; i++) {
convert.str("");
convert << i;
s=s+"<a href='/changePresetRating/"+convert.str().c_str()+"'>"+convert.str().c_str()+"</a> ";
}
s=s+"<p>";
for(int i=0; i<parent3->getPlaylistSize(); i++) {
convert.str("");
convert << i;
std::string n=parent3->getPresetName(i);
convert2.str("");
convert2 << parent3->getPresetRating(i, FIRST_RATING_TYPE);
s=s+"<a href='/selectPresetPosition/"+convert.str().c_str()+"'>"+n.substr(0, n.find(".milk")).c_str()+" ["+convert2.str().c_str()+"]</a><br>";
}
s=s+"</body>";
s=s+"</html>";
postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, s.toUtf8()));
}
void HTTPRemoteControl::selectPresetPosition(QxtWebRequestEvent* event, QString a) {
postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "selectPresetPosition('"+a.toUtf8()+"')"));
parent3->selectPreset(a.toUInt(), HARDCUT);
}
void HTTPRemoteControl::changePresetRating(QxtWebRequestEvent* event, QString a) {
postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "changePresetRating('"+a.toUtf8()+"')"));
unsigned int index;
parent3->selectedPresetIndex(index);
parent3->changePresetRating(index, a.toUInt(), FIRST_RATING_TYPE);
parent3->selectNext(HARDCUT);
}

View File

@ -0,0 +1,27 @@
#ifndef HTTPREMOTECONTROL
#define HTTPREMOTECONTROL
#include <QxtHttpServerConnector>
#include <QxtHttpSessionManager>
#include <QxtWebSlotService>
#include <QxtWebPageEvent>
#include "qprojectm.hpp"
class HTTPRemoteControl : public QxtWebSlotService {
Q_OBJECT
QProjectM * parent3;
public:
HTTPRemoteControl(QxtAbstractWebSessionManager * sm, QProjectM * parent2): QxtWebSlotService(sm, 0) {
parent3=parent2;
printf("HTTPRemoteControl()\n"); fflush(stdout);
}
public slots:
void selectPrevious(QxtWebRequestEvent*);
void selectNext(QxtWebRequestEvent*);
void selectRandom(QxtWebRequestEvent*);
void index(QxtWebRequestEvent*);
void selectPresetPosition(QxtWebRequestEvent*, QString);
void changePresetRating(QxtWebRequestEvent*, QString);
};
#endif

View File

@ -34,6 +34,10 @@
#include <sys/stat.h> // for mkdir
#include <jack/jack.h>
#ifdef HTTP_REMOTE_CONTROL
#include "HTTPRemoteControl.h"
#endif
#define QPROJECTM_JACK_CONFIG_FILE "/config.inp"
std::string read_config();
@ -323,6 +327,26 @@ int main (int argc, char **argv) {
}
free (ports);
#ifdef HTTP_REMOTE_CONTROL
uint port=qgetenv("HTTP_PORT").toUInt();
QxtHttpServerConnector connector;
QxtHttpSessionManager session;
printf("session.setPort(%i\n", port); fflush(stdout);
session.setPort(port);
session.setConnector(&connector);
HTTPRemoteControl s1(&session, mainWindow->qprojectM());
session.setStaticContentService ( &s1);
printf("session.start()\n"); fflush(stdout);
if(port>0) { // I think it didn't work when the conditional was further up
session.start();
}
#endif
//----------------------------------END