[{"id":243,"web_url":"https://patchwork.libcamera.org/comment/243/","msgid":"<20190108094343.fbegwcuffbhcevbr@uno.localdomain>","date":"2019-01-08T09:43:43","subject":"Re: [libcamera-devel] [PATCH v2 06/11] libcamera: Add event\n\tnotification infrastructure","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n   a few minor things on comments, otherwise\n\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nOn Tue, Jan 08, 2019 at 01:11:46AM +0200, Laurent Pinchart wrote:\n> Add three new classes, EventDispatcher, EventNotifier and Timer, that\n> define APIs for file descriptor event notification and timers. The\n> implementation of the EventDispatcher is meant to be provided to\n> libcamera by the application.\n>\n> The event dispatcher is integrated twith the camera manager to implement\n> automatic registration of timers and events.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n> ---\n> Changes since v1:\n>\n> - Rename EventNotifier::isEnabled() to EventNotifier::enabled()\n> - Fix typo in documentation\n> ---\n>  include/libcamera/camera_manager.h   |   7 ++\n>  include/libcamera/event_dispatcher.h |  33 ++++++++\n>  include/libcamera/event_notifier.h   |  42 ++++++++++\n>  include/libcamera/libcamera.h        |   1 +\n>  include/libcamera/meson.build        |   3 +\n>  include/libcamera/timer.h            |  37 ++++++++\n>  src/libcamera/camera_manager.cpp     |  42 +++++++++-\n>  src/libcamera/event_dispatcher.cpp   | 103 +++++++++++++++++++++++\n>  src/libcamera/event_notifier.cpp     | 121 +++++++++++++++++++++++++++\n>  src/libcamera/meson.build            |   3 +\n>  src/libcamera/timer.cpp              | 105 +++++++++++++++++++++++\n>  11 files changed, 496 insertions(+), 1 deletion(-)\n>  create mode 100644 include/libcamera/event_dispatcher.h\n>  create mode 100644 include/libcamera/event_notifier.h\n>  create mode 100644 include/libcamera/timer.h\n>  create mode 100644 src/libcamera/event_dispatcher.cpp\n>  create mode 100644 src/libcamera/event_notifier.cpp\n>  create mode 100644 src/libcamera/timer.cpp\n>\n> diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h\n> index e14da0f893b3..15e7c162032a 100644\n> --- a/include/libcamera/camera_manager.h\n> +++ b/include/libcamera/camera_manager.h\n> @@ -14,6 +14,7 @@ namespace libcamera {\n>\n>  class Camera;\n>  class DeviceEnumerator;\n> +class EventDispatcher;\n>  class PipelineHandler;\n>\n>  class CameraManager\n> @@ -27,13 +28,19 @@ public:\n>\n>  \tstatic CameraManager *instance();\n>\n> +\tvoid setEventDispatcher(EventDispatcher *dispatcher);\n> +\tEventDispatcher *eventDispatcher();\n> +\n>  private:\n>  \tCameraManager();\n>  \tCameraManager(const CameraManager &) = delete;\n>  \tvoid operator=(const CameraManager &) = delete;\n> +\t~CameraManager();\n>\n>  \tDeviceEnumerator *enumerator_;\n>  \tstd::vector<PipelineHandler *> pipes_;\n> +\n> +\tEventDispatcher *dispatcher_;\n>  };\n>\n>  } /* namespace libcamera */\n> diff --git a/include/libcamera/event_dispatcher.h b/include/libcamera/event_dispatcher.h\n> new file mode 100644\n> index 000000000000..c20518c6866d\n> --- /dev/null\n> +++ b/include/libcamera/event_dispatcher.h\n> @@ -0,0 +1,33 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2019, Google Inc.\n> + *\n> + * event_dispatcher.h - Event dispatcher\n> + */\n> +#ifndef __LIBCAMERA_EVENT_DISPATCHER_H__\n> +#define __LIBCAMERA_EVENT_DISPATCHER_H__\n> +\n> +#include <vector>\n> +\n> +namespace libcamera {\n> +\n> +class EventNotifier;\n> +class Timer;\n> +\n> +class EventDispatcher\n> +{\n> +public:\n> +\tvirtual ~EventDispatcher();\n> +\n> +\tvirtual void registerEventNotifier(EventNotifier *notifier) = 0;\n> +\tvirtual void unregisterEventNotifier(EventNotifier *notifier) = 0;\n> +\n> +\tvirtual void registerTimer(Timer *timer) = 0;\n> +\tvirtual void unregisterTimer(Timer *timer) = 0;\n> +\n> +\tvirtual void processEvents() = 0;\n> +};\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif /* __LIBCAMERA_EVENT_DISPATCHER_H__ */\n> diff --git a/include/libcamera/event_notifier.h b/include/libcamera/event_notifier.h\n> new file mode 100644\n> index 000000000000..1e9b6da1340c\n> --- /dev/null\n> +++ b/include/libcamera/event_notifier.h\n> @@ -0,0 +1,42 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2019, Google Inc.\n> + *\n> + * event_notifier.h - File descriptor event notifier\n> + */\n> +#ifndef __LIBCAMERA_EVENT_NOTIFIER_H__\n> +#define __LIBCAMERA_EVENT_NOTIFIER_H__\n> +\n> +#include <libcamera/signal.h>\n> +\n> +namespace libcamera {\n> +\n> +class EventNotifier\n> +{\n> +public:\n> +\tenum Type {\n> +\t\tRead,\n> +\t\tWrite,\n> +\t\tException,\n> +\t};\n> +\n> +\tEventNotifier(int fd, Type type);\n> +\tvirtual ~EventNotifier();\n> +\n> +\tType type() const { return type_; }\n> +\tint fd() const { return fd_; }\n> +\n> +\tbool enabled() const { return enabled_; }\n> +\tvoid setEnabled(bool enable);\n> +\n> +\tSignal<EventNotifier *> activated;\n> +\n> +private:\n> +\tint fd_;\n> +\tType type_;\n> +\tbool enabled_;\n> +};\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif /* __LIBCAMERA_EVENT_NOTIFIER_H__ */\n> diff --git a/include/libcamera/libcamera.h b/include/libcamera/libcamera.h\n> index f9556a8bce62..785babefa1c8 100644\n> --- a/include/libcamera/libcamera.h\n> +++ b/include/libcamera/libcamera.h\n> @@ -9,5 +9,6 @@\n>\n>  #include <libcamera/camera.h>\n>  #include <libcamera/camera_manager.h>\n> +#include <libcamera/event_dispatcher.h>\n>\n>  #endif /* __LIBCAMERA_LIBCAMERA_H__ */\n> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build\n> index 6f87689ea528..d7cb55ba4a49 100644\n> --- a/include/libcamera/meson.build\n> +++ b/include/libcamera/meson.build\n> @@ -1,8 +1,11 @@\n>  libcamera_api = files([\n>      'camera.h',\n>      'camera_manager.h',\n> +    'event_dispatcher.h',\n> +    'event_notifier.h',\n>      'libcamera.h',\n>      'signal.h',\n> +    'timer.h',\n>  ])\n>\n>  install_headers(libcamera_api,\n> diff --git a/include/libcamera/timer.h b/include/libcamera/timer.h\n> new file mode 100644\n> index 000000000000..97dcc01f493d\n> --- /dev/null\n> +++ b/include/libcamera/timer.h\n> @@ -0,0 +1,37 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2019, Google Inc.\n> + *\n> + * timer.h - Generic timer\n> + */\n> +#ifndef __LIBCAMERA_TIMER_H__\n> +#define __LIBCAMERA_TIMER_H__\n> +\n> +#include <cstdint>\n> +\n> +#include <libcamera/signal.h>\n> +\n> +namespace libcamera {\n> +\n> +class Timer\n> +{\n> +public:\n> +\tTimer();\n> +\n> +\tvoid start(unsigned int msec);\n> +\tvoid stop();\n> +\tbool isRunning() const;\n> +\n> +\tunsigned int interval() const { return interval_; }\n> +\tuint64_t deadline() const { return deadline_; }\n> +\n> +\tSignal<Timer *> timeout;\n> +\n> +private:\n> +\tunsigned int interval_;\n> +\tuint64_t deadline_;\n> +};\n> +\n> +} /* namespace libcamera */\n> +\n> +#endif /* __LIBCAMERA_TIMER_H__ */\n> diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\n> index 1a9d2f38e3b9..cbfd977f1e3c 100644\n> --- a/src/libcamera/camera_manager.cpp\n> +++ b/src/libcamera/camera_manager.cpp\n> @@ -6,8 +6,10 @@\n>   */\n>\n>  #include <libcamera/camera_manager.h>\n> +#include <libcamera/event_dispatcher.h>\n>\n>  #include \"device_enumerator.h\"\n> +#include \"log.h\"\n>  #include \"pipeline_handler.h\"\n>\n>  /**\n> @@ -37,10 +39,15 @@\n>  namespace libcamera {\n>\n>  CameraManager::CameraManager()\n> -\t: enumerator_(nullptr)\n> +\t: enumerator_(nullptr), dispatcher_(nullptr)\n>  {\n>  }\n>\n> +CameraManager::~CameraManager()\n> +{\n> +\tdelete dispatcher_;\n> +}\n> +\n>  /**\n>   * \\brief Start the camera manager\n>   *\n> @@ -176,4 +183,37 @@ CameraManager *CameraManager::instance()\n>  \treturn &manager;\n>  }\n>\n> +/**\n> + * \\brief Set the event dispatcher\n> + * \\param dispatcher Pointer to the event dispatcher\n> + *\n> + * libcamera requires an event dispatcher to integrate event notification and\n> + * timers with the application event loop. Applications shall call this function\n> + * once and only once before the camera manager is started with start() to set\n> + * the event dispatcher.\n> + *\n> + * The CameraManager takes ownership of the event dispatcher and will delete it\n> + * when the application terminates.\n> + */\n> +void CameraManager::setEventDispatcher(EventDispatcher *dispatcher)\n> +{\n> +\tif (dispatcher_) {\n> +\t\tLOG(Warning) << \"Event dispatcher is already set\";\n> +\t\treturn;\n> +\t}\n> +\n> +\tdispatcher_ = dispatcher;\n> +}\n> +\n> +/**\n> + * \\fn CameraManager::eventDispatcher()\n\nNot needed, as the comment applies to the function just after the\ncomment block.\n\n> + * \\brief Retrieve the event dispatcher\n> + * \\return Pointer to the event dispatcher, or nullptr if no event dispatcher\n> + * has been set\n> + */\n> +EventDispatcher *CameraManager::eventDispatcher()\n> +{\n> +\treturn dispatcher_;\n> +}\n> +\n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/event_dispatcher.cpp b/src/libcamera/event_dispatcher.cpp\n> new file mode 100644\n> index 000000000000..b893ab046985\n> --- /dev/null\n> +++ b/src/libcamera/event_dispatcher.cpp\n> @@ -0,0 +1,103 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2019, Google Inc.\n> + *\n> + * event_dispatcher.cpp - Event dispatcher\n> + */\n> +\n> +#include <libcamera/event_dispatcher.h>\n> +\n> +/**\n> + * \\file event_dispatcher.h\n> + */\n> +\n> +namespace libcamera {\n> +\n> +/**\n> + * \\class EventDispatcher\n> + * \\brief Interface to manage the libcamera events and timers\n> + *\n> + * The EventDispatcher class allows the integration of the application event\n> + * loop with libcamera by abstracting how events and timers are managed and\n> + * processed.\n> + *\n> + * To listen to events, libcamera creates EventNotifier instances and register\n\ns/register/registers ?\n\n> + * them with the dispatcher with registerEventNotifier(). The event notifier\n> + * \\ref EventNotifier::activated signal is then emitted by the dispatcher\n> + * whenever the event is detected.\n> + *\n> + * To set timers, libcamera creates Timer instances and register them with the\n\ns/register/registers ?\n\n> + * dispatcher with registerTimer(). The timer \\ref Timer::timeout signal is then\n> + * emitted by the dispatcher when the timer times out.\n> + */\n> +\n> +EventDispatcher::~EventDispatcher()\n> +{\n> +}\n> +\n> +/**\n> + * \\fn EventDispatcher::registerEventNotifier()\n> + * \\brief Register an event notifier\n> + * \\param notifier The event notifier to register\n> + *\n> + * Once the \\a notifier is registered with the dispatcher, the dispatcher will\n> + * emit the notifier \\ref EventNotifier::activated signal whenever a\n> + * corresponding event is detected on the notifier's file descriptor. The event\n> + * is monitored until the notifier is unregistered with\n> + * unregisterEventNotifier().\n> + *\n> + * Registering multiple notifiers for the same file descriptor and event type is\n> + * not allowed and results in undefined behaviour.\n> + */\n> +\n> +/**\n> + * \\fn EventDispatcher::unregisterEventNotifier()\n> + * \\brief Unregister an event notifier\n> + * \\param notifier The event notifier to unregister\n> + *\n> + * After this function returns the \\a notifier is guaranteed not to emit the\n> + * \\ref EventNotifier::activated signal.\n> + *\n> + * If the notifier isn't registered, this function performs no operation.\n> + */\n> +\n> +/**\n> + * \\fn EventDispatcher::registerTimer()\n> + * \\brief Register a timer\n> + * \\param timer The timer to register\n> + *\n> + * Once the \\a timer is registered with the dispatcher, the dispatcher will emit\n> + * the timer \\ref Timer::timeout signal when the timer times out. The timer can\n> + * be unregistered with unregisterTimer() before it times out, in which case the\n> + * signal will not be emitted.\n> + *\n> + * When the \\a timer times out, it is automatically unregistered by the\n> + * dispatcher and can be registered back as early as from the \\ref Timer::timeout\n> + * signal handlers.\n> + *\n> + * Registering the same timer multiple times is not allowed and results in\n> + * undefined behaviour.\n> + */\n> +\n> +/**\n> + * \\fn EventDispatcher::unregisterTimer()\n> + * \\brief Unregister a timer\n> + * \\param timer The timer to unregister\n> + *\n> + * After this function returns the \\a timer is guaranteed not to emit the\n> + * \\ref Timer::timeout signal.\n> + *\n> + * If the timer isn't registered, this function performs no operation.\n> + */\n> +\n> +/**\n> + * \\fn EventDispatcher::processEvents()\n> + * \\brief Wait for and process pending events\n> + *\n> + * This function processes all pending events associated with registered event\n> + * notifiers and timers and signals the corresponding EventNotifier and Timer\n> + * objects. If no events are pending, it waits for the first event and processes\n> + * it before returning.\n> + */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/libcamera/event_notifier.cpp b/src/libcamera/event_notifier.cpp\n> new file mode 100644\n> index 000000000000..8dc45a546a11\n> --- /dev/null\n> +++ b/src/libcamera/event_notifier.cpp\n> @@ -0,0 +1,121 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2019, Google Inc.\n> + *\n> + * event_notifier.cpp - File descriptor event notifier\n> + */\n> +\n> +#include <libcamera/camera_manager.h>\n> +#include <libcamera/event_dispatcher.h>\n> +#include <libcamera/event_notifier.h>\n> +\n> +/**\n> + * \\file event_notifier.h\n> + * \\brief Event notifier\n\nEvent notifier for file descriptor events ?\n\n> + */\n> +\n> +namespace libcamera {\n> +\n> +/**\n> + * \\class EventNotifier\n> + * \\brief Notify of activity on a file descriptor\n> + *\n> + * The EventNotifier models a file descriptor event source that can be\n> + * monitored. It is created with the file descriptor to be monitored and the\n> + * type of event, and is enabled by default. It will emit the \\ref activated\n> + * signal whenever an event of the monitored type occurs on the file descriptor.\n> + *\n> + * Supported type of events are EventNotifier::Read, EventNotifier::Write and\n> + * EventNotifier::Exception. The type is specified when constructing the\n> + * notifier, and can be retrieved using the type() function. To listen to\n> + * multiple event types on the same file descriptor multiple notifiers must be\n> + * created.\n> + *\n> + * The notifier can be disabled with the setEnable() function. When the notifier\n> + * is disabled it ignores events and does not emit the \\ref activated signal.\n> + * The notifier can then be re-enabled with the setEnable() function.\n> + *\n> + * Creating multiple notifiers of the same type for the same file descriptor is\n> + * not allowed and results in undefined behaviour.\n> + *\n> + * Notifier events are detected and dispatched from the\n> + * EventDispatcher::processEvents() function.\n> + */\n> +\n> +/**\n> + * \\enum EventNotifier::Type\n> + * Type of file descriptor event to listen for.\n> + * \\var EventNotifier::Read\n> + * Data is available to be read from the file descriptor\n> + * \\var EventNotifier::Write\n> + * Data can be written to the file descriptor\n> + * \\var EventNotifier::Exception\n> + * An exception has occurred on the file descriptor\n> + */\n> +\n> +/**\n> + * \\brief Construct an event notifier with a file descriptor and event type\n> + * \\param fd The file descriptor to monitor\n> + * \\param type The event type to monitor\n> + */\n> +EventNotifier::EventNotifier(int fd, Type type)\n> +\t: fd_(fd), type_(type), enabled_(false)\n> +{\n> +\tsetEnabled(true);\n> +}\n> +\n> +EventNotifier::~EventNotifier()\n> +{\n> +\tsetEnabled(false);\n> +}\n> +\n> +/**\n> + * \\fn EventNotifier::type()\n> + * \\brief Retrive the type of the event being monitored\n> + * \\return The type of the event\n> + */\n> +\n> +/**\n> + * \\fn EventNotifier::fd()\n> + * \\brief Retrive the file descriptor being monitored\n> + * \\return The file descriptor\n> + */\n> +\n> +/**\n> + * \\fn EventNotifier::enabled()\n> + * \\brief Retrieve the notifier state\n> + * \\return true if the notifier is enabled, or false otherwise\n\ns/true/True ?\n\n> + * \\sa setEnable()\n> + */\n> +\n> +/**\n> + * \\brief Enable or disable the notifier\n> + * \\param enable true to enable the notifier, false to disable it\n\ns/true/True ?\n\n> + *\n> + * This function enables or disables the notifier. A disabled notifier ignores\n> + * events and does not emit the \\ref activated signal.\n> + */\n> +void EventNotifier::setEnabled(bool enable)\n> +{\n> +\tif (enabled_ == enable)\n> +\t\treturn;\n> +\n> +\tenabled_ = enable;\n> +\n> +\tEventDispatcher *dispatcher = CameraManager::instance()->eventDispatcher();\n> +\tif (enable)\n> +\t\tdispatcher->registerEventNotifier(this);\n> +\telse\n> +\t\tdispatcher->unregisterEventNotifier(this);\n> +}\n> +\n> +/**\n> + * \\var EventNotifier::activated\n> + * \\brief Signal emitted when the event occurs\n> + *\n> + * This signal is emitted when the event \\ref type() occurs on the file\n> + * descriptor monitored by the notifier. The notifier pointer is passed as a\n> + * parameter.\n> + */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\n> index 3ec86e75b57e..61fb93205b34 100644\n> --- a/src/libcamera/meson.build\n> +++ b/src/libcamera/meson.build\n> @@ -2,11 +2,14 @@ libcamera_sources = files([\n>      'camera.cpp',\n>      'camera_manager.cpp',\n>      'device_enumerator.cpp',\n> +    'event_dispatcher.cpp',\n> +    'event_notifier.cpp',\n>      'log.cpp',\n>      'media_device.cpp',\n>      'media_object.cpp',\n>      'pipeline_handler.cpp',\n>      'signal.cpp',\n> +    'timer.cpp',\n>  ])\n>\n>  libcamera_headers = files([\n> diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp\n> new file mode 100644\n> index 000000000000..57c49aa2ef36\n> --- /dev/null\n> +++ b/src/libcamera/timer.cpp\n> @@ -0,0 +1,105 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2019, Google Inc.\n> + *\n> + * timer.cpp - Generic timer\n> + */\n> +\n> +#include <time.h>\n> +\n> +#include <libcamera/camera_manager.h>\n> +#include <libcamera/event_dispatcher.h>\n> +#include <libcamera/timer.h>\n> +\n> +#include \"log.h\"\n> +\n> +/**\n> + * \\file timer.h\n> + * \\brief Generic timer\n> + */\n> +\n> +namespace libcamera {\n> +\n> +/**\n> + * \\class Timer\n> + * \\brief Single-shot timer interface\n> + *\n> + * The Timer class models a single-shot timer that is started with start() and\n> + * emits the \\ref timeout signal when it times out.\n> + *\n> + * Once started the timer will run until it times out. It can be stopped with\n> + * stop(), and once it times out or is stopped, can be started again with\n> + * start().\n> + */\n> +\n> +/**\n> + * \\brief Construct a timer\n> + */\n> +Timer::Timer()\n> +{\n> +}\n> +\n> +/**\n> + * \\brief Start or restart the timer with a timeout of \\a msec\n> + * \\param msec The timer duration in milliseconds\n> + *\n> + * If the timer is already running it will be stopped and restarted.\n> + */\n> +void Timer::start(unsigned int msec)\n> +{\n> +\tstruct timespec tp;\n> +\tclock_gettime(CLOCK_MONOTONIC, &tp);\n> +\n> +\tinterval_ = msec;\n> +\tdeadline_ = tp.tv_sec * 1000000000ULL + tp.tv_nsec + msec * 1000000;\n> +\n> +\tLOG(Debug) << \"Starting timer \" << this << \" with interval \" << msec\n> +\t\t   << \": deadline \" << deadline_;\n> +\n> +\tCameraManager::instance()->eventDispatcher()->registerTimer(this);\n> +}\n> +\n> +/**\n> + * \\brief Stop the timer\n> + *\n> + * After this function returns the timer is guaranteed not to emit the\n> + * \\ref timeout signal.\n> + *\n> + * If the timer is not running this function performs no operation.\n> + */\n> +void Timer::stop()\n> +{\n> +\tCameraManager::instance()->eventDispatcher()->unregisterTimer(this);\n> +\n> +\tdeadline_ = 0;\n> +}\n> +\n> +/**\n> + * \\brief\n\nEmpty brief. I know, there's not much to say on this function...\n\n> + * \\return true if the timer is running, false otherwise\n\ns/true/True ?\n\n> + */\n> +bool Timer::isRunning() const\n> +{\n> +\treturn deadline_ != 0;\n> +}\n> +\n> +/**\n> + * \\fn Timer::interval()\n> + * \\brief Retrieve the timer interval\n> + * \\return The timer interval in milliseconds\n> + */\n> +\n> +/**\n> + * \\fn Timer::deadline()\n> + * \\brief Retrieve the timer deadline\n> + * \\return The timer deadline in nanoseconds\n> + */\n> +\n> +/**\n> + * \\var Timer::timeout\n> + * \\brief Signal emitted when the timer times out\n> + *\n> + * The timer pointer is passed as a parameter.\n> + */\n> +\n> +} /* namespace libcamera */\n\nThanks\n  j\n\n> --\n> Regards,\n>\n> Laurent Pinchart\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net\n\t[217.70.183.200])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 01A6860B2D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  8 Jan 2019 10:43:37 +0100 (CET)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 75B0620007;\n\tTue,  8 Jan 2019 09:43:37 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Tue, 8 Jan 2019 10:43:43 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190108094343.fbegwcuffbhcevbr@uno.localdomain>","References":"<20190107231151.23291-1-laurent.pinchart@ideasonboard.com>\n\t<20190107231151.23291-7-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"igeqwcx23u4d2i6w\"","Content-Disposition":"inline","In-Reply-To":"<20190107231151.23291-7-laurent.pinchart@ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v2 06/11] libcamera: Add event\n\tnotification infrastructure","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Tue, 08 Jan 2019 09:43:38 -0000"}}]