summaryrefslogtreecommitdiff
path: root/src/libcamera/camera_manager.cpp
blob: 91ef6753f4059869a884abae3f34fb01b2d3dbde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2018, Google Inc.
 *
 * camera_manager.h - Camera management
 */

#include <libcamera/camera_manager.h>
#include <libcamera/event_dispatcher.h>

#include "device_enumerator.h"
#include "event_dispatcher_poll.h"
#include "log.h"
#include "pipeline_handler.h"

/**
 * \file camera_manager.h
 * \brief Manage all cameras handled by libcamera
 *
 * The responsibility of the camera manager is to control the lifetime
 * management of objects provided by libcamera.
 *
 * When a user wish to interact with libcamera it creates and starts a
 * CameraManager object. Once confirmed the camera manager is running
 * the application can list all cameras detected by the library, get
 * one or more of the cameras and interact with them.
 *
 * When the user is done with the camera it should be returned to the
 * camera manager. Once all cameras are returned to the camera manager
 * the user is free to stop the manager.
 *
 * \todo Add ability to add and remove media devices based on
 *       hot-(un)plug events coming from the device enumerator.
 *
 * \todo Add interface to register a notification callback to the user
 *       to be able to inform it new cameras have been hot-plugged or
 *       cameras have been removed due to hot-unplug.
 */

namespace libcamera {

CameraManager::CameraManager()
	: enumerator_(nullptr), dispatcher_(nullptr)
{
}

CameraManager::~CameraManager()
{
	delete dispatcher_;
}

/**
 * \brief Start the camera manager
 *
 * Start the camera manager and enumerate all devices in the system. Once
 * the start has been confirmed the user is free to list and otherwise
 * interact with cameras in the system until either the camera manager
 * is stopped or the camera is unplugged from the system.
 *
 * \return true on successful start false otherwise
 */
int CameraManager::start()
{

	if (enumerator_)
		return -ENODEV;

	enumerator_ = DeviceEnumerator::create();
	if (enumerator_->enumerate())
		return -ENODEV;

	/*
	 * TODO: Try to read handlers and order from configuration
	 * file and only fallback on all handlers if there is no
	 * configuration file.
	 */
	std::vector<PipelineHandlerFactory *> &handlers = PipelineHandlerFactory::handlers();

	for (PipelineHandlerFactory *factory : handlers) {
		/*
		 * Try each pipeline handler until it exhaust
		 * all pipelines it can provide.
		 */
		while (1) {
			PipelineHandler *pipe = factory->create();
			if (!pipe->match(enumerator_)) {
				delete pipe;
				break;
			}

			LOG(Debug) << "Pipeline handler \"" << factory->name()
				   << "\" matched";
			pipes_.push_back(pipe);
		}
	}

	/* TODO: register hot-plug callback here */

	return 0;
}

/**
 * \brief Stop the camera manager
 *
 * Before stopping the camera manger the caller is responsible for making
 * sure all cameras provided by the manager are returned to the manager.
 *
 * After the manager has been stopped no resource provided by the camera
 * manager should be consider valid or functional even if they for one
 * reason or another have yet to be deleted.
 */
void CameraManager::stop()
{
	/* TODO: unregister hot-plug callback here */

	for (PipelineHandler *pipe : pipes_)
		delete pipe;

	pipes_.clear();

	if (enumerator_)
		delete enumerator_;

	enumerator_ = nullptr;
}

/**
 * \brief List all detected cameras
 *
 * Before calling this function the caller is responsible for ensuring that
 * the camera manger is running.
 *
 * \return List of names for all detected cameras
 */
std::vector<std::string> CameraManager::list() const
{
	std::vector<std::string> list;

	for (PipelineHandler *pipe : pipes_) {
		for (unsigned int i = 0; i < pipe->count(); i++) {
			Camera *cam = pipe->camera(i);
			list.push_back(cam->name());
		}
	}

	return list;
}

/**
 * \brief Get a camera based on name
 *
 * \param[in] name Name of camera to get
 *
 * Before calling this function the caller is responsible for ensuring that
 * the camera manger is running. A camera fetched this way shall be
 * released by the user with the put() method of the Camera object once
 * it is done using the camera.
 *
 * \return Pointer to Camera object or nullptr if camera not found
 */
Camera *CameraManager::get(const std::string &name)
{
	for (PipelineHandler *pipe : pipes_) {
		for (unsigned int i = 0; i < pipe->count(); i++) {
			Camera *cam = pipe->camera(i);
			if (cam->name() == name) {
				cam->get();
				return cam;
			}
		}
	}

	return nullptr;
}

/**
 * \brief Retrieve the camera manager instance
 *
 * The CameraManager is a singleton and can't be constructed manually. This
 * function shall instead be used to retrieve the single global instance of the
 * manager.
 *
 * \return The camera manager instance
 */
CameraManager *CameraManager::instance()
{
	static CameraManager manager;
	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 that want to provide
 * their own event dispatcher shall call this function once and only once before
 * the camera manager is started with start(). If no event dispatcher is
 * provided, a default poll-based implementation will be used.
 *
 * 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
 *
 * This function retrieves the event dispatcher set with setEventDispatcher().
 * If no dispatcher has been set, a default poll-based implementation is created
 * and returned, and no custom event dispatcher may be installed anymore.
 *
 * \return Pointer to the event dispatcher
 */
EventDispatcher *CameraManager::eventDispatcher()
{
	if (!dispatcher_)
		dispatcher_ = new EventDispatcherPoll();

	return dispatcher_;
}

} /* namespace libcamera */