author | paule <paule> | 2007-02-07 10:25:00 (UTC) |
---|---|---|
committer | paule <paule> | 2007-02-07 10:25:00 (UTC) |
commit | 6629be2c0147283023abcf021227bf74ca18849f (patch) (side-by-side diff) | |
tree | ed90c015aa96f199ec92fd930c0208e69098b941 /noncore/tools/remote/recorddialog.cpp | |
parent | d7a838e0f4352522fb2c12feea58129b16e76b89 (diff) | |
download | opie-6629be2c0147283023abcf021227bf74ca18849f.zip opie-6629be2c0147283023abcf021227bf74ca18849f.tar.gz opie-6629be2c0147283023abcf021227bf74ca18849f.tar.bz2 |
Implement learning process (requires patched irrecord with stdout buffering disabled)
Diffstat (limited to 'noncore/tools/remote/recorddialog.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/tools/remote/recorddialog.cpp | 230 |
1 files changed, 204 insertions, 26 deletions
diff --git a/noncore/tools/remote/recorddialog.cpp b/noncore/tools/remote/recorddialog.cpp index a9c4c61..3d21fad 100644 --- a/noncore/tools/remote/recorddialog.cpp +++ b/noncore/tools/remote/recorddialog.cpp @@ -1,7 +1,7 @@ /* Opie-Remote. emulates remote controlls on an iPaq (and maybe a Zaurus) in Opie. -Copyright (C) 2002 Thomas Stephens +Copyright (C) 2007 Paul Eggleton & Thomas Stephens This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,20 +13,32 @@ Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <stdlib.h> +#include <sys/stat.h> + +#include <qfile.h> + #include "recorddialog.h" +#define RECORD_TMPDIR "/tmp/opie-remote" + using namespace Opie::Core; using namespace Opie::Core; RecordDialog::RecordDialog(QWidget *parent, const char *name) - :QDialog(parent, name) + :QDialog(parent, name, TRUE) { QVBoxLayout *layout = new QVBoxLayout(this); QHBoxLayout *hlayout = new QHBoxLayout(this); layout->insertSpacing(0,5); - output = new QTextView("Please enter the name of the new remote, and press Return\n", 0, this, "output"); + + output = new QMultiLineEdit(this, "output"); + output->setReadOnly(true); + output->setWordWrap(QMultiLineEdit::WidgetWidth); + output->setText(tr("Please enter the name of the new remote, and press Next\n")); + layout->insertWidget(-1, output); layout->insertSpacing(-1, 5); layout->insertLayout(-1, hlayout); layout->insertSpacing(-1, 5); @@ -35,50 +47,216 @@ RecordDialog::RecordDialog(QWidget *parent, const char *name) input = new QLineEdit(this, "input"); hlayout->insertWidget(-1, input, 1); hlayout->insertSpacing(-1, 5); - QPushButton *ret = new QPushButton("Return", this, "return"); - hlayout->insertWidget(-1, ret); + nextbtn = new QPushButton(tr("Next"), this, "next"); + nextbtn->setDefault(true); + hlayout->insertWidget(-1, nextbtn); hlayout->insertSpacing(-1, 5); - connect(ret, SIGNAL(clicked()), this, SLOT(retPressed()) ); - where = 0; + connect(nextbtn, SIGNAL(clicked()), this, SLOT(nextPressed()) ); + + setCaption(tr("Learn Remote")); + input->setFocus(); + + stepnum = 0; + outputenabled = false; + writeok = true; + ignorekill = false; record = new OProcess; + + // We need to stop lircd because irrecord accesses the IR device directly + lh = new LircHandler(); + lh->stopLircd(); } -void RecordDialog::retPressed() +RecordDialog::~RecordDialog(void) { - printf("RecordDialog::retPressed: ret pressed\n"); + delete lh; + delete record; +} - if(where == 0) +void RecordDialog::nextPressed() { + if(stepnum == 0) { + QString remotename = input->text().stripWhiteSpace(); + + if(remotename == "") { + QMessageBox::warning(this, tr("Error"), + tr("Please enter a name"), + QMessageBox::Ok, QMessageBox::NoButton); + return; + } + + if(remotename.left(1) == ".") { + QMessageBox::warning(this, tr("Error"), + tr("Name cannot start with a dot"), + QMessageBox::Ok, QMessageBox::NoButton); + return; + } + + // Check for invalid chars + QRegExp invalidchars = QRegExp("[~\\[\\]/'\"|\\\\]", TRUE, FALSE); + if(remotename.find(invalidchars) > -1) { + QMessageBox::warning(this, tr("Error"), + tr("The name %1 contains\ninvalid characters").arg(remotename), + QMessageBox::Ok, QMessageBox::NoButton); + return; + } + + // Check if name already exists in config + if(lh->checkRemoteExists(remotename)) { + QMessageBox::warning(this, tr("Error"), + tr("A remote named %1\nalready exists.").arg(remotename), + QMessageBox::Ok, QMessageBox::NoButton); + return; + } + + printf("RecordDialog::nextPressed: starting irrecord\n"); + input->setEnabled(false); + connect(record, SIGNAL(receivedStdout(Opie::Core::OProcess*,char*,int)), this, SLOT(incoming(Opie::Core::OProcess*,char*,int)) ); - connect(record, SIGNAL(receivedStderr(Opie::Core::OProcess*,char*,int)), this, SLOT(incoming(Opie::Core::OProcess*,char*,int)) ); + connect(record, SIGNAL(receivedStderr(Opie::Core::OProcess*,char*,int)), this, SLOT(incomingErr(Opie::Core::OProcess*,char*,int)) ); connect(record, SIGNAL(processExited(Opie::Core::OProcess*)), this, SLOT(done(Opie::Core::OProcess*)) ); - printf("RecordDialog::retPressed: starting irrecord\n"); - QString file = "/tmp/" + input->text(); - *record<<"irrecord"<<file.latin1(); - if(!record->start(OProcess::NotifyOnExit, OProcess::AllOutput)) + connect(record, SIGNAL(wroteStdin(Opie::Core::OProcess*)), this, SLOT(writeFinished(Opie::Core::OProcess*)) ); + + // Prepare temp path + QString tmpdir = RECORD_TMPDIR; + mkdir(tmpdir, 0700); + remotefile = tmpdir + "/" + remotename; + if(QFile::exists(remotefile)) + QFile::remove(remotefile); + + // Set up and start irrecord + *record<<"irrecord"<<remotename.latin1(); + record->setWorkingDirectory(tmpdir); + if(!record->start(OProcess::NotifyOnExit, OProcess::All)) { - QMessageBox *mb = new QMessageBox("Error!", - "Could not start irrecord. You must<br>use an lirc ipkg that includes<br>irrecord", - QMessageBox::NoIcon, - QMessageBox::Ok, - QMessageBox::NoButton, - QMessageBox::NoButton); - mb->exec(); + QMessageBox::critical(this, tr("Error"), + tr("Failed to start irrecord."), + QMessageBox::Ok, QMessageBox::NoButton); return; } -// record->resume(); - where = 1; + stepnum = 1; + writeToProcess("\n", 1); + output->setText("Please get ready to press buttons on your remote.\n\nPress many different buttons, one at a time, holding each one down for approximately one second. Each button should generate at least one dot but in no case more than ten dots of output. Don't stop pressing buttons until at least two lines of dots appear.\n\nClick Next when you are ready to begin."); + } + else if(stepnum == 1) { + output->setText("Press buttons now:\n"); + output->setCursorPosition(output->numLines(), 32767); + outputenabled = true; + decoding = true; + writeToProcess("\n", 1); + nextbtn->setEnabled(false); + stepnum = 2; + } + else if(stepnum == 2) { + QString inp = input->text() + "\n"; + writeToProcess(inp, inp.length()); + input->clear(); } } void RecordDialog::incoming(OProcess *proc, char *buffer, int len) { -// output->setText(output->text() + QString(buffer).truncate(len-1)); - printf("RecordDialog::incoming: got text from irrecord\n"); + int line, col; + + if(outputenabled) { + char *bufstr = strndup(buffer, len); + output->getCursorPosition( &line, &col ); + output->insertAt( bufstr, line, col ); + + if(decoding) { + int pos = output->text().find("Now enter the names for the buttons"); + if(pos > -1) { + output->setText(output->text().mid(pos)); + output->setCursorPosition(output->numLines(), 32767); + decoding = false; + input->clear(); + input->setEnabled(true); + nextbtn->setEnabled(true); + input->setFocus(); + } + } + + free(bufstr); + } +} + +void RecordDialog::incomingErr(OProcess *proc, char *buffer, int len) +{ + char *bufstr = strndup(buffer, len); + errors += bufstr; + free(bufstr); +} + +void RecordDialog::writeToProcess(const char *buffer, int len) +{ + while(!writeok) { } + // FIXME leakage + record->writeStdin(strndup(buffer, len), len); +} + +void RecordDialog::writeFinished(Opie::Core::OProcess *proc) +{ + writeok = true; } void RecordDialog::done(OProcess *proc) { + if(proc->normalExit() && proc->exitStatus() == 0) { + // Success + + // Merge in new remote to lircd.conf + lh->mergeRemoteConfig(remotefile); + + nextbtn->hide(); + input->hide(); + output->setText("Learning completed successfully. Click OK to close."); + stepnum = 4; + } + else if(!ignorekill) { + QMessageBox::critical(this, tr("Error"), tr("Learning failed.\n") + errors, QMessageBox::Ok, QMessageBox::NoButton); + } +} + +void RecordDialog::accept() +{ + if(stepnum < 4) + QMessageBox::warning(this, tr("Error"), tr("Please complete the learning\n process or tap X to cancel."), QMessageBox::Ok, QMessageBox::NoButton); + else { + if(checkClose()) + QDialog::accept(); + } +} + +void RecordDialog::reject() +{ + if(checkClose()) + QDialog::reject(); +} + +bool RecordDialog::checkClose() +{ + if(!record->isRunning() || confirmClose()) { + if(record->isRunning()) { + ignorekill = true; + record->kill(); + } + // Restart lircd + lh->startLircd(); + // Delete temp file if it exists + if(QFile::exists(remotefile)) + unlink(remotefile); + rmdir(RECORD_TMPDIR); + + return true; + } + return false; +} + +bool RecordDialog::confirmClose() +{ + return (QMessageBox::warning(this, tr("Cancel"), + tr("Learning is not complete.\nAre you sure you want to close?"), + QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes); } |