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>
21 #include <core/media/track_list.h>
22 
25 
26 #include <core/posix/signal.h>
27 
28 #include <iostream>
29 
30 namespace media = core::ubuntu::media;
31 
32 using namespace std;
33 
34 #if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
35 #include <hybris/media/media_codec_layer.h>
36 
37 namespace
38 {
39 // All platform-specific initialization routines go here.
40 void platform_init()
41 {
42  decoding_service_init();
43 }
44 }
45 #else // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
46 namespace
47 {
48 // All platform-specific initialization routines go here.
49 void platform_init()
50 {
51  // Consciously left empty
52 }
53 }
54 #endif // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
55 
56 int main()
57 {
58  auto trap = core::posix::trap_signals_for_all_subsequent_threads(
59  {
60  core::posix::Signal::sig_int,
61  core::posix::Signal::sig_term
62  });
63 
64  trap->signal_raised().connect([trap](core::posix::Signal)
65  {
66  trap->stop();
67  });
68 
69  // Init platform-specific functionality.
70  platform_init();
71 
72  // We keep track of our state.
73  bool shutdown_requested{false};
74 
75  // Our helper for connecting to external services.
77 
78  // We move communication with all external services to its own worker thread
79  // to keep the actual service thread free from such operations.
80  std::thread external_services_worker
81  {
82  // We keep on running until shutdown has been explicitly requested.
83  // All exceptions thrown on this thread are caught, and reported to
84  // the terminal for post-mortem debugging purposes.
85  [&shutdown_requested, &external_services]()
86  {
87  while (not shutdown_requested)
88  {
89  try
90  {
91  // Blocking call to the underlying reactor implementation.
92  // Only returns cleanly when explicitly stopped.
93  external_services.io_service.run();
94  }
95  catch (const std::exception& e)
96  {
97  std::cerr << "Error while executing the underlying io_service: " << e.what() << std::endl;
98  }
99  catch (...)
100  {
101  std::cerr << "Error while executing the underlying io_service." << std::endl;
102  }
103  }
104  }
105  };
106 
107  // Our common player store instance for tracking player instances.
108  auto player_store = std::make_shared<media::HashedKeyedPlayerStore>();
109  // We assemble the configuration for executing the service now.
110  media::ServiceImplementation::Configuration service_config
111  {
112  std::make_shared<media::HashedKeyedPlayerStore>(),
113  external_services
114  };
115 
116  auto impl = std::make_shared<media::ServiceImplementation>(media::ServiceImplementation::Configuration
117  {
118  player_store,
119  external_services
120  });
121 
122  auto skeleton = std::make_shared<media::ServiceSkeleton>(media::ServiceSkeleton::Configuration
123  {
124  impl,
125  player_store,
126  external_services
127  });
128 
129  std::thread service_worker
130  {
131  [&shutdown_requested, skeleton]()
132  {
133  while (not shutdown_requested)
134  {
135  try
136  {
137  skeleton->run();
138  }
139  catch (const std::exception& e)
140  {
141  std::cerr << "Recoverable error while executing the service: " << e.what() << std::endl;
142  }
143  catch (...)
144  {
145  std::cerr << "Recoverable error while executing the service." << std::endl;
146  }
147  }
148  }
149  };
150 
151  // We block on waiting for signals telling us to gracefully shutdown.
152  // Incoming signals are handled in a lambda connected to signal_raised()
153  // which is setup at the beginning of main(...).
154  trap->run();
155 
156  // Inform our workers that we should shutdown gracefully
157  shutdown_requested = true;
158 
159  // And stop execution of helper and actual service.
160  skeleton->stop();
161 
162  if (service_worker.joinable())
163  service_worker.join();
164 
165  external_services.stop();
166 
167  if (external_services_worker.joinable())
168  external_services_worker.join();
169 
170  return 0;
171 }
STL namespace.
int main()
Definition: server.cpp:56