Music Hub ..
A session-wide music playback service
server.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
17 */
18
19#include <core/media/service.h>
20#include <core/media/player.h>
22
26
27#include <hybris/media/media_codec_layer.h>
28
29#include <core/posix/signal.h>
30
31#include <iostream>
32
33namespace media = core::ubuntu::media;
34
35using namespace std;
36
37namespace
38{
39void logger_init()
40{
41 const char *level = ::getenv("MH_LOG_LEVEL");
42 // Default level is kInfo
43 media::Logger::Severity severity{media::Logger::Severity::kInfo};
44 if (level)
45 {
46 if (strcmp(level, "trace") == 0)
47 severity = media::Logger::Severity::kTrace;
48 else if (strcmp(level, "debug") == 0)
49 severity = media::Logger::Severity::kDebug;
50 else if (strcmp(level, "info") == 0)
51 severity = media::Logger::Severity::kInfo;
52 else if (strcmp(level, "warning") == 0)
53 severity = media::Logger::Severity::kWarning;
54 else if (strcmp(level, "error") == 0)
55 severity = media::Logger::Severity::kError;
56 else if (strcmp(level, "fatal") == 0)
57 severity = media::Logger::Severity::kFatal;
58 else
59 std::cerr << "Invalid log level \"" << level
60 << "\", setting to info. Valid options: [trace, debug, info, warning, error, fatal]."
61 << std::endl;
62 }
63 else
64 std::cout << "Using default log level: info" << std::endl;
65
66 media::Log().Init(severity);
67 cout << "Log level: " << severity << std::endl;
68}
69
70// All platform-specific initialization routines go here.
71void platform_init()
72{
74 switch (b)
75 {
76 case media::AVBackend::Backend::hybris:
77 MH_DEBUG("Found hybris backend");
78 decoding_service_init();
79 break;
80 case media::AVBackend::Backend::mir:
81 MH_DEBUG("Found mir backend");
82 break;
83 case media::AVBackend::Backend::none:
84 MH_WARNING("No video backend selected. Video functionality won't work.");
85 break;
86 default:
87 MH_INFO("Invalid or no A/V backend specified, using \"hybris\" as a default.");
88 decoding_service_init();
89 }
90}
91}
92
93int main()
94{
95 auto trap = core::posix::trap_signals_for_all_subsequent_threads(
96 {
97 core::posix::Signal::sig_int,
98 core::posix::Signal::sig_term
99 });
100
101 trap->signal_raised().connect([trap](core::posix::Signal)
102 {
103 trap->stop();
104 });
105
106 logger_init();
107
108 // Init platform-specific functionality.
109 platform_init();
110
111 // We keep track of our state.
112 bool shutdown_requested{false};
113
114 // Our helper for connecting to external services.
116
117 // We move communication with all external services to its own worker thread
118 // to keep the actual service thread free from such operations.
119 std::thread external_services_worker
120 {
121 // We keep on running until shutdown has been explicitly requested.
122 // All exceptions thrown on this thread are caught, and reported to
123 // the terminal for post-mortem debugging purposes.
124 [&shutdown_requested, &external_services]()
125 {
126 while (not shutdown_requested)
127 {
128 try
129 {
130 // Blocking call to the underlying reactor implementation.
131 // Only returns cleanly when explicitly stopped.
132 external_services.io_context.run();
133 }
134 catch (const std::exception& e)
135 {
136 std::cerr << "Error while executing the underlying io_context: " << e.what() << std::endl;
137 }
138 catch (...)
139 {
140 std::cerr << "Error while executing the underlying io_context." << std::endl;
141 }
142 }
143 }
144 };
145
146 // Our common player store instance for tracking player instances.
147 auto player_store = std::make_shared<media::HashedKeyedPlayerStore>();
148 // We assemble the configuration for executing the service now.
149 media::ServiceImplementation::Configuration service_config
150 {
151 std::make_shared<media::HashedKeyedPlayerStore>(),
152 external_services
153 };
154
155 auto impl = std::make_shared<media::ServiceImplementation>(media::ServiceImplementation::Configuration
156 {
157 player_store,
158 external_services
159 });
160
161 auto skeleton = std::make_shared<media::ServiceSkeleton>(media::ServiceSkeleton::Configuration
162 {
163 impl,
164 player_store,
165 external_services,
166 nullptr
167 });
168
169 std::thread service_worker
170 {
171 [&shutdown_requested, skeleton]()
172 {
173 while (not shutdown_requested)
174 {
175 try
176 {
177 skeleton->run();
178 }
179 catch (const std::exception& e)
180 {
181 std::cerr << "Recoverable error while executing the service: " << e.what() << std::endl;
182 }
183 catch (...)
184 {
185 std::cerr << "Recoverable error while executing the service." << std::endl;
186 }
187 }
188 }
189 };
190
191 // We block on waiting for signals telling us to gracefully shutdown.
192 // Incoming signals are handled in a lambda connected to signal_raised()
193 // which is setup at the beginning of main(...).
194 trap->run();
195
196 // Inform our workers that we should shutdown gracefully
197 shutdown_requested = true;
198
199 // And stop execution of helper and actual service.
200 skeleton->stop();
201
202 if (service_worker.joinable())
203 service_worker.join();
204
205 external_services.stop();
206
207 if (external_services_worker.joinable())
208 external_services_worker.join();
209
210 return 0;
211}
virtual void Init(const core::ubuntu::media::Logger::Severity &severity=core::ubuntu::media::Logger::Severity::kWarning)=0
#define MH_INFO(...)
Definition: logger.h:125
#define MH_WARNING(...)
Definition: logger.h:127
#define MH_DEBUG(...)
Definition: logger.h:123
Logger & Log()
Definition: logger.cpp:151
int main()
Definition: server.cpp:93
static Backend get_backend_type()
Returns the type of audio/video decoding/encoding backend being used.
Definition: backend.cpp:26