LCOV - code coverage report
Current view: top level - media/client/main/source - WebAudioPlayer.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.8 % 120 109
Test Date: 2025-02-18 13:13:53 Functions: 89.5 % 19 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 2023 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 <cstring>
      21              : #include <limits.h>
      22              : #include <mutex>
      23              : #include <stdexcept>
      24              : 
      25              : #include "IWebAudioPlayerIpc.h"
      26              : #include "IWebAudioPlayerIpcClient.h"
      27              : #include "RialtoClientLogging.h"
      28              : #include "WebAudioPlayer.h"
      29              : #include "WebAudioPlayerProxy.h"
      30              : 
      31              : namespace firebolt::rialto
      32              : {
      33            2 : std::shared_ptr<IWebAudioPlayerFactory> IWebAudioPlayerFactory::createFactory()
      34              : {
      35            2 :     std::shared_ptr<IWebAudioPlayerFactory> factory;
      36              : 
      37              :     try
      38              :     {
      39            2 :         factory = std::make_shared<WebAudioPlayerFactory>();
      40              :     }
      41            0 :     catch (const std::exception &e)
      42              :     {
      43            0 :         RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player factory, reason: %s", e.what());
      44              :     }
      45              : 
      46            2 :     return factory;
      47              : }
      48              : 
      49              : std::unique_ptr<IWebAudioPlayer>
      50            0 : WebAudioPlayerFactory::createWebAudioPlayer(std::weak_ptr<IWebAudioPlayerClient> client, const std::string &audioMimeType,
      51              :                                             const uint32_t priority, std::weak_ptr<const WebAudioConfig> config) const
      52              : {
      53            0 :     return createWebAudioPlayer(client, audioMimeType, priority, config, {}, {});
      54              : }
      55              : 
      56              : std::unique_ptr<IWebAudioPlayer>
      57            2 : WebAudioPlayerFactory::createWebAudioPlayer(std::weak_ptr<IWebAudioPlayerClient> client, const std::string &audioMimeType,
      58              :                                             const uint32_t priority, std::weak_ptr<const WebAudioConfig> config,
      59              :                                             std::weak_ptr<client::IWebAudioPlayerIpcFactory> webAudioPlayerIpcFactory,
      60              :                                             std::weak_ptr<client::IClientController> clientController) const
      61              : {
      62            2 :     std::unique_ptr<IWebAudioPlayer> webAudioPlayer;
      63              :     try
      64              :     {
      65              :         std::shared_ptr<client::IWebAudioPlayerIpcFactory> webAudioPlayerIpcFactoryLocked =
      66            2 :             webAudioPlayerIpcFactory.lock();
      67            2 :         std::shared_ptr<client::IClientController> clientControllerLocked = clientController.lock();
      68              :         client::IClientController &cc = clientControllerLocked
      69            2 :                                             ? *clientControllerLocked
      70            2 :                                             : client::IClientControllerAccessor::instance().getClientController();
      71              : 
      72              :         auto wap{std::make_shared<client::WebAudioPlayer>(client, audioMimeType, priority, config,
      73              :                                                           webAudioPlayerIpcFactoryLocked
      74            3 :                                                               ? webAudioPlayerIpcFactoryLocked
      75            2 :                                                               : client::IWebAudioPlayerIpcFactory::getFactory(),
      76            2 :                                                           cc)};
      77            1 :         webAudioPlayer = std::make_unique<WebAudioPlayerProxy>(wap, cc);
      78            3 :     }
      79            1 :     catch (const std::exception &e)
      80              :     {
      81            1 :         RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player, reason: %s", e.what());
      82              :     }
      83              : 
      84            2 :     return webAudioPlayer;
      85              : }
      86              : 
      87            4 : WebAudioPlayerProxy::WebAudioPlayerProxy(const std::shared_ptr<IWebAudioPlayerAndIControlClient> &ptr,
      88            4 :                                          client::IClientController &clientController)
      89            4 :     : m_webAudioPlayer(ptr), m_clientController{clientController}
      90              : {
      91            4 :     ApplicationState state{ApplicationState::UNKNOWN};
      92            4 :     if (!m_clientController.registerClient(m_webAudioPlayer, state))
      93              :     {
      94            1 :         throw std::runtime_error("Failed to register client with clientController");
      95              :     }
      96            3 :     m_webAudioPlayer->notifyApplicationState(state);
      97            5 : }
      98              : 
      99            4 : WebAudioPlayerProxy::~WebAudioPlayerProxy()
     100              : {
     101            3 :     if (!m_clientController.unregisterClient(m_webAudioPlayer))
     102              :     {
     103            0 :         RIALTO_CLIENT_LOG_WARN("Failed to unregister client with clientController");
     104              :     }
     105            4 : }
     106              : 
     107              : }; // namespace firebolt::rialto
     108              : 
     109              : namespace firebolt::rialto::client
     110              : {
     111           32 : WebAudioPlayer::WebAudioPlayer(std::weak_ptr<IWebAudioPlayerClient> client, const std::string &audioMimeType,
     112              :                                const uint32_t priority, std::weak_ptr<const WebAudioConfig> webAudioConfig,
     113              :                                const std::shared_ptr<IWebAudioPlayerIpcFactory> &webAudioPlayerIpcFactory,
     114           32 :                                IClientController &clientController)
     115           96 :     : m_webAudioPlayerClient(client), m_clientController{clientController}, m_bytesPerFrame{0},
     116           32 :       m_currentAppState{ApplicationState::UNKNOWN}
     117              : {
     118           32 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     119              : 
     120           32 :     if (audioMimeType == "audio/x-raw")
     121              :     {
     122           32 :         std::shared_ptr<const WebAudioConfig> kConfig = webAudioConfig.lock();
     123           32 :         if (!kConfig)
     124              :         {
     125            0 :             throw std::runtime_error("Config is null for 'audio/x-raw'");
     126              :         }
     127           32 :         m_bytesPerFrame = kConfig->pcm.channels * (kConfig->pcm.sampleSize / CHAR_BIT);
     128           32 :         if (m_bytesPerFrame == 0)
     129              :         {
     130            0 :             throw std::runtime_error("Bytes per frame cannot be 0, channels " + std::to_string(kConfig->pcm.channels) +
     131            0 :                                      ", sampleSize " + std::to_string(kConfig->pcm.sampleSize));
     132              :         }
     133           32 :     }
     134              : 
     135           32 :     if (!webAudioPlayerIpcFactory)
     136              :     {
     137            0 :         throw std::runtime_error("Web audio player ipc factory could not be null");
     138              :     }
     139              : 
     140              :     m_webAudioPlayerIpc =
     141           32 :         webAudioPlayerIpcFactory->createWebAudioPlayerIpc(this, audioMimeType, priority, webAudioConfig);
     142           32 :     if (!m_webAudioPlayerIpc)
     143              :     {
     144            3 :         throw std::runtime_error("Web audio player ipc could not be created");
     145              :     }
     146           44 : }
     147              : 
     148           56 : WebAudioPlayer::~WebAudioPlayer()
     149              : {
     150           29 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     151              : 
     152           29 :     m_webAudioPlayerIpc.reset();
     153           56 : }
     154              : 
     155            2 : bool WebAudioPlayer::play()
     156              : {
     157            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     158              : 
     159            2 :     return m_webAudioPlayerIpc->play();
     160              : }
     161              : 
     162            2 : bool WebAudioPlayer::pause()
     163              : {
     164            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     165              : 
     166            2 :     return m_webAudioPlayerIpc->pause();
     167              : }
     168              : 
     169            2 : bool WebAudioPlayer::setEos()
     170              : {
     171            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     172              : 
     173            2 :     return m_webAudioPlayerIpc->setEos();
     174              : }
     175              : 
     176            9 : bool WebAudioPlayer::getBufferAvailable(uint32_t &availableFrames, std::shared_ptr<WebAudioShmInfo> &)
     177              : {
     178            9 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     179            9 :     std::lock_guard<std::mutex> bufLocker(m_bufLock);
     180            9 :     if (!m_webAudioShmInfo)
     181              :     {
     182            9 :         m_webAudioShmInfo = std::make_shared<WebAudioShmInfo>();
     183              :     }
     184           18 :     return m_webAudioPlayerIpc->getBufferAvailable(availableFrames, m_webAudioShmInfo);
     185            9 : }
     186              : 
     187            2 : bool WebAudioPlayer::getBufferDelay(uint32_t &delayFrames)
     188              : {
     189            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     190              : 
     191            2 :     return m_webAudioPlayerIpc->getBufferDelay(delayFrames);
     192              : }
     193              : 
     194            8 : bool WebAudioPlayer::writeBuffer(const uint32_t numberOfFrames, void *data)
     195              : {
     196            8 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     197              : 
     198            8 :     std::lock_guard<std::mutex> bufLocker(m_bufLock);
     199            8 :     if (!m_webAudioShmInfo)
     200              :     {
     201            1 :         RIALTO_CLIENT_LOG_ERROR("Web audio shared info is null!");
     202            1 :         return false;
     203              :     }
     204              : 
     205            7 :     uint32_t dataLength = numberOfFrames * m_bytesPerFrame;
     206            7 :     uint32_t availableDataLength = m_webAudioShmInfo->lengthMain + m_webAudioShmInfo->lengthWrap;
     207            7 :     if (dataLength > availableDataLength)
     208              :     {
     209            1 :         RIALTO_CLIENT_LOG_ERROR("The number of frames to write exceeds the available space!");
     210            1 :         return false;
     211              :     }
     212              : 
     213            6 :     if (ApplicationState::RUNNING != m_currentAppState)
     214              :     {
     215            1 :         RIALTO_CLIENT_LOG_ERROR("Current ApplicationState is not RUNNING!");
     216            1 :         return false;
     217              :     }
     218              : 
     219            5 :     std::shared_ptr<ISharedMemoryHandle> shmHandle = m_clientController.getSharedMemoryHandle();
     220            5 :     if (nullptr == shmHandle || nullptr == shmHandle->getShm())
     221              :     {
     222            2 :         RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid");
     223            2 :         return false;
     224              :     }
     225              : 
     226            3 :     if (dataLength > m_webAudioShmInfo->lengthMain)
     227              :     {
     228            1 :         std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetMain, data, m_webAudioShmInfo->lengthMain);
     229            1 :         std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetWrap,
     230            1 :                     reinterpret_cast<uint8_t *>(data) + m_webAudioShmInfo->lengthMain,
     231            1 :                     dataLength - m_webAudioShmInfo->lengthMain);
     232              :     }
     233              :     else
     234              :     {
     235            2 :         std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetMain, data, dataLength);
     236              :     }
     237            3 :     return m_webAudioPlayerIpc->writeBuffer(numberOfFrames);
     238            8 : }
     239              : 
     240            2 : bool WebAudioPlayer::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay)
     241              : {
     242            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     243              : 
     244            2 :     return m_webAudioPlayerIpc->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay);
     245              : }
     246              : 
     247            2 : bool WebAudioPlayer::setVolume(double volume)
     248              : {
     249            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     250              : 
     251            2 :     return m_webAudioPlayerIpc->setVolume(volume);
     252              : }
     253              : 
     254            2 : bool WebAudioPlayer::getVolume(double &volume)
     255              : {
     256            2 :     RIALTO_CLIENT_LOG_DEBUG("entry:");
     257              : 
     258            2 :     return m_webAudioPlayerIpc->getVolume(volume);
     259              : }
     260              : 
     261            0 : std::weak_ptr<IWebAudioPlayerClient> WebAudioPlayer::getClient()
     262              : {
     263            0 :     return m_webAudioPlayerClient;
     264              : }
     265              : 
     266            1 : void WebAudioPlayer::notifyState(WebAudioPlayerState state)
     267              : {
     268            1 :     std::shared_ptr<IWebAudioPlayerClient> client = m_webAudioPlayerClient.lock();
     269            1 :     if (client)
     270              :     {
     271            1 :         client->notifyState(state);
     272              :     }
     273              : }
     274              : 
     275           28 : void WebAudioPlayer::notifyApplicationState(ApplicationState state)
     276              : {
     277           28 :     m_currentAppState = state;
     278              : }
     279              : 
     280              : }; // namespace firebolt::rialto::client
        

Generated by: LCOV version 2.0-1