summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/camera_manager.h7
-rw-r--r--include/libcamera/event_dispatcher.h33
-rw-r--r--include/libcamera/event_notifier.h42
-rw-r--r--include/libcamera/libcamera.h1
-rw-r--r--include/libcamera/meson.build3
-rw-r--r--include/libcamera/timer.h37
-rw-r--r--src/libcamera/camera_manager.cpp41
-rw-r--r--src/libcamera/event_dispatcher.cpp103
-rw-r--r--src/libcamera/event_notifier.cpp121
-rw-r--r--src/libcamera/meson.build3
-rw-r--r--src/libcamera/timer.cpp105
11 files changed, 495 insertions, 1 deletions
diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h
index e14da0f8..15e7c162 100644
--- a/include/libcamera/camera_manager.h
+++ b/include/libcamera/camera_manager.h
@@ -14,6 +14,7 @@ namespace libcamera {
class Camera;
class DeviceEnumerator;
+class EventDispatcher;
class PipelineHandler;
class CameraManager
@@ -27,13 +28,19 @@ public:
static CameraManager *instance();
+ void setEventDispatcher(EventDispatcher *dispatcher);
+ EventDispatcher *eventDispatcher();
+
private:
CameraManager();
CameraManager(const CameraManager &) = delete;
void operator=(const CameraManager &) = delete;
+ ~CameraManager();
DeviceEnumerator *enumerator_;
std::vector<PipelineHandler *> pipes_;
+
+ EventDispatcher *dispatcher_;
};
} /* namespace libcamera */
diff --git a/include/libcamera/event_dispatcher.h b/include/libcamera/event_dispatcher.h
new file mode 100644
index 00000000..c20518c6
--- /dev/null
+++ b/include/libcamera/event_dispatcher.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * event_dispatcher.h - Event dispatcher
+ */
+#ifndef __LIBCAMERA_EVENT_DISPATCHER_H__
+#define __LIBCAMERA_EVENT_DISPATCHER_H__
+
+#include <vector>
+
+namespace libcamera {
+
+class EventNotifier;
+class Timer;
+
+class EventDispatcher
+{
+public:
+ virtual ~EventDispatcher();
+
+ virtual void registerEventNotifier(EventNotifier *notifier) = 0;
+ virtual void unregisterEventNotifier(EventNotifier *notifier) = 0;
+
+ virtual void registerTimer(Timer *timer) = 0;
+ virtual void unregisterTimer(Timer *timer) = 0;
+
+ virtual void processEvents() = 0;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_EVENT_DISPATCHER_H__ */
diff --git a/include/libcamera/event_notifier.h b/include/libcamera/event_notifier.h
new file mode 100644
index 00000000..1e9b6da1
--- /dev/null
+++ b/include/libcamera/event_notifier.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * event_notifier.h - File descriptor event notifier
+ */
+#ifndef __LIBCAMERA_EVENT_NOTIFIER_H__
+#define __LIBCAMERA_EVENT_NOTIFIER_H__
+
+#include <libcamera/signal.h>
+
+namespace libcamera {
+
+class EventNotifier
+{
+public:
+ enum Type {
+ Read,
+ Write,
+ Exception,
+ };
+
+ EventNotifier(int fd, Type type);
+ virtual ~EventNotifier();
+
+ Type type() const { return type_; }
+ int fd() const { return fd_; }
+
+ bool enabled() const { return enabled_; }
+ void setEnabled(bool enable);
+
+ Signal<EventNotifier *> activated;
+
+private:
+ int fd_;
+ Type type_;
+ bool enabled_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_EVENT_NOTIFIER_H__ */
diff --git a/include/libcamera/libcamera.h b/include/libcamera/libcamera.h
index f9556a8b..785babef 100644
--- a/include/libcamera/libcamera.h
+++ b/include/libcamera/libcamera.h
@@ -9,5 +9,6 @@
#include <libcamera/camera.h>
#include <libcamera/camera_manager.h>
+#include <libcamera/event_dispatcher.h>
#endif /* __LIBCAMERA_LIBCAMERA_H__ */
diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
index 6f87689e..d7cb55ba 100644
--- a/include/libcamera/meson.build
+++ b/include/libcamera/meson.build
@@ -1,8 +1,11 @@
libcamera_api = files([
'camera.h',
'camera_manager.h',
+ 'event_dispatcher.h',
+ 'event_notifier.h',
'libcamera.h',
'signal.h',
+ 'timer.h',
])
install_headers(libcamera_api,
diff --git a/include/libcamera/timer.h b/include/libcamera/timer.h
new file mode 100644
index 00000000..97dcc01f
--- /dev/null
+++ b/include/libcamera/timer.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * timer.h - Generic timer
+ */
+#ifndef __LIBCAMERA_TIMER_H__
+#define __LIBCAMERA_TIMER_H__
+
+#include <cstdint>
+
+#include <libcamera/signal.h>
+
+namespace libcamera {
+
+class Timer
+{
+public:
+ Timer();
+
+ void start(unsigned int msec);
+ void stop();
+ bool isRunning() const;
+
+ unsigned int interval() const { return interval_; }
+ uint64_t deadline() const { return deadline_; }
+
+ Signal<Timer *> timeout;
+
+private:
+ unsigned int interval_;
+ uint64_t deadline_;
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_TIMER_H__ */
diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
index 1a9d2f38..6e1d5db1 100644
--- a/src/libcamera/camera_manager.cpp
+++ b/src/libcamera/camera_manager.cpp
@@ -6,8 +6,10 @@
*/
#include <libcamera/camera_manager.h>
+#include <libcamera/event_dispatcher.h>
#include "device_enumerator.h"
+#include "log.h"
#include "pipeline_handler.h"
/**
@@ -37,10 +39,15 @@
namespace libcamera {
CameraManager::CameraManager()
- : enumerator_(nullptr)
+ : enumerator_(nullptr), dispatcher_(nullptr)
{
}
+CameraManager::~CameraManager()
+{
+ delete dispatcher_;
+}
+
/**
* \brief Start the camera manager
*
@@ -176,4 +183,36 @@ CameraManager *CameraManager::instance()
return &manager;
}
+/**
+ * \brief Set the event dispatcher
+ * \param dispatcher Pointer to the event dispatcher
+ *
+ * libcamera requires an event dispatcher to integrate event notification and
+ * timers with the application event loop. Applications shall call this function
+ * once and only once before the camera manager is started with start() to set
+ * the event dispatcher.
+ *
+ * The CameraManager takes ownership of the event dispatcher and will delete it
+ * when the application terminates.
+ */
+void CameraManager::setEventDispatcher(EventDispatcher *dispatcher)
+{
+ if (dispatcher_) {
+ LOG(Warning) << "Event dispatcher is already set";
+ return;
+ }
+
+ dispatcher_ = dispatcher;
+}
+
+/**
+ * \brief Retrieve the event dispatcher
+ * \return Pointer to the event dispatcher, or nullptr if no event dispatcher
+ * has been set
+ */
+EventDispatcher *CameraManager::eventDispatcher()
+{
+ return dispatcher_;
+}
+
} /* namespace libcamera */
diff --git a/src/libcamera/event_dispatcher.cpp b/src/libcamera/event_dispatcher.cpp
new file mode 100644
index 00000000..54627302
--- /dev/null
+++ b/src/libcamera/event_dispatcher.cpp
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * event_dispatcher.cpp - Event dispatcher
+ */
+
+#include <libcamera/event_dispatcher.h>
+
+/**
+ * \file event_dispatcher.h
+ */
+
+namespace libcamera {
+
+/**
+ * \class EventDispatcher
+ * \brief Interface to manage the libcamera events and timers
+ *
+ * The EventDispatcher class allows the integration of the application event
+ * loop with libcamera by abstracting how events and timers are managed and
+ * processed.
+ *
+ * To listen to events, libcamera creates EventNotifier instances and registers
+ * them with the dispatcher with registerEventNotifier(). The event notifier
+ * \ref EventNotifier::activated signal is then emitted by the dispatcher
+ * whenever the event is detected.
+ *
+ * To set timers, libcamera creates Timer instances and registers them with the
+ * dispatcher with registerTimer(). The timer \ref Timer::timeout signal is then
+ * emitted by the dispatcher when the timer times out.
+ */
+
+EventDispatcher::~EventDispatcher()
+{
+}
+
+/**
+ * \fn EventDispatcher::registerEventNotifier()
+ * \brief Register an event notifier
+ * \param notifier The event notifier to register
+ *
+ * Once the \a notifier is registered with the dispatcher, the dispatcher will
+ * emit the notifier \ref EventNotifier::activated signal whenever a
+ * corresponding event is detected on the notifier's file descriptor. The event
+ * is monitored until the notifier is unregistered with
+ * unregisterEventNotifier().
+ *
+ * Registering multiple notifiers for the same file descriptor and event type is
+ * not allowed and results in undefined behaviour.
+ */
+
+/**
+ * \fn EventDispatcher::unregisterEventNotifier()
+ * \brief Unregister an event notifier
+ * \param notifier The event notifier to unregister
+ *
+ * After this function returns the \a notifier is guaranteed not to emit the
+ * \ref EventNotifier::activated signal.
+ *
+ * If the notifier isn't registered, this function performs no operation.
+ */
+
+/**
+ * \fn EventDispatcher::registerTimer()
+ * \brief Register a timer
+ * \param timer The timer to register
+ *
+ * Once the \a timer is registered with the dispatcher, the dispatcher will emit
+ * the timer \ref Timer::timeout signal when the timer times out. The timer can
+ * be unregistered with unregisterTimer() before it times out, in which case the
+ * signal will not be emitted.
+ *
+ * When the \a timer times out, it is automatically unregistered by the
+ * dispatcher and can be registered back as early as from the \ref Timer::timeout
+ * signal handlers.
+ *
+ * Registering the same timer multiple times is not allowed and results in
+ * undefined behaviour.
+ */
+
+/**
+ * \fn EventDispatcher::unregisterTimer()
+ * \brief Unregister a timer
+ * \param timer The timer to unregister
+ *
+ * After this function returns the \a timer is guaranteed not to emit the
+ * \ref Timer::timeout signal.
+ *
+ * If the timer isn't registered, this function performs no operation.
+ */
+
+/**
+ * \fn EventDispatcher::processEvents()
+ * \brief Wait for and process pending events
+ *
+ * This function processes all pending events associated with registered event
+ * notifiers and timers and signals the corresponding EventNotifier and Timer
+ * objects. If no events are pending, it waits for the first event and processes
+ * it before returning.
+ */
+
+} /* namespace libcamera */
diff --git a/src/libcamera/event_notifier.cpp b/src/libcamera/event_notifier.cpp
new file mode 100644
index 00000000..71775a9c
--- /dev/null
+++ b/src/libcamera/event_notifier.cpp
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * event_notifier.cpp - File descriptor event notifier
+ */
+
+#include <libcamera/camera_manager.h>
+#include <libcamera/event_dispatcher.h>
+#include <libcamera/event_notifier.h>
+
+/**
+ * \file event_notifier.h
+ * \brief File descriptor event notifier
+ */
+
+namespace libcamera {
+
+/**
+ * \class EventNotifier
+ * \brief Notify of activity on a file descriptor
+ *
+ * The EventNotifier models a file descriptor event source that can be
+ * monitored. It is created with the file descriptor to be monitored and the
+ * type of event, and is enabled by default. It will emit the \ref activated
+ * signal whenever an event of the monitored type occurs on the file descriptor.
+ *
+ * Supported type of events are EventNotifier::Read, EventNotifier::Write and
+ * EventNotifier::Exception. The type is specified when constructing the
+ * notifier, and can be retrieved using the type() function. To listen to
+ * multiple event types on the same file descriptor multiple notifiers must be
+ * created.
+ *
+ * The notifier can be disabled with the setEnable() function. When the notifier
+ * is disabled it ignores events and does not emit the \ref activated signal.
+ * The notifier can then be re-enabled with the setEnable() function.
+ *
+ * Creating multiple notifiers of the same type for the same file descriptor is
+ * not allowed and results in undefined behaviour.
+ *
+ * Notifier events are detected and dispatched from the
+ * EventDispatcher::processEvents() function.
+ */
+
+/**
+ * \enum EventNotifier::Type
+ * Type of file descriptor event to listen for.
+ * \var EventNotifier::Read
+ * Data is available to be read from the file descriptor
+ * \var EventNotifier::Write
+ * Data can be written to the file descriptor
+ * \var EventNotifier::Exception
+ * An exception has occurred on the file descriptor
+ */
+
+/**
+ * \brief Construct an event notifier with a file descriptor and event type
+ * \param fd The file descriptor to monitor
+ * \param type The event type to monitor
+ */
+EventNotifier::EventNotifier(int fd, Type type)
+ : fd_(fd), type_(type), enabled_(false)
+{
+ setEnabled(true);
+}
+
+EventNotifier::~EventNotifier()
+{
+ setEnabled(false);
+}
+
+/**
+ * \fn EventNotifier::type()
+ * \brief Retrieve the type of the event being monitored
+ * \return The type of the event
+ */
+
+/**
+ * \fn EventNotifier::fd()
+ * \brief Retrieve the file descriptor being monitored
+ * \return The file descriptor
+ */
+
+/**
+ * \fn EventNotifier::enabled()
+ * \brief Retrieve the notifier state
+ * \return True if the notifier is enabled, or false otherwise
+ * \sa setEnable()
+ */
+
+/**
+ * \brief Enable or disable the notifier
+ * \param enable True to enable the notifier, false to disable it
+ *
+ * This function enables or disables the notifier. A disabled notifier ignores
+ * events and does not emit the \ref activated signal.
+ */
+void EventNotifier::setEnabled(bool enable)
+{
+ if (enabled_ == enable)
+ return;
+
+ enabled_ = enable;
+
+ EventDispatcher *dispatcher = CameraManager::instance()->eventDispatcher();
+ if (enable)
+ dispatcher->registerEventNotifier(this);
+ else
+ dispatcher->unregisterEventNotifier(this);
+}
+
+/**
+ * \var EventNotifier::activated
+ * \brief Signal emitted when the event occurs
+ *
+ * This signal is emitted when the event \ref type() occurs on the file
+ * descriptor monitored by the notifier. The notifier pointer is passed as a
+ * parameter.
+ */
+
+} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 3ec86e75..61fb9320 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -2,11 +2,14 @@ libcamera_sources = files([
'camera.cpp',
'camera_manager.cpp',
'device_enumerator.cpp',
+ 'event_dispatcher.cpp',
+ 'event_notifier.cpp',
'log.cpp',
'media_device.cpp',
'media_object.cpp',
'pipeline_handler.cpp',
'signal.cpp',
+ 'timer.cpp',
])
libcamera_headers = files([
diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp
new file mode 100644
index 00000000..b5212ba2
--- /dev/null
+++ b/src/libcamera/timer.cpp
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * timer.cpp - Generic timer
+ */
+
+#include <time.h>
+
+#include <libcamera/camera_manager.h>
+#include <libcamera/event_dispatcher.h>
+#include <libcamera/timer.h>
+
+#include "log.h"
+
+/**
+ * \file timer.h
+ * \brief Generic timer
+ */
+
+namespace libcamera {
+
+/**
+ * \class Timer
+ * \brief Single-shot timer interface
+ *
+ * The Timer class models a single-shot timer that is started with start() and
+ * emits the \ref timeout signal when it times out.
+ *
+ * Once started the timer will run until it times out. It can be stopped with
+ * stop(), and once it times out or is stopped, can be started again with
+ * start().
+ */
+
+/**
+ * \brief Construct a timer
+ */
+Timer::Timer()
+{
+}
+
+/**
+ * \brief Start or restart the timer with a timeout of \a msec
+ * \param msec The timer duration in milliseconds
+ *
+ * If the timer is already running it will be stopped and restarted.
+ */
+void Timer::start(unsigned int msec)
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+
+ interval_ = msec;
+ deadline_ = tp.tv_sec * 1000000000ULL + tp.tv_nsec + msec * 1000000;
+
+ LOG(Debug) << "Starting timer " << this << " with interval " << msec
+ << ": deadline " << deadline_;
+
+ CameraManager::instance()->eventDispatcher()->registerTimer(this);
+}
+
+/**
+ * \brief Stop the timer
+ *
+ * After this function returns the timer is guaranteed not to emit the
+ * \ref timeout signal.
+ *
+ * If the timer is not running this function performs no operation.
+ */
+void Timer::stop()
+{
+ CameraManager::instance()->eventDispatcher()->unregisterTimer(this);
+
+ deadline_ = 0;
+}
+
+/**
+ * \brief Check if the timer is running
+ * \return True if the timer is running, false otherwise
+ */
+bool Timer::isRunning() const
+{
+ return deadline_ != 0;
+}
+
+/**
+ * \fn Timer::interval()
+ * \brief Retrieve the timer interval
+ * \return The timer interval in milliseconds
+ */
+
+/**
+ * \fn Timer::deadline()
+ * \brief Retrieve the timer deadline
+ * \return The timer deadline in nanoseconds
+ */
+
+/**
+ * \var Timer::timeout
+ * \brief Signal emitted when the timer times out
+ *
+ * The timer pointer is passed as a parameter.
+ */
+
+} /* namespace libcamera */