LCOV - code coverage report
Current view: top level - media/server/ipc/source - WebAudioPlayerModuleService.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.5 % 147 133
Test Date: 2025-02-18 13:13:53 Functions: 100.0 % 17 17

            Line data    Source code
       1              : /*
       2              :  * If not stated otherwise in this file or this component's LICENSE file the
       3              :  * following copyright and licenses apply:
       4              :  *
       5              :  * Copyright 2022 Sky UK
       6              :  *
       7              :  * Licensed under the Apache License, Version 2.0 (the "License");
       8              :  * you may not use this file except in compliance with the License.
       9              :  * You may obtain a copy of the License at
      10              :  *
      11              :  * http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  * Unless required by applicable law or agreed to in writing, software
      14              :  * distributed under the License is distributed on an "AS IS" BASIS,
      15              :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  * See the License for the specific language governing permissions and
      17              :  * limitations under the License.
      18              :  */
      19              : 
      20              : #include "WebAudioPlayerModuleService.h"
      21              : #include "IWebAudioPlayerService.h"
      22              : #include "RialtoServerLogging.h"
      23              : #include "WebAudioPlayerClient.h"
      24              : #include <IIpcController.h>
      25              : #include <algorithm>
      26              : #include <cstdint>
      27              : 
      28              : namespace
      29              : {
      30            5 : int generateHandle()
      31              : {
      32              :     static int webAudioPlayerHandle{0};
      33            5 :     return webAudioPlayerHandle++;
      34              : }
      35              : } // namespace
      36              : 
      37              : namespace firebolt::rialto::server::ipc
      38              : {
      39            1 : std::shared_ptr<IWebAudioPlayerModuleServiceFactory> IWebAudioPlayerModuleServiceFactory::createFactory()
      40              : {
      41            1 :     std::shared_ptr<IWebAudioPlayerModuleServiceFactory> factory;
      42              : 
      43              :     try
      44              :     {
      45            1 :         factory = std::make_shared<WebAudioPlayerModuleServiceFactory>();
      46              :     }
      47            0 :     catch (const std::exception &e)
      48              :     {
      49            0 :         RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player module service factory, reason: %s", e.what());
      50              :     }
      51              : 
      52            1 :     return factory;
      53              : }
      54              : 
      55              : std::shared_ptr<IWebAudioPlayerModuleService>
      56            1 : WebAudioPlayerModuleServiceFactory::create(service::IWebAudioPlayerService &webAudioPlayerService) const
      57              : {
      58            1 :     std::shared_ptr<IWebAudioPlayerModuleService> webAudioPlayerModule;
      59              : 
      60              :     try
      61              :     {
      62            1 :         webAudioPlayerModule = std::make_shared<WebAudioPlayerModuleService>(webAudioPlayerService);
      63              :     }
      64            0 :     catch (const std::exception &e)
      65              :     {
      66            0 :         RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player module service, reason: %s", e.what());
      67              :     }
      68              : 
      69            1 :     return webAudioPlayerModule;
      70              : }
      71              : 
      72           28 : WebAudioPlayerModuleService::WebAudioPlayerModuleService(service::IWebAudioPlayerService &webAudioPlayerService)
      73           28 :     : m_webAudioPlayerService{webAudioPlayerService}
      74              : {
      75              : }
      76              : 
      77              : WebAudioPlayerModuleService::~WebAudioPlayerModuleService() {}
      78              : 
      79            2 : void WebAudioPlayerModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient)
      80              : {
      81            2 :     RIALTO_SERVER_LOG_INFO("Client Connected!");
      82              :     {
      83            2 :         m_clientWebAudioPlayerHandles.emplace(ipcClient, std::set<int>());
      84              :     }
      85            2 :     ipcClient->exportService(shared_from_this());
      86              : }
      87              : 
      88            1 : void WebAudioPlayerModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient)
      89              : {
      90            1 :     RIALTO_SERVER_LOG_INFO("Client disconnected!");
      91            1 :     std::set<int> webAudioPlayerHandles;
      92              :     {
      93            1 :         auto handleIter = m_clientWebAudioPlayerHandles.find(ipcClient);
      94            1 :         if (handleIter == m_clientWebAudioPlayerHandles.end())
      95              :         {
      96            0 :             RIALTO_SERVER_LOG_ERROR("unknown client disconnected");
      97            0 :             return;
      98              :         }
      99            1 :         webAudioPlayerHandles = handleIter->second; // copy to avoid deadlock
     100            1 :         m_clientWebAudioPlayerHandles.erase(handleIter);
     101              :     }
     102            2 :     for (const auto &webAudioPlayerHandle : webAudioPlayerHandles)
     103              :     {
     104            1 :         m_webAudioPlayerService.destroyWebAudioPlayer(webAudioPlayerHandle);
     105              :     }
     106              : }
     107              : 
     108            5 : void WebAudioPlayerModuleService::createWebAudioPlayer(::google::protobuf::RpcController *controller,
     109              :                                                        const ::firebolt::rialto::CreateWebAudioPlayerRequest *request,
     110              :                                                        ::firebolt::rialto::CreateWebAudioPlayerResponse *response,
     111              :                                                        ::google::protobuf::Closure *done)
     112              : {
     113            5 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     114            5 :     auto ipcController = dynamic_cast<firebolt::rialto::ipc::IController *>(controller);
     115            5 :     if (!ipcController)
     116              :     {
     117            0 :         RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object");
     118            0 :         controller->SetFailed("ipc library provided incompatible controller object");
     119            0 :         done->Run();
     120            0 :         return;
     121              :     }
     122              : 
     123            5 :     std::shared_ptr<WebAudioConfig> config = std::make_shared<WebAudioConfig>();
     124            5 :     if (request->has_config())
     125              :     {
     126            1 :         if (request->config().has_pcm())
     127              :         {
     128            1 :             config->pcm.rate = request->config().pcm().rate();
     129            1 :             config->pcm.channels = request->config().pcm().channels();
     130            1 :             config->pcm.sampleSize = request->config().pcm().sample_size();
     131            1 :             config->pcm.isBigEndian = request->config().pcm().is_big_endian();
     132            1 :             config->pcm.isSigned = request->config().pcm().is_signed();
     133            1 :             config->pcm.isFloat = request->config().pcm().is_float();
     134              :         }
     135              :     }
     136            5 :     int handle = generateHandle();
     137              :     bool webAudioPlayerCreated =
     138           10 :         m_webAudioPlayerService.createWebAudioPlayer(handle,
     139           10 :                                                      std::make_shared<WebAudioPlayerClient>(handle,
     140           10 :                                                                                             ipcController->getClient()),
     141              :                                                      request->audio_mime_type(), request->priority(), config);
     142            5 :     if (webAudioPlayerCreated)
     143              :     {
     144              :         // Assume that IPC library works well and client is present
     145            4 :         m_clientWebAudioPlayerHandles[ipcController->getClient()].insert(handle);
     146            4 :         response->set_web_audio_player_handle(handle);
     147              :     }
     148              :     else
     149              :     {
     150            1 :         RIALTO_SERVER_LOG_ERROR("Create web audio player failed");
     151            1 :         controller->SetFailed("Operation failed");
     152              :     }
     153            5 :     done->Run();
     154              : }
     155              : 
     156            2 : void WebAudioPlayerModuleService::destroyWebAudioPlayer(::google::protobuf::RpcController *controller,
     157              :                                                         const ::firebolt::rialto::DestroyWebAudioPlayerRequest *request,
     158              :                                                         ::firebolt::rialto::DestroyWebAudioPlayerResponse *response,
     159              :                                                         ::google::protobuf::Closure *done)
     160              : {
     161            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     162            2 :     auto ipcController = dynamic_cast<firebolt::rialto::ipc::IController *>(controller);
     163            2 :     if (!ipcController)
     164              :     {
     165            0 :         RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object");
     166            0 :         controller->SetFailed("ipc library provided incompatible controller object");
     167            0 :         done->Run();
     168            1 :         return;
     169              :     }
     170            2 :     if (!m_webAudioPlayerService.destroyWebAudioPlayer(request->web_audio_player_handle()))
     171              :     {
     172            1 :         RIALTO_SERVER_LOG_ERROR("Destroy web audio player failed");
     173            1 :         controller->SetFailed("Operation failed");
     174            1 :         done->Run();
     175            1 :         return;
     176              :     }
     177            1 :     auto handleIter = m_clientWebAudioPlayerHandles.find(ipcController->getClient());
     178            1 :     if (handleIter != m_clientWebAudioPlayerHandles.end())
     179              :     {
     180            0 :         handleIter->second.erase(request->web_audio_player_handle());
     181              :     }
     182            1 :     done->Run();
     183              : }
     184              : 
     185            2 : void WebAudioPlayerModuleService::play(::google::protobuf::RpcController *controller,
     186              :                                        const ::firebolt::rialto::WebAudioPlayRequest *request,
     187              :                                        ::firebolt::rialto::WebAudioPlayResponse *response,
     188              :                                        ::google::protobuf::Closure *done)
     189              : {
     190            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     191            2 :     if (!m_webAudioPlayerService.play(request->web_audio_player_handle()))
     192              :     {
     193            1 :         RIALTO_SERVER_LOG_ERROR("play failed");
     194            1 :         controller->SetFailed("Operation failed");
     195              :     }
     196            2 :     done->Run();
     197              : }
     198              : 
     199            2 : void WebAudioPlayerModuleService::pause(::google::protobuf::RpcController *controller,
     200              :                                         const ::firebolt::rialto::WebAudioPauseRequest *request,
     201              :                                         ::firebolt::rialto::WebAudioPauseResponse *response,
     202              :                                         ::google::protobuf::Closure *done)
     203              : {
     204            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     205            2 :     if (!m_webAudioPlayerService.pause(request->web_audio_player_handle()))
     206              :     {
     207            1 :         RIALTO_SERVER_LOG_ERROR("pause failed");
     208            1 :         controller->SetFailed("Operation failed");
     209              :     }
     210            2 :     done->Run();
     211              : }
     212              : 
     213            2 : void WebAudioPlayerModuleService::setEos(::google::protobuf::RpcController *controller,
     214              :                                          const ::firebolt::rialto::WebAudioSetEosRequest *request,
     215              :                                          ::firebolt::rialto::WebAudioSetEosResponse *response,
     216              :                                          ::google::protobuf::Closure *done)
     217              : {
     218            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     219            2 :     if (!m_webAudioPlayerService.setEos(request->web_audio_player_handle()))
     220              :     {
     221            1 :         RIALTO_SERVER_LOG_ERROR("setEos failed");
     222            1 :         controller->SetFailed("Operation failed");
     223              :     }
     224            2 :     done->Run();
     225              : }
     226              : 
     227            2 : void WebAudioPlayerModuleService::getBufferAvailable(::google::protobuf::RpcController *controller,
     228              :                                                      const ::firebolt::rialto::WebAudioGetBufferAvailableRequest *request,
     229              :                                                      ::firebolt::rialto::WebAudioGetBufferAvailableResponse *response,
     230              :                                                      ::google::protobuf::Closure *done)
     231              : {
     232            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     233              : 
     234            2 :     uint32_t availableFrames{};
     235            2 :     std::shared_ptr<WebAudioShmInfo> shmInfo = std::make_shared<WebAudioShmInfo>();
     236            2 :     if (!m_webAudioPlayerService.getBufferAvailable(request->web_audio_player_handle(), availableFrames, shmInfo))
     237              :     {
     238            1 :         RIALTO_SERVER_LOG_ERROR("getBufferAvailable failed");
     239            1 :         controller->SetFailed("Operation failed");
     240              :     }
     241              :     else
     242              :     {
     243            1 :         response->set_available_frames(availableFrames);
     244            1 :         auto responseShmInfo = response->mutable_shm_info();
     245            1 :         responseShmInfo->set_offset_main(shmInfo->offsetMain);
     246            1 :         responseShmInfo->set_length_main(shmInfo->lengthMain);
     247            1 :         responseShmInfo->set_offset_wrap(shmInfo->offsetWrap);
     248            1 :         responseShmInfo->set_length_wrap(shmInfo->lengthWrap);
     249              :     }
     250            2 :     done->Run();
     251              : }
     252              : 
     253            2 : void WebAudioPlayerModuleService::getBufferDelay(::google::protobuf::RpcController *controller,
     254              :                                                  const ::firebolt::rialto::WebAudioGetBufferDelayRequest *request,
     255              :                                                  ::firebolt::rialto::WebAudioGetBufferDelayResponse *response,
     256              :                                                  ::google::protobuf::Closure *done)
     257              : {
     258            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     259              : 
     260            2 :     uint32_t delayFrames{};
     261            2 :     if (!m_webAudioPlayerService.getBufferDelay(request->web_audio_player_handle(), delayFrames))
     262              :     {
     263            1 :         RIALTO_SERVER_LOG_ERROR("getBufferDelay failed");
     264            1 :         controller->SetFailed("Operation failed");
     265              :     }
     266              :     else
     267              :     {
     268            1 :         response->set_delay_frames(delayFrames);
     269              :     }
     270            2 :     done->Run();
     271              : }
     272              : 
     273            2 : void WebAudioPlayerModuleService::writeBuffer(::google::protobuf::RpcController *controller,
     274              :                                               const ::firebolt::rialto::WebAudioWriteBufferRequest *request,
     275              :                                               ::firebolt::rialto::WebAudioWriteBufferResponse *response,
     276              :                                               ::google::protobuf::Closure *done)
     277              : {
     278            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     279            2 :     if (!m_webAudioPlayerService.writeBuffer(request->web_audio_player_handle(), request->number_of_frames(), nullptr))
     280              :     {
     281            1 :         RIALTO_SERVER_LOG_ERROR("writeBuffer failed");
     282            1 :         controller->SetFailed("Operation failed");
     283              :     }
     284            2 :     done->Run();
     285              : }
     286              : 
     287            2 : void WebAudioPlayerModuleService::getDeviceInfo(::google::protobuf::RpcController *controller,
     288              :                                                 const ::firebolt::rialto::WebAudioGetDeviceInfoRequest *request,
     289              :                                                 ::firebolt::rialto::WebAudioGetDeviceInfoResponse *response,
     290              :                                                 ::google::protobuf::Closure *done)
     291              : {
     292            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     293              : 
     294            2 :     uint32_t preferredFrames{};
     295            2 :     uint32_t maximumFrames{};
     296            2 :     bool supportDeferredPlay{};
     297            2 :     if (!m_webAudioPlayerService.getDeviceInfo(request->web_audio_player_handle(), preferredFrames, maximumFrames,
     298              :                                                supportDeferredPlay))
     299              :     {
     300            1 :         RIALTO_SERVER_LOG_ERROR("getDeviceInfo failed");
     301            1 :         controller->SetFailed("Operation failed");
     302              :     }
     303              :     else
     304              :     {
     305            1 :         response->set_preferred_frames(preferredFrames);
     306            1 :         response->set_maximum_frames(maximumFrames);
     307            1 :         response->set_support_deferred_play(supportDeferredPlay);
     308              :     }
     309            2 :     done->Run();
     310              : }
     311              : 
     312            2 : void WebAudioPlayerModuleService::setVolume(::google::protobuf::RpcController *controller,
     313              :                                             const ::firebolt::rialto::WebAudioSetVolumeRequest *request,
     314              :                                             ::firebolt::rialto::WebAudioSetVolumeResponse *response,
     315              :                                             ::google::protobuf::Closure *done)
     316              : {
     317            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     318            2 :     if (!m_webAudioPlayerService.setVolume(request->web_audio_player_handle(), request->volume()))
     319              :     {
     320            1 :         RIALTO_SERVER_LOG_ERROR("setVolume failed");
     321            1 :         controller->SetFailed("Operation failed");
     322              :     }
     323            2 :     done->Run();
     324              : }
     325              : 
     326            2 : void WebAudioPlayerModuleService::getVolume(::google::protobuf::RpcController *controller,
     327              :                                             const ::firebolt::rialto::WebAudioGetVolumeRequest *request,
     328              :                                             ::firebolt::rialto::WebAudioGetVolumeResponse *response,
     329              :                                             ::google::protobuf::Closure *done)
     330              : {
     331            2 :     RIALTO_SERVER_LOG_DEBUG("entry:");
     332              : 
     333            2 :     double volume{};
     334            2 :     if (!m_webAudioPlayerService.getVolume(request->web_audio_player_handle(), volume))
     335              :     {
     336            1 :         RIALTO_SERVER_LOG_ERROR("getVolume failed");
     337            1 :         controller->SetFailed("Operation failed");
     338              :     }
     339              :     else
     340              :     {
     341            1 :         response->set_volume(volume);
     342              :     }
     343            2 :     done->Run();
     344              : }
     345              : 
     346              : } // namespace firebolt::rialto::server::ipc
        

Generated by: LCOV version 2.0-1