//=========================================== // Lumina-Desktop source code // Copyright (c) 2017, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== #include "PianoBarProcess.h" #include #include #include #include #include #include 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(); } } // ===== PUBLIC ====== //Interaction functions 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(){ return cstation; } QStringList PianoBarProcess::stations(){ return stationList; } void PianoBarProcess::setCurrentStation(QString station){ cstation = station; sendToProcess("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"); //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"); } void PianoBarProcess::createStationFromCurrentArtist(){ //"v" -> "a" sendToProcess("v"); sendToProcess("a"); } //Settings Manipulation QString PianoBarProcess::audioQuality(){ // "audio_quality" = [low, medium, high] return settingValue("audio_quality"); } void PianoBarProcess::setAudioQuality(QString val){ // [low, medium, high] setSettingValue("audio_quality",val); } QString PianoBarProcess::autostartStation(){ //"autostart_station" = ID return settingValue("autostart_station"); } void PianoBarProcess::setAutostartStation(QString id){ setSettingValue("autostart_station", id); } 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); } // ====== PUBLIC SLOTS ====== void PianoBarProcess::play(){ if(PROC->state() == QProcess::NotRunning){ PROC->start(); }else{ sendToProcess("P"); } } // ====== PRIVATE ====== void PianoBarProcess::GenerateSettings(){ currentSettings << "audio_quality = medium"; currentSettings << "autoselect = 1"; //automatically select the last item in a list (station selection only) 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 } bool PianoBarProcess::loadSettings(){ currentSettings.clear(); 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){ for(int i=0; isetProcessEnvironment(penv); //Now setup the rest of the process PROC->setProcessChannelMode(QProcess::MergedChannels); QString bin = "pianobar"; LUtils::isValidBinary(bin); //will change "bin" to the full path PROC->setProgram(bin); connect(PROC, SIGNAL(readyRead()), this, SLOT(ProcUpdate()) ); } void PianoBarProcess::sendToProcess(QString txt){ if(PROC->state()==QProcess::Running){ PROC->write( QString(txt+"\r\n").toLocal8Bit() ); } } // ====== PRIVATE SLOTS ====== void PianoBarProcess::ProcUpdate(){ 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; for(int i=0; i")){ //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 emit NowPlayingStation(data[0], data[1]); if(stationList.isEmpty()){ //Need to prompt to list all the available stations sendToProcess("s"); sendToProcess(""); //empty line - canceles 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] ); } }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 //qDebug() << "Got Question:" << info[i] << infoList; if(info[i].contains("Select station:")){ 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 i=0; i