LCOV - code coverage report
Current view: top level - muse/framework/rcommand - icommanddispatcher.h Coverage Total Hit
Test: filtered_coverage.info Lines: 24.4 % 41 10
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore/Audacity CLA applies
       4              :  *
       5              :  * Copyright (C) MuseScore/Audacity and others
       6              :  *
       7              :  * This program is free software: you can redistribute it and/or modify
       8              :  * it under the terms of the GNU General Public License version 3 as
       9              :  * published by the Free Software Foundation.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14              :  * GNU General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU General Public License
      17              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18              :  */
      19              : 
      20              : #pragma once
      21              : 
      22              : #include "modularity/imoduleinterface.h"
      23              : 
      24              : #include "global/async/promise.h"
      25              : #include "global/async/channel.h"
      26              : #include "global/types/ret.h"
      27              : #include "global/types/retval.h"
      28              : #include "commandtypes.h"
      29              : #include "typedcommand.h"
      30              : 
      31              : namespace muse::rcommand {
      32              : class Commandable;
      33              : class ICommandDispatcher : MODULE_CONTEXT_INTERFACE
      34              : {
      35           38 :     INTERFACE_ID(ICommandDispatcher)
      36              : public:
      37          157 :     virtual ~ICommandDispatcher() = default;
      38              : 
      39              :     using OnResponse = std::function<void (const Response& response)>;
      40              : 
      41              :     using CallBack = std::function<Response (const Request& request)>;
      42              :     using AsyncCallBack = std::function<void (const Request& request, OnResponse onResponse)>;
      43              : 
      44              :     using CallBackRet = std::function<Ret ()>;
      45              :     using CallBackParamsRet = std::function<Ret (const Params& params)>;
      46              :     using CallBackParamsPromiseRet = std::function<async::Promise<Ret>(const Params& params)>;
      47              : 
      48              :     virtual async::Promise<Response> dispatch(const Request& request) = 0;
      49              :     virtual void onRequest(Commandable* client, const Command& command, const CallBack& callback) = 0;
      50              :     virtual void onRequest(Commandable* client, const Command& command, const AsyncCallBack& callback) = 0;
      51              :     virtual void unreg(Commandable* client) = 0;
      52              : 
      53              :     virtual async::Channel<Command, bool* /*allow dispatch*/> preDispatch() const = 0;
      54              :     virtual async::Channel<Command> postDispatch() const = 0;
      55              : 
      56              :     // Helpers for convenience
      57            1 :     async::Promise<Response> dispatch(const Command& command)
      58              :     {
      59            1 :         return dispatch(make_request(command, {}));
      60              :     }
      61              : 
      62            7 :     async::Promise<Response> dispatch(const Command& command, const Params& params)
      63              :     {
      64            7 :         return dispatch(make_request(command, params));
      65              :     }
      66              : 
      67            0 :     async::Promise<Response> dispatch(const CommandQuery& query)
      68              :     {
      69            0 :         return dispatch(make_request(query.uri(), query.params()));
      70              :     }
      71              : 
      72          530 :     void onRequest(Commandable* client, const Command& command, const CallBackRet& callback)
      73              :     {
      74          530 :         onRequest(client, command, [callback](const Request& request) {
      75           36 :             return make_response(request, callback());
      76              :         });
      77          530 :     }
      78              : 
      79            0 :     void onRequest(Commandable* client, const Command& command, const CallBackParamsRet& callback)
      80              :     {
      81            0 :         onRequest(client, command, [callback](const Request& request) {
      82            0 :             return make_response(request, callback(request.params));
      83              :         });
      84            0 :     }
      85              : 
      86            0 :     void onRequest(Commandable* client, const Command& command, const CallBackParamsPromiseRet& callback)
      87              :     {
      88            0 :         onRequest(client, command, AsyncCallBack([callback](const Request& request, const OnResponse& onResponse) {
      89            0 :             answerWhenResolved(request, callback(request.params), onResponse);
      90            0 :         }));
      91            0 :     }
      92              : 
      93              :     // Typed commands
      94              :     template<TypedCommand C>
      95              :     async::Promise<Response> dispatch(const C& command)
      96              :     {
      97              :         Params params;
      98              :         if constexpr (HasInput<C>) {
      99              :             params = toInputParams(command);
     100              :         }
     101              :         return dispatch(make_request(command.id, params));
     102              :     }
     103              : 
     104              :     template<TypedCommand C>
     105            0 :     void onRequest(Commandable* client, std::function<Ret(const C&)> callback)
     106              :     {
     107            0 :         onRequest(client, C::id, CallBack([callback](const Request& request) {
     108            0 :             C command;
     109              :             if constexpr (HasInput<C>) {
     110            0 :                 ConvertParamsResult res = fromInputParams(request.params, command);
     111            0 :                 if (!res) {
     112            0 :                     return make_response(request, res.ret);
     113              :                 }
     114            0 :             }
     115            0 :             return make_response(request, callback(command));
     116              :         }));
     117            0 :     }
     118              : 
     119              :     template<HasOutput C>
     120            0 :     void onRequest(Commandable* client, std::function<RetVal<typename C::Output>(const C&)> callback)
     121              :     {
     122            0 :         onRequest(client, C::id, CallBack([callback](const Request& request) {
     123              :             C command;
     124              :             if constexpr (HasInput<C>) {
     125              :                 ConvertParamsResult res = fromInputParams(request.params, command);
     126              :                 if (!res) {
     127              :                     return make_response(request, res.ret);
     128              :                 }
     129              :             }
     130            0 :             RetVal<typename C::Output> rv = callback(command);
     131            0 :             return make_response(request, rv.ret, toOutputParams<C>(rv.val));
     132            0 :         }));
     133            0 :     }
     134              : 
     135              : private:
     136              : 
     137            0 :     static void answerWhenResolved(const Request& request, async::Promise<Ret> retPromise, const OnResponse& onResponse)
     138              :     {
     139            0 :         retPromise.onResolve(nullptr, [request, onResponse](const Ret& ret) {
     140            0 :             onResponse(make_response(request, ret));
     141            0 :         });
     142            0 :     }
     143              : };
     144              : }
        

Generated by: LCOV version 2.0-1