Files
2026-08-24 10:03:24 +08:00

917 lines
25 KiB
C++

/*
* Copyright (C) 2014-present Amlogic, Inc. All rights reserved.
*
* All information contained herein is Amlogic confidential.
*
* This software is provided to you pursuant to Software License Agreement
* (SLA) with Amlogic Inc ("Amlogic"). This software may be used
* only in accordance with the terms of this agreement.
*
* Redistribution and use in source and binary forms, with or without
* modification is strictly prohibited without prior written permission from
* Amlogic.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <future>
#include <mutex>
#include <poll.h>
#include <thread>
#include <vector>
#include <systemd/sd-bus.h>
#include "dbus_defines.h"
#define LOG_MODULE_TAG "TV"
#define LOG_CLASS_TAG "TvClient"
#include "CTvLog.h"
#include "TvClient.h"
static sd_bus *gs_signal_bus = nullptr;
bool tvclient_preset_signal_bus(sd_bus *bus) {
if (nullptr == bus) {
LOGE("invalid parameter\n");
return false;
}
if (nullptr != gs_signal_bus) {
LOGE("signal bus already set\n");
return false;
}
gs_signal_bus = bus;
return true;
}
static int gs_method_call_pipe[2];
static std::vector<TvClient::TvClientIObserver *> mTvClientObserver;
static int SendEvent(CTvEvent &event) {
for (const auto &o : mTvClientObserver) {
if (o != nullptr) {
o->onTvClientEvent(event);
LOGD("send event for %p count TvClientObserver!\n", o);
}
}
return 0;
}
static int signalCallback(sd_bus_message *msg, void *userdata,
sd_bus_error *ret_error) {
const char *memb = sd_bus_message_get_member(msg);
if (strcmp(memb, TV_SERVICE_SIGNAL_SIGNAL_DETECTED) == 0) {
TvEvent::SignalDetectEvent e;
int r = sd_bus_message_read(msg, "iiiiiu", &e.mSourceInput, &e.mFmt,
&e.mTrans_fmt, &e.mStatus, &e.mDviFlag,
&e.mhdr_info);
if (r < 0)
return r;
SendEvent(e);
} else if (strcmp(memb, TV_SERVICE_SIGNAL_SOURCE_CONNECTED) == 0) {
TvEvent::SourceConnectEvent e;
int r = sd_bus_message_read(msg, "ii", &e.mSourceInput, &e.connectionState);
if (r < 0)
return r;
SendEvent(e);
} else if (strcmp(memb, TV_SERVICE_SIGNAL_DV_ALLM_CHANGED) == 0) {
TvEvent::SignalDvAllmEvent e;
int r = sd_bus_message_read(msg, "iii", &e.allm_mode, &e.it_content,
&e.cn_type);
if (r < 0)
return r;
SendEvent(e);
} else if (strcmp(memb, TV_SERVICE_SIGNAL_VRR_CHANGED) == 0) {
TvEvent::SignalVrrEvent e;
int r = sd_bus_message_read(msg, "i", &e.cur_vrr_status);
if (r < 0)
return r;
SendEvent(e);
} else if (strcmp(memb, TV_SERVICE_SIGNAL_QMS_CHANGED) == 0) {
TvEvent::QMSEvent e;
int r = sd_bus_message_read(msg, "iii", &e.qms_en, &e.qms_fps,
&e.qms_base_fps);
if (r < 0)
return r;
SendEvent(e);
} else if (strcmp(memb, TV_SERVICE_SIGNAL_PIP_SIGNAL_DETECTED) == 0) {
TvEvent::PipSignalDetectEvent e;
int r = sd_bus_message_read(msg, "iiiiiu", &e.mSourceInput, &e.mFmt,
&e.mTrans_fmt, &e.mStatus, &e.mDviFlag,
&e.mhdr_info);
if (r < 0)
return r;
SendEvent(e);
} else {
LOGE("invalid signal received!\n");
}
return 0;
}
static void bus_cleanup(sd_bus *bus, sd_event *event) {
if (event) {
sd_event_exit(event, 0);
sd_event_unref(event);
event = nullptr;
}
if (bus) {
sd_bus_unref(bus);
bus = nullptr;
}
}
using DeferCallbackHandler = std::function<void(sd_bus *, sd_event *)>;
struct defer_callback_data {
sd_bus *bus;
sd_event *event;
const DeferCallbackHandler *handler;
defer_callback_data(sd_bus *b, sd_event *e, const DeferCallbackHandler *h)
: bus(b), event(e), handler(h) {}
};
static int defer_callback(sd_event_source *, void *userdata) {
auto data = static_cast<defer_callback_data *>(userdata);
(*data->handler)(data->bus, data->event);
delete data;
return 0;
}
static void init_run_bus(DeferCallbackHandler callback) {
std::thread t([=]() {
sd_bus *bus = nullptr;
sd_event *event = nullptr;
int r = sd_bus_default_system(&bus);
if (r < 0) {
LOGE("Failed to open system bus: %s\n", strerror(-r));
return;
}
r = sd_event_default(&event);
if (r < 0) {
LOGE("Failed to create event: %s\n", strerror(-r));
sd_bus_unref(bus);
return;
}
r = sd_bus_attach_event(bus, event, 0);
if (r < 0) {
LOGE("Failed to attach event: %s\n", strerror(-r));
sd_event_unref(event);
sd_bus_unref(bus);
return;
}
if (callback) {
// Add a defer event
r = sd_event_add_defer(event, nullptr, defer_callback,
new defer_callback_data(bus, event, &callback));
if (r < 0) {
LOGE("Failed to add defer event: %s\n", strerror(-r));
sd_event_unref(event);
sd_bus_unref(bus);
return;
}
}
sd_event_loop(event);
bus_cleanup(bus, event);
});
t.detach();
}
using onCallPrepareHandler = std::function<bool(sd_bus_message *)>;
using onCallDoneHandler = std::function<int(sd_bus_message *)>;
struct MethodCallRequest {
const char *method;
onCallPrepareHandler *callPrepare;
onCallDoneHandler *onCallDone;
MethodCallRequest()
: method(nullptr), callPrepare(nullptr), onCallDone(nullptr) {}
MethodCallRequest(const char *m, onCallPrepareHandler *cp,
onCallDoneHandler *ocd)
: method(m), callPrepare(cp), onCallDone(ocd) {}
};
static int on_call_done(sd_bus_message *m, void *userdata,
sd_bus_error *ret_error) {
auto handler = static_cast<onCallDoneHandler *>(userdata);
const sd_bus_error *err = sd_bus_message_get_error(m);
if (err) {
LOGE("Failed to call: %s, %s(%s)\n", strerror(-sd_bus_error_get_errno(err)),
err->name, err->message);
return (*handler)(nullptr);
}
return (*handler)(m);
}
static int method_call_handler(sd_event_source *, int fd, uint32_t /*revents*/,
void *userdata) {
sd_bus *bus = (sd_bus *)userdata;
MethodCallRequest req;
int len = read(fd, &req, sizeof(req));
if (len != sizeof(req)) {
LOGE("%d read, %d bytes expected\n", len, sizeof(req));
} else {
if (req.method == nullptr)
return 0;
sd_bus_message *msg = nullptr;
if (sd_bus_message_new_method_call(
bus, &msg, TV_SERVICE_DBUS_SERVICE, TV_SERVICE_DBUS_OBJECT,
TV_SERVICE_DBUS_INTERFACE, req.method) < 0)
return 0;
if (req.callPrepare && !(*req.callPrepare)(msg)) {
sd_bus_message_unref(msg);
msg = nullptr;
return 0;
}
int r;
if ((r = sd_bus_call_async(bus, nullptr, msg, on_call_done, req.onCallDone,
0)) < 0) {
LOGE("Failed to async call: %s (%s)\n", req.method, strerror(-r));
(*req.onCallDone)(nullptr);
}
if (msg) {
sd_bus_message_unref(msg);
msg = nullptr;
}
}
return 0;
}
static sd_bus_message *
call_method(const char *member, std::function<bool(sd_bus_message *)> packer) {
std::promise<sd_bus_message *> b;
std::future<sd_bus_message *> f = b.get_future();
onCallPrepareHandler prepare(
[=](sd_bus_message *msg) -> bool { return packer(msg); });
onCallDoneHandler done([&b](sd_bus_message *m) -> int {
sd_bus_message_ref(m);
b.set_value(m);
return 0;
});
MethodCallRequest req(member, packer ? &prepare : nullptr, &done);
if (write(gs_method_call_pipe[1], &req, sizeof(req)) != sizeof(req)) {
LOGE("Failed to write to pipe: %s\n", strerror(errno));
return nullptr;
}
sd_bus_message *msg = f.get();
return msg;
}
#define _cleanup_(x) __attribute__((__cleanup__(x)))
#define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
int TvClient::StartTv(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("StartTv", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::StopTv(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("StopTv", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::SwitchSource(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SwitchSource", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
tv_source_input_t TvClient::GetCurrentSource() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSource", nullptr);
tv_source_input_t source;
int r = sd_bus_message_read(m, "i", &source);
if (r < 0) {
return SOURCE_INVALID;
}
return source;
}
int TvClient::SetVdinWorkMode(vdin_work_mode_t vdinWorkMode) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetVdinWorkMode", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", vdinWorkMode);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::SetEdidVersion(tv_source_input_t source, int edidVer) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetEdidVersion", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "ii", source, edidVer);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::GetEdidVersion(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetEdidVersion", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::SetEdidData(tv_source_input_t source, char *dataBuf) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetEdidData", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append_array(msg, 'y', dataBuf, 256);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::GetEdidData(tv_source_input_t source, char *dataBuf) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetEdidData", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
const void *ptr;
size_t size = 0;
int ret = 0;
int r = sd_bus_message_read(m, "i", &ret);
if (r < 0) {
return -1;
}
r = sd_bus_message_read_array(m, 'y', &ptr, &size);
if (r < 0) {
return -1;
}
memcpy(dataBuf, ptr, size > 256 ? 256 : size);
return ret;
}
int TvClient::GetHdmiSPDInfo(tv_source_input_t source, char *dataBuf,
size_t datalen) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiSPDInfo", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
const void *ptr;
size_t size = 0;
int ret = 0;
int r = sd_bus_message_read(m, "i", &ret);
if (r < 0) {
return -1;
}
r = sd_bus_message_read_array(m, 'y', &ptr, &size);
if (r < 0) {
return -1;
}
memcpy(dataBuf, ptr, size > datalen ? datalen : size);
return ret;
}
int TvClient::GetCurrentSourceFrameHeight() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceFrameHeight", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::GetCurrentSourceFrameWidth() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceFrameWidth", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::GetCurrentSourceFrameFps() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceFrameFps", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::GetCurrentSourceColorDepth() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceColorDepth", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
tvin_aspect_ratio_t TvClient::GetCurrentSourceAspectRatio() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceAspectRatio", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return (tvin_aspect_ratio_t)0;
}
return (tvin_aspect_ratio_t)result;
}
tvin_color_fmt_t TvClient::GetCurrentSourceColorFormat() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceColorFormat", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return (tvin_color_fmt_t)0;
}
return (tvin_color_fmt_t)result;
}
int TvClient::SetCurrentSourceColorRange(tvin_color_range_t range_mode) {
_cleanup_bus_message_unref_ sd_bus_message *m = call_method(
"SetCurrentSourceColorRange", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", range_mode);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
tvin_color_range_t TvClient::GetCurrentSourceColorRange() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceColorRange", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return (tvin_color_range_t)0;
}
return (tvin_color_range_t)result;
}
tvin_line_scan_mode_t TvClient::GetCurrentSourceLineScanMode() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceLineScanMode", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return (tvin_line_scan_mode_t)0;
}
return (tvin_line_scan_mode_t)result;
}
int TvClient::GetSourceConnectStatus(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetSourceConnectStatus", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::SetEdidBoostOn(int bBoostOn) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetEdidBoostOn", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", bBoostOn);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::GetCurrentSourceAllmInfo(tvin_latency_s *info) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentSourceAllmInfo", nullptr);
int r = sd_bus_message_read(m, "yyiy", &info->allm_mode, &info->it_content,
&info->cn_type, &info->fmm_flag);
if (r < 0) {
return -1;
}
return 0;
}
int TvClient::SetHdmiAllmEnabled(bool enable) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetHdmiAllmEnabled", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "b", enable);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
bool TvClient::GetHdmiAllmEnabled() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiAllmEnabled", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
bool TvClient::GetHdmiVrrSupport() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiVrrSupport", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
int TvClient::SetHdmiVrrEnabled(bool enable) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetHdmiVrrEnabled", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "b", enable);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
bool TvClient::GetHdmiVrrEnabled() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiVrrEnabled", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
vdin_vrr_mode_t TvClient::GetHdmiVrrMode() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiVrrMode", nullptr);
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return (vdin_vrr_mode_t)0;
}
return (vdin_vrr_mode_t)result;
}
bool TvClient::GetHdmiQmsSupport() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiQmsSupport", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
int TvClient::SetHdmiQmsEnabled(bool enable) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetHdmiQmsEnabled", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "b", enable);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
bool TvClient::GetHdmiQmsEnabled() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiQmsEnabled", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
int TvClient::GetCurrentStdInfo(struct tvin_std_s *info) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetCurrentStdInfo", nullptr);
int r = sd_bus_message_read(m, "iiyyy", &info->source, &info->edid_version,
&info->allm_enabled, &info->vrr_enabled, &info->qms_enabled);
if (r < 0) {
return -1;
}
return 0;
}
int TvClient::SetAudioDecoderId(int channel, int id) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetAudioDecoderId", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "ii", channel, id);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::SetAvAudioModeEnabled (bool enable) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetAvAudioModeEnabled", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "b", enable);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::StartTvInPIP(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("StartTvInPIP", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
int TvClient::StopTvInPIP(tv_source_input_t source) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("StopTvInPIP", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "i", source);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
bool TvClient::GetHdmiDlgSupport() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiDlgSupport", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
int TvClient::SetHdmiDlgEnabled(bool enable) {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("SetHdmiDlgEnabled", [&](sd_bus_message *msg) -> bool {
int r = sd_bus_message_append(msg, "b", enable);
if (r < 0) {
return false;
}
return true;
});
int result;
int r = sd_bus_message_read(m, "i", &result);
if (r < 0) {
return -1;
}
return result;
}
bool TvClient::GetHdmiDlgEnabled() {
_cleanup_bus_message_unref_ sd_bus_message *m =
call_method("GetHdmiDlgEnabled", nullptr);
int result;
int r = sd_bus_message_read(m, "b", &result);
if (r < 0) {
return false;
}
return result;
}
TvClient::TvClient() {
init_tv_logging();
if (gs_signal_bus) {
int r = sd_bus_match_signal(
gs_signal_bus, nullptr, TV_SERVICE_DBUS_SERVICE, TV_SERVICE_DBUS_OBJECT,
TV_SERVICE_DBUS_INTERFACE, nullptr, signalCallback, nullptr);
if (r < 0) {
LOGE("Failed to match signal: %s\n", strerror(-r));
}
} else {
init_run_bus([](sd_bus *bus, sd_event *) {
int r = sd_bus_match_signal(
bus, nullptr, TV_SERVICE_DBUS_SERVICE, TV_SERVICE_DBUS_OBJECT,
TV_SERVICE_DBUS_INTERFACE, nullptr, signalCallback, nullptr);
if (r < 0) {
LOGE("Failed to match signal: %s\n", strerror(-r));
}
});
}
std::promise<bool> b;
std::future<bool> f = b.get_future();
init_run_bus([&](sd_bus *bus, sd_event *event) {
if (pipe(gs_method_call_pipe) < 0) {
LOGE("pipe() failed: %s\n", strerror(errno));
return;
}
sd_event_add_io(event, nullptr, gs_method_call_pipe[0], POLLIN,
method_call_handler, bus);
try {
b.set_value(true);
} catch (const std::future_error &e) {
LOGE("%s\n", e.what());
}
});
f.get();
}
TvClient::~TvClient() {
LOGD("%s: TvClient has been destructed.\n", __FUNCTION__);
}
int TvClient::setTvClientObserver(TvClientIObserver *observer) {
if (observer != nullptr) {
mTvClientObserver.emplace_back(observer);
LOGD("%s: mTvClientObserver[%p] has been register.\n", __FUNCTION__,
observer);
} else {
LOGD("%s: observer is NULL.\n", __FUNCTION__);
}
return 0;
}
TvClient *TvClient::GetInstance() {
static std::shared_ptr<TvClient> inst_;
if (inst_.get() == nullptr) {
inst_ = std::shared_ptr<TvClient>(new TvClient(),
[](TvClient *ptr) { delete ptr; });
}
return inst_.get();
}
void TvClient::Release() {}