Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: rescan for available devices when scanner is unavailable #19

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions src/InsaneDaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const std::string InsaneDaemon::NAME = "insaned";

const int InsaneDaemon::SKIP_TIMEOUT_MS = 2500;
const int InsaneDaemon::BUSY_TIMEOUT_MS = 15000;
const int InsaneDaemon::OFF_SLEEP_MS = 3000;

InsaneDaemon InsaneDaemon::mInstance;

Expand Down Expand Up @@ -73,6 +74,7 @@ InsaneDaemon::~InsaneDaemon() noexcept

void InsaneDaemon::init(std::string device_name, std::string events_dir, int sleep_ms, int verbose, bool log_to_syslog, bool suspend_after_event)
{
device_fixed = !device_name.empty();
mCurrentDevice = device_name;
mEventsDir = events_dir;
mSleepMs = sleep_ms;
Expand Down Expand Up @@ -113,7 +115,7 @@ void InsaneDaemon::open(std::string device_name)
"devices are installed in your system, you should be able to see a list with\n"
"\"scanimage --list-devices\"." << std::endl;
}
throw InsaneException("Failed to open device '" + device_name + "'");
throw InsaneException("Failed to open device '" + device_name + "'", InsaneErrorType::OPEN_DEVICE);
}
log("timer: sane_open: " + std::to_string(t.restart()) + " ms", 2);
}
Expand All @@ -140,12 +142,9 @@ void InsaneDaemon::close() noexcept
void InsaneDaemon::run()
{
mRun = true;
{
// try to open the device to select one if no device was given
OpenGuard g(mCurrentDevice);
}

log("Starting polling sensors of " + mCurrentDevice + " every " + std::to_string(mSleepMs) + " ms", 1);
log("Starting polling sensors every " + std::to_string(mSleepMs) + " ms", 1);
char deviceOn = '_'; //use a char to track on(1)/off(0)/unknown(_)
while (mRun) {
if (mSuspendCount <= 0) {
// TODO skip reading sensors if
Expand All @@ -154,6 +153,13 @@ void InsaneDaemon::run()
log("Reading sensors...", 2);
try {
auto sensors = get_sensors();
if (deviceOn != '1')
{
deviceOn = '1';
log("Using sensors on " + mCurrentDevice, 1);
process_event("on", false);
}

for (auto & sensor : sensors) {
if (mRepeatCount.find(sensor.first) != mRepeatCount.end()) {
mRepeatCount[sensor.first]--;
Expand All @@ -164,6 +170,26 @@ void InsaneDaemon::run()
}
} catch (InsaneException & e) {
log(e.what(), 1);
if(e.type() == InsaneErrorType::OPEN_DEVICE)
{
if (deviceOn != '0')
{
deviceOn = '0';
log("There is a problem with " + mCurrentDevice + " , will scan for devices again after a short wait", 2);
process_event("off", false);
}
if (!device_fixed)
{
// trigger the re-scaning of devices after opening failed
mCurrentDevice.clear();
mDevices.clear();
mSuspendCount = OFF_SLEEP_MS / mSleepMs;
}
else
{
log("Will continue trying to open " + mCurrentDevice, 2);
}
}
}
} else {
log("Reading sensors is suspended: " + std::to_string(mSuspendCount) + " events left", 2);
Expand All @@ -175,7 +201,7 @@ void InsaneDaemon::run()
}


void InsaneDaemon::process_event(std::string name)
void InsaneDaemon::process_event(const std::string& name, bool debounce)
{
if (mRepeatCount.find(name) != mRepeatCount.end()) {
int count = mRepeatCount[name];
Expand All @@ -184,7 +210,10 @@ void InsaneDaemon::process_event(std::string name)
return;
}
}
mRepeatCount[name] = SKIP_TIMEOUT_MS / mSleepMs;
if( debounce )
{
mRepeatCount[name] = SKIP_TIMEOUT_MS / mSleepMs;
}

log("Processing event '" + name + "'", 1);
std::string handler = mEventsDir + "/" + name;
Expand Down Expand Up @@ -248,7 +277,7 @@ const std::vector<std::string> InsaneDaemon::get_devices()
throw InsaneException("Could not list SANE devices");
}
if (!device_list[0]) {
throw InsaneException("No SANE devices found");
throw InsaneException("No SANE devices found", InsaneErrorType::OPEN_DEVICE);
}
for (int i = 0; device_list[i]; ++i) {
mDevices.push_back(device_list[i]->name);
Expand Down
8 changes: 7 additions & 1 deletion src/InsaneDaemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ class InsaneDaemon
/// Timeout in ms to suspend main loop when device is busy
static const int BUSY_TIMEOUT_MS;

/// Time in ms to sleep when scanner is offline
static const int OFF_SLEEP_MS;

/// Singleton instance
static InsaneDaemon mInstance;

Expand All @@ -116,6 +119,9 @@ class InsaneDaemon
/// SANE version
SANE_Int mVersionCode = 0;

/// device is set be the user
bool device_fixed = true;

/// Device to use
std::string mCurrentDevice = "";

Expand Down Expand Up @@ -209,7 +215,7 @@ class InsaneDaemon
*
* @param name sensor name
*/
void process_event(std::string name);
void process_event(const std::string& nam, bool debounce = true);

/**
* Signal handler
Expand Down
15 changes: 13 additions & 2 deletions src/InsaneException.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,22 @@
#include <string>
#include <stdexcept>

enum class InsaneErrorType
{
GENERAL=0,
OPEN_DEVICE=1
};

/**
* The InsaneException class
*/
class InsaneException : std::exception
{
public:
InsaneException(std::string message)
InsaneException(std::string message, InsaneErrorType errorType=InsaneErrorType::GENERAL)
: std::exception(),
mMessage(message) {
mMessage(message),
mType(errorType) {
}

virtual ~InsaneException();
Expand All @@ -44,8 +50,13 @@ class InsaneException : std::exception
return mMessage.c_str();
}

InsaneErrorType type() const {
return mType;
}

private:
std::string mMessage;
InsaneErrorType mType;
};

#endif