InputFile: Use new reset() function to allow re-reading file
authorSoeren Apel <soeren@apelpie.net>
Mon, 2 May 2016 20:22:39 +0000 (22:22 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Mon, 9 May 2016 11:04:55 +0000 (13:04 +0200)
Commit 519d0ccbe67d005a9c442795ce3b8255e78ca46d tried to solve
the problem of being unable to re-read an opened file by clicking
the "run" button. However, the solution is insufficient.
PV expects the session device to be updated after the open()
call. If it is not, the device settings popup will show the
settings of the previously used device.

This patch fixes this and also makes use of the new reset()
method to allow re-reading of the file contents. The method
is necessary because otherwise we have to destroy the input
module and create a new instance. This however also means
setting a new session device, which is highly undesirable.
So reset() it is.

pv/devices/inputfile.cpp
pv/devices/inputfile.hpp

index 935b0c47bdf6e41714bf889a530af61513ccb420..c30bcd33db570d1b56ff219b94928b322dc57924 100644 (file)
@@ -48,6 +48,31 @@ void InputFile::open()
                close();
        else
                session_ = context_->create_session();
+
+       input_ = format_->create_input(options_);
+
+       if (!input_)
+               throw QString("Failed to create input");
+
+       // open() should add the input device to the session but
+       // we can't open the device without sending some data first
+       f = new std::ifstream(file_name_, std::ios::binary);
+
+       char buffer[BufferSize];
+       f->read(buffer, BufferSize);
+       const std::streamsize size = f->gcount();
+       if (size == 0)
+               return;
+
+       input_->send(buffer, size);
+
+       try {
+               device_ = input_->device();
+       } catch (sigrok::Error) {
+               return;
+       }
+
+       session_->add_device(device_);
 }
 
 void InputFile::close()
@@ -63,42 +88,30 @@ void InputFile::start()
 void InputFile::run()
 {
        char buffer[BufferSize];
-       bool need_device = true;
-
-       assert(session_);
 
-       input_ = format_->create_input(options_);
-
-       if (!input_)
-               throw QString("Failed to create input");
+       if (!f) {
+               // Previous call to run() processed the entire file already
+               f = new std::ifstream(file_name_, std::ios::binary);
+               input_->reset();
+       }
 
        interrupt_ = false;
-       std::ifstream f(file_name_, std::ios::binary);
-       while (!interrupt_ && f) {
-               f.read(buffer, BufferSize);
-               const std::streamsize size = f.gcount();
+       while (!interrupt_ && !f->eof()) {
+               f->read(buffer, BufferSize);
+               const std::streamsize size = f->gcount();
                if (size == 0)
                        break;
 
                input_->send(buffer, size);
 
-               if (need_device) {
-                       try {
-                               device_ = input_->device();
-                       } catch (sigrok::Error) {
-                               break;
-                       }
-
-                       session_->remove_devices(); // Remove instance from previous run
-                       session_->add_device(device_);
-                       need_device = false;
-               }
-
                if (size != BufferSize)
                        break;
        }
 
        input_->end();
+
+       delete f;
+       f = nullptr;
 }
 
 void InputFile::stop()
index 02d4417c99e8af4bb95260e082e543b354bdccdb..e6b57033a02720b31aac2e52dadda5d8262a563e 100644 (file)
@@ -57,6 +57,7 @@ private:
        const std::map<std::string, Glib::VariantBase> options_;
        std::shared_ptr<sigrok::Input> input_;
 
+       std::ifstream *f;
        std::atomic<bool> interrupt_;
 };