diff options
Diffstat (limited to 'src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp')
-rw-r--r-- | src-qt5/desktop-utils/lumina-mediaplayer/PianoBarProcess.cpp | 230 |
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); +} |