aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp')
-rw-r--r--src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp230
1 files changed, 180 insertions, 50 deletions
diff --git a/src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp b/src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp
index 667ebefb..88abce82 100644
--- a/src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp
+++ b/src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp
@@ -10,64 +10,132 @@
#include <QDir>
#include <QFile>
#include <QTextStream>
-
+#include <QApplication>
#include <LUtils.h>
PianoBarProcess::PianoBarProcess(QWidget *parent) : QObject(parent){
setupProcess();
-
+ saveTimer = new QTimer(this);
+ saveTimer->setInterval(100); //1/10 second (just enough to change a few settings at once before dumping to disk)
+ saveTimer->setSingleShot(true);
+ connect(saveTimer, SIGNAL(timeout()), this, SLOT(saveSettingsFile()) );
+ if( !loadSettings() ){ GenerateSettings(); }
}
PianoBarProcess::~PianoBarProcess(){
+ if(PROC->state()!=QProcess::NotRunning){
+ PROC->kill();
+ }
+}
+PianoBarProcess::State PianoBarProcess::currentState(){
+ return cState;
}
// ===== PUBLIC ======
//Interaction functions
-bool PianoBarProcess::isSetup(); //email/password already saved for use or not
-void PianoBarProcess::setLogin(QString email, QString pass);
-void PianoBarProcess::closePianoBar(); //"q"
+bool PianoBarProcess::isSetup(){ //email/password already saved for use or not
+ return !(settingValue("user").isEmpty() || settingValue("password").isEmpty());
+}
+
+void PianoBarProcess::setLogin(QString email, QString pass){
+ setSettingValue("user",email);
+ setSettingValue("password",pass);
+}
+
+QString PianoBarProcess::email(){
+ return settingValue("user");
+}
+
+QString PianoBarProcess::password(){
+ return settingValue("password");
+}
+
+void PianoBarProcess::closePianoBar(){ //"q"
+ sendToProcess("q");
+}
-QString PianoBarProcess::currentStation(); //Re-direct for the "autostartStation()" function;
-QStringList PianoBarProcess::stations();
-void PianoBarProcess::setCurrentStation(QString station);
+QString PianoBarProcess::currentStation(){ return cstation.simplified(); }
+QStringList PianoBarProcess::stations(){ return stationList; }
+void PianoBarProcess::setCurrentStation(QString station){
+ cstation = station;
+ sendToProcess("s");
+}
-void PianoBarProcess::deleteCurrentStation(); //"d"
-void PianoBarProcess::createNewStation(); //"c"
-void PianoBarProcess::createStationFromCurrentSong(); //"v"
-void PianoBarProcess::changeStation(); //"s"
+void PianoBarProcess::deleteCurrentStation(){ //"d" -> "y"
+ if(cstation == "QuickMix" || cstation=="Thumbprint Radio"){ return; } //cannot delete these stations - provided by Pandora itself
+ sendToProcess("d"); //delete current station
+ sendToProcess("y",true); //yes, we want to delete it
+ //Now need to automatically change to another station
+ setCurrentStation("QuickMix"); //this is always a valid station
+}
+
+//void PianoBarProcess::createNewStation(); //"c"
+void PianoBarProcess::createStationFromCurrentSong(){ //"v" -> "s"
+ sendToProcess("v");
+ sendToProcess("s",true);
+ setCurrentStation("<NEW>"); //internal definition for auto-switching to a new station
+}
+
+void PianoBarProcess::createStationFromCurrentArtist(){ //"v" -> "a"
+ sendToProcess("v");
+ sendToProcess("a",true);
+ setCurrentStation("<NEW>"); //internal definition for auto-switching to a new station
+}
//Settings Manipulation
QString PianoBarProcess::audioQuality(){ // "audio_quality" = [low, medium, high]
-
+ return settingValue("audio_quality");
}
-void PianoBarProcess::setAudioQuality(QString); // [low, medium, high]
-QString PianoBarProcess::autostartStation(); //"autostart_station" = ID
-void PianoBarProcess::setAutostartStation(QString);
-QString PianoBarProcess::proxy(); //"proxy" = URL (example: "http://USER:PASSWORD@HOST:PORT/" )
-void PianoBarProcess::setProxy(QString);
-QString PianoBarProcess::controlProxy(); //"control_proxy" = URL (example: "http://USER:PASSWORD@HOST:PORT/" )
-void PianoBarProcess::setControlProxy(QString);
+void PianoBarProcess::setAudioQuality(QString val){ // [low, medium, high]
+ setSettingValue("audio_quality",val);
+}
-// ====== PUBLIC SLOTS ======
-void PianoBarProcess::play(); // "P"
-void PianoBarProcess::pause(); //"S"
+QString PianoBarProcess::autostartStation(){ //"autostart_station" = ID
+ return settingValue("autostart_station");
+}
+
+void PianoBarProcess::setAutostartStation(QString id){
+ setSettingValue("autostart_station", id);
+}
-void PianoBarProcess::volumeDown(); //"("
-void PianoBarProcess::volumeUp(); //")"
+QString PianoBarProcess::proxy(){ //"proxy" = URL (example: "http://USER:PASSWORD@HOST:PORT/" )
+ return settingValue("proxy");
+}
+
+void PianoBarProcess::setProxy(QString url){
+ setSettingValue("proxy",url);
+}
+
+QString PianoBarProcess::controlProxy(){ //"control_proxy" = URL (example: "http://USER:PASSWORD@HOST:PORT/" )
+ return settingValue("control_proxy");
+}
+
+void PianoBarProcess::setControlProxy(QString url){
+ setSettingValue("control_proxy", url);
+}
-void PianoBarProcess::skipSong(); //"n"
-void PianoBarProcess::loveSong(); // "+"
-void PianoBarProcess::tiredSong(); // "t"
-void PianoBarProcess::banSong(); //"-"
-void PianoBarProcess::bookmarkSong(); //"b"
+// ====== PUBLIC SLOTS ======
+void PianoBarProcess::play(){
+ if(PROC->state() == QProcess::NotRunning){
+ PROC->start();
+ }else{
+ sendToProcess("P");
+ cState = PianoBarProcess::Running;
+ emit currentStateChanged(cState);
+ }
+}
-void PianoBarProcess::explainSong(); //"e"
+void PianoBarProcess::pause(){
+ sendToProcess("S");
+ cState = PianoBarProcess::Paused;
+ emit currentStateChanged(cState);
+}
-void PianoBarProcess::requestHistory(); // "h"
-void PianoBarProcess::requestSongInfo(); //"i"
-void PianoBarProcess::requestUpcoming(); //"u"
+void PianoBarProcess::skipSong(){
+ sendToProcess("n");
+}
// ====== PRIVATE ======
void PianoBarProcess::GenerateSettings(){
@@ -76,17 +144,20 @@ void PianoBarProcess::GenerateSettings(){
currentSettings << "format_list_song = %r::::%t::::%a"; //[rating, title, artist]
currentSettings << "format_nowplaying_song = %r::::%t::::%a::::%l::::%u::::%s"; // [rating, title, artist, album, details url, station (if not quickmix)]
currentSettings << "format_nowplaying_station = %n::::%i"; //[name, id]
+ saveSettingsFile(); //save this to disk *now* - needed before starting the pianobar process
}
-void PianoBarProcess::loadSettings(){
+bool PianoBarProcess::loadSettings(){
currentSettings.clear();
- QFile file(settingspath);
- if(!file.exists()){ return; }
+ QFile file(settingsPath);
+ if(!file.exists()){ return false; }
if(file.open(QIODevice::ReadOnly)){
QTextStream in(&file);
currentSettings = in.readAll().split("\n");
file.close();
+ return true;
}
+ return false;
}
QString PianoBarProcess::settingValue(QString var){
@@ -102,14 +173,15 @@ void PianoBarProcess::setSettingValue(QString var,QString val){
if(currentSettings[i].startsWith(var+" = ")){ currentSettings[i] = var+" = "+val; changed = true; }
}
if(!changed){ currentSettings << var+" = "+val; }
+ saveTimer->start(); //save this to disk in a moment
}
void PianoBarProcess::saveSettingsFile(){
//Ensure the parent directory exists first
- QDir dir(settingspath.section("/",0,-2));
+ QDir dir(settingsPath.section("/",0,-2));
if(!dir.exists()){ dir.mkpath(dir.absolutePath()); }
//Now save the settings
- QFile file(settingspath);
+ QFile file(settingsPath);
if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
QTextStream out(&file);
out << currentSettings.join("\n");
@@ -125,7 +197,7 @@ void PianoBarProcess::setupProcess(){
else{ configdir.append("/lumina-desktop"); }
QProcessEnvironment penv;
penv.insert("XDG_CONFIG_HOME",configdir);
- settingspath = configdir+"/pianobar/config";
+ settingsPath = configdir+"/pianobar/config";
PROC->setProcessEnvironment(penv);
//Now setup the rest of the process
PROC->setProcessChannelMode(QProcess::MergedChannels);
@@ -133,35 +205,87 @@ void PianoBarProcess::setupProcess(){
LUtils::isValidBinary(bin); //will change "bin" to the full path
PROC->setProgram(bin);
connect(PROC, SIGNAL(readyRead()), this, SLOT(ProcUpdate()) );
+ connect(PROC, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(ProcStateChanged(QProcess::ProcessState)) );
+ cState = PianoBarProcess::Stopped;
+}
+
+void PianoBarProcess::sendToProcess(QString txt, bool withreturn){
+ if(PROC->state()==QProcess::Running){
+ if(withreturn){ PROC->write( QString(txt+"\r\n").toLocal8Bit() ); }
+ else{ PROC->write( QString(txt).toLocal8Bit() ); }
+ }
}
// ====== PRIVATE SLOTS ======
void PianoBarProcess::ProcUpdate(){
- QStringList info = QString(PROC->readAllStandardOutput()).split("\n");
+ QString tmp = QString(PROC->readAllStandardOutput()).replace("\r","\n").remove("\u001B[2K");
+ QStringList info = tmp.split("\n",QString::SkipEmptyParts);
+
//NOTE: Need to have a cache of info lines which can carry over between updates as needed (for questions, etc)
- qDebug() << "Got Update:" << info;
+ //qDebug() << "Got Update:" << info;
for(int i=0; i<info.length(); i++){
+ //First handle any pending cache of listing lines
+ if((info[i].startsWith("\t")||info[i].startsWith(" ")) && info[i].contains(")")){
+ if(info[i].simplified().startsWith("0) ")){ infoList.clear(); }
+ infoList << info[i].section(") ",1,-1).simplified();
+ continue; //done handling this line
+ }else if(!info[i].startsWith("[?]") && !infoList.isEmpty()){
+ emit NewList(infoList);
+ infoList.clear();
+ }
+ //Now parse the lines for messages/etc
if(info[i].startsWith("|>")){
//Now playing line (station, or song)
QStringList data = info[i].section(">",1,-1).simplified().split("::::"); //Make sure to chop the line prefix off first
if(data.length()==2){ //station
- cstation = data[0]; //save the name for later
+ cstation = data[0].simplified(); //save the name for later
emit NowPlayingStation(data[0], data[1]);
+ if(stationList.isEmpty()){
+ //Need to prompt to list all the available stations
+ sendToProcess("s",true);//line return cancels the prompt
+ //sendToProcess("",true); //empty line - cancels the prompt
+ }
//Automatically save this station for autostart next time (make toggle-able later)
if(data[1]!=autostartStation()){ setAutostartStation(data[1]); }
}else if(data.length()==6){ //song
emit NowPlayingSong( data[0]=="<3", data[1], data[2], data[3], data[4], data[5] );
}
+ //If a new song/station is detected, ensure that the state is set to "Running"
+ if(cState!=PianoBarProcess::Running){
+ cState = PianoBarProcess::Running;
+ emit currentStateChanged(cState);
+ }
}else if(info[i].startsWith("(i) ")){ //informational line
emit NewInformation(info[i].section(" ",1,-1));
}else if(info[i].startsWith("[?] ")){ //waiting for reply to question
- if(info[i].contains("Select Station:"){
- //Find the number before this line which corresponds to the cstation variable/name
- for(j=i-1; j>=0; j--){
- if(info[j].contains(")" && info[j].contains(cstation) ){
- PROC->write(info[j].section(")",0,0).simplified() + "\r\n");
+ //qDebug() << "Got Question:" << info[i] << infoList;
+ if(info[i].contains("Select station:")){
+ //qDebug() << "Change to Station:" << cstation;
+ //Clean up the station list a bit first (remove the quickmix-status)
+ for(int j=0; j<infoList.length(); j++){
+ infoList[j] = infoList[j].simplified();
+ if(infoList[j].startsWith("q ")){ infoList[j] = infoList[j].section("q ",1,-1); }
+ if(infoList[j].startsWith("Q ")){ infoList[j] = infoList[j].section("Q ",1,-1); }
+ }
+ if(cstation=="<NEW>"){
+ //Compare the new list to the previous list and switch to the new one automatically
+ for(int j=0; j<infoList.length(); j++){
+ if(!stationList.contains(infoList[j])){ cstation = infoList[j]; break; }
+ }
+ }
+ stationList = infoList; //save this list for later
+ infoList.clear();
+ emit StationListChanged(stationList);
+ //Find the station number which corresponds to the cstation variable/name
+ for(int j=0; j<stationList.length(); j++){
+ if(stationList[j].endsWith(cstation) ){
+ //qDebug() << "Activate Station:" << stationList[i];
+ sendToProcess(QString::number(j), true);
break;
+ }else if(j==stationList.length()-1){
+ //qDebug() << "Activate Last Station:" << stationList[i];
+ sendToProcess(QString::number(stationList.length()-1), true);
}
}
}
@@ -169,10 +293,16 @@ void PianoBarProcess::ProcUpdate(){
}else if(info[i].startsWith("#")){
//Time Stamp
QTime stamp = QTime::fromString(info[i].section("/",0,0).section("-",1,-1), "mm:ss");
- int curS = 60*stamp.minutes() + stamp.seconds(); //time remaining
+ int curS = 60*stamp.minute() + stamp.second(); //time remaining
stamp = QTime::fromString(info[i].section("/",1,-1), "mm:ss");
- int totS = 60*stamp.minutes() + stamp.sections(); //time total
+ int totS = 60*stamp.minute() + stamp.second(); //time total
emit TimeUpdate(totS-curS, totS);
}
}
}
+
+void PianoBarProcess::ProcStateChanged(QProcess::ProcessState stat){
+ if(stat == QProcess::NotRunning){ cState = PianoBarProcess::Stopped; }
+ else{ cState = PianoBarProcess::Paused; }
+ emit currentStateChanged(cState);
+}
bgstack15