summaryrefslogtreecommitdiff
authorpaule <paule>2007-02-07 10:25:00 (UTC)
committer paule <paule>2007-02-07 10:25:00 (UTC)
commit6629be2c0147283023abcf021227bf74ca18849f (patch) (side-by-side diff)
treeed90c015aa96f199ec92fd930c0208e69098b941
parentd7a838e0f4352522fb2c12feea58129b16e76b89 (diff)
downloadopie-6629be2c0147283023abcf021227bf74ca18849f.zip
opie-6629be2c0147283023abcf021227bf74ca18849f.tar.gz
opie-6629be2c0147283023abcf021227bf74ca18849f.tar.bz2
Implement learning process (requires patched irrecord with stdout buffering disabled)
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/tools/remote/recorddialog.cpp234
-rw-r--r--noncore/tools/remote/recorddialog.h29
2 files changed, 231 insertions, 32 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,6 +1,6 @@
/*
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
@@ -14,18 +14,30 @@ You should have received a copy of the GNU General Public License along with thi
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);
@@ -36,49 +48,215 @@ RecordDialog::RecordDialog(QWidget *parent, const char *name)
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);
}
diff --git a/noncore/tools/remote/recorddialog.h b/noncore/tools/remote/recorddialog.h
index 46a82ce..e569fb6 100644
--- a/noncore/tools/remote/recorddialog.h
+++ b/noncore/tools/remote/recorddialog.h
@@ -18,31 +18,52 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define RecordDialog_H
#include <qdialog.h>
-#include <qtextview.h>
+#include <qmultilineedit.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qwidget.h>
#include <qlayout.h>
+#include <qlabel.h>
#include <qmessagebox.h>
#include <stdio.h>
#include <opie2/oprocess.h>
+#include "lirchandler.h"
+
class RecordDialog : public QDialog
{
Q_OBJECT
public:
RecordDialog(QWidget *parent=0, const char *name=0);
+ ~RecordDialog(void);
public slots:
- void retPressed();
+ void nextPressed();
void incoming(Opie::Core::OProcess *proc, char *buffer, int len);
+ void incomingErr(Opie::Core::OProcess *proc, char *buffer, int len);
+ void writeFinished(Opie::Core::OProcess *proc);
void done(Opie::Core::OProcess *proc);
+ void accept();
+ void reject();
+protected:
+ bool confirmClose();
+ bool checkClose();
private:
- QTextView *output;
+ QMultiLineEdit *output;
QLineEdit *input;
+ QPushButton *nextbtn;
Opie::Core::OProcess *record;
- int where;
+ int stepnum;
+ bool outputenabled;
+ bool decoding;
+ bool writeok;
+ bool ignorekill;
+ QString errors;
+ QString remotefile;
+ LircHandler *lh;
+
+ void writeToProcess(const char *buffer, int len);
};
#endif