summaryrefslogtreecommitdiff
path: root/src/libcamera/camera_manager.cpp
blob: 50a805fc665cbf1d40042ad952dc948bb456b4f6 (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
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2018, Google Inc.
 *
 * camera_manager.h - Camera management
 */

#include <libcamera/camera_manager.h>

#include "device_enumerator.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)
{
}

/**
 * \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<std::string> handlers = PipelineHandlerFactory::handlers();

	for (std::string const &handler : handlers) {
		PipelineHandler *pipe;

		/*
		 * Try each pipeline handler until it exhaust
		 * all pipelines it can provide.
		 */
		do {
			pipe = PipelineHandlerFactory::create(handler, enumerator_);
			if (pipe)
				pipes_.push_back(pipe);
		} while (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;
}

} /* namespace libcamera */