375 lines
13 KiB
C++
375 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2014-2025 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.
|
|
*/
|
|
#define LOG_TAG "SubtitleServiceLinux"
|
|
|
|
#include "SubtitleServiceLinux.h"
|
|
|
|
#include <EventsTracker.h>
|
|
#include <IpcSocket.h>
|
|
#include <SubtitleSignalHandler.h>
|
|
#include <cutils/native_handle.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include "SubtitleLog.h"
|
|
#include "SubtitleServer.h"
|
|
#include "subtitlecmd.h"
|
|
|
|
#define SERVER_PORT 10200
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
SubtitleServiceLinux *mInstance = NULL;
|
|
SubtitleServiceLinux *SubtitleServiceLinux::GetInstance() {
|
|
SUBTITLE_LOGI("SubtitleServiceLinux");
|
|
if (mInstance == NULL) {
|
|
mInstance = new SubtitleServiceLinux();
|
|
}
|
|
|
|
return mInstance;
|
|
}
|
|
|
|
static pthread_once_t threadFlag = PTHREAD_ONCE_INIT;
|
|
SubtitleServiceLinux::SubtitleServiceLinux() {
|
|
mIpcSocket = std::make_shared<IpcSocket>(true);
|
|
mIpcSocket->start(SERVER_PORT, this, []() {
|
|
pthread_once(&threadFlag,
|
|
[] { SubtitleSignalHandler::instance().installSignalHandlers(); });
|
|
});
|
|
|
|
if (!mIpcSocket->isvalid()) {
|
|
SUBTITLE_LOGE("Server socket init failed");
|
|
mIpcSocket->stop();
|
|
return;
|
|
}
|
|
|
|
mIpcSocket->setEventListener(eventReceiver);
|
|
mpSubtitlecontrol = SubtitleServer::Instance();
|
|
}
|
|
|
|
/*static*/
|
|
int SubtitleServiceLinux::eventReceiver(int fd, void *selfData) {
|
|
auto subService = static_cast<SubtitleServiceLinux *>(selfData);
|
|
if (subService == nullptr) {
|
|
return EventsTracker::RET_REMOVE;
|
|
}
|
|
|
|
char recvBuf[1024] = {0};
|
|
int retLen = IpcSocket::receive(fd, recvBuf, sizeof(recvBuf));
|
|
|
|
if (retLen <= 0) {
|
|
if (retLen == 0) {
|
|
SUBTITLE_LOGE("Client broken, fd=%d, remove.", fd);
|
|
subService->onRemoteDead(0);
|
|
return EventsTracker::RET_REMOVE;
|
|
}
|
|
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
return EventsTracker::RET_CONTINUE;
|
|
}
|
|
|
|
SUBTITLE_LOGE("recv error (fd=%d): %m", fd);
|
|
return EventsTracker::RET_REMOVE;
|
|
}
|
|
|
|
SUBTITLE_LOGI("Receive: %s", recvBuf);
|
|
int ret = subService->ParserSubtitleCommand(recvBuf, nullptr);
|
|
|
|
std::string retStr = std::to_string(ret);
|
|
bool send = IpcSocket::send(fd, retStr.c_str(), retStr.size());
|
|
SUBTITLE_LOGI("Reply %s", (send ? "OK" : "NG"));
|
|
|
|
return EventsTracker::RET_CONTINUE;
|
|
}
|
|
|
|
SubtitleServiceLinux::~SubtitleServiceLinux() {
|
|
SUBTITLE_LOGI("SubtitleServiceLinux");
|
|
if (mpSubtitlecontrol != NULL) {
|
|
delete mpSubtitlecontrol;
|
|
mpSubtitlecontrol = NULL;
|
|
}
|
|
}
|
|
|
|
int SubtitleServiceLinux::SplitCommand(const char *commandData) {
|
|
char cmdbuff[1024];
|
|
char *token;
|
|
int cmd_size = 0;
|
|
const char *delimitation = ".";
|
|
strcpy(cmdbuff, commandData);
|
|
|
|
/* get first str*/
|
|
token = strtok(cmdbuff, delimitation);
|
|
|
|
/* continue get str*/
|
|
while (token != NULL) {
|
|
mSubtitleCommand[cmd_size].assign(token);
|
|
|
|
// SUBTITLE_LOGE("%s mSubtitleCommand[%d]:%s\n", token, cmd_size,
|
|
// mSubtitleCommand[cmd_size].c_str());
|
|
cmd_size++;
|
|
token = strtok(NULL, delimitation);
|
|
}
|
|
// SUBTITLE_LOGI("cmd_size = %d\n", cmd_size);
|
|
|
|
return cmd_size;
|
|
}
|
|
|
|
int SubtitleServiceLinux::SetTeleCmd(subtitle_module_param_t param) {
|
|
int ret = 0;
|
|
int moduleId = param.moduleId;
|
|
if ((moduleId >= SUBTITLE_MODULE_CMD_START) && (moduleId <= SUBTITLE_CMD_MAX)) {
|
|
int paramData[32] = {0};
|
|
int i = 0;
|
|
for (i = 0; i < param.paramLength; i++) {
|
|
paramData[i] = param.paramBuf[i];
|
|
}
|
|
switch (moduleId) {
|
|
case SUBTITLE_TTCONTROL:
|
|
mpSubtitlecontrol->ttControl(paramData[0], paramData[1], paramData[2], paramData[3],
|
|
paramData[4], paramData[5]);
|
|
break;
|
|
case SUBTITLE_TTGOHOME:
|
|
mpSubtitlecontrol->ttGoHome(paramData[0]);
|
|
break;
|
|
case SUBTITLE_TTNEXTPAGE:
|
|
mpSubtitlecontrol->ttNextPage(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_TTNEXTSUBPAGE:
|
|
mpSubtitlecontrol->ttNextSubPage(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_TTGOTOPAGE:
|
|
mpSubtitlecontrol->ttGotoPage(paramData[0], paramData[1], paramData[2]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
SUBTITLE_LOGE("invalid Subtitle cmd: %d\n", moduleId);
|
|
ret = -1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int SubtitleServiceLinux::SetCmd(subtitle_module_param_t param, native_handle_t *handle) {
|
|
int ret = 0;
|
|
int moduleId = param.moduleId;
|
|
SUBTITLE_LOGD("moduleId = %d", moduleId);
|
|
if ((moduleId >= SUBTITLE_MODULE_CMD_START) && (moduleId <= SUBTITLE_CMD_MAX)) {
|
|
int paramData[32] = {0};
|
|
int i = 0;
|
|
for (i = 0; i < param.paramLength; i++) {
|
|
paramData[i] = param.paramBuf[i];
|
|
}
|
|
SUBTITLE_LOGD("moduleId = %d, paramData[0]=%d, paramData[1]=%d", moduleId, paramData[0],
|
|
paramData[1]);
|
|
switch (moduleId) {
|
|
case SUBTITLE_OPENCONNECTION:
|
|
ret = mpSubtitlecontrol->openConnection();
|
|
break;
|
|
case SUBTITLE_CLOSECONNECTION:
|
|
ret = mpSubtitlecontrol->closeConnection(paramData[0]);
|
|
break;
|
|
case SUBTITLE_OPEN:
|
|
updateSubtitleLogLevel();
|
|
ret = mpSubtitlecontrol->open(paramData[0], paramData[1], (OpenType)paramData[2],
|
|
handle);
|
|
break;
|
|
case SUBTITLE_CLOSE:
|
|
SUBTITLE_LOGI("SUBTITLE_CLOSE");
|
|
ret = mpSubtitlecontrol->close(paramData[0]);
|
|
break;
|
|
case SUBTITLE_RESETFORSEEK:
|
|
SUBTITLE_LOGI("SUBTITLE_RESETFORSEEK");
|
|
break;
|
|
case SUBTITLE_UPDATEVIDEOPTS:
|
|
static int logCnt = 0;
|
|
if (++logCnt % 100 == 0) {
|
|
SUBTITLE_LOGI("SUBTITLE_UPDATEVIDEOPTS");
|
|
}
|
|
ret = mpSubtitlecontrol->updateVideoPos(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_SETPAGEID:
|
|
SUBTITLE_LOGI("SUBTITLE_SETPAGEID");
|
|
ret = mpSubtitlecontrol->setPageId(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_SETANCPAGEID:
|
|
SUBTITLE_LOGI("SUBTITLE_SETANCPAGEID");
|
|
ret = mpSubtitlecontrol->setAncPageId(paramData[0], paramData[1]);
|
|
break;
|
|
case SBUTITLE_SETCHANNELID:
|
|
SUBTITLE_LOGI("SBUTITLE_SETCHANNELID");
|
|
ret = mpSubtitlecontrol->setChannelId(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_SETCLOSECAPTIONVFMT:
|
|
SUBTITLE_LOGI("SUBTITLE_SETCLOSECAPTIONVFMT");
|
|
break;
|
|
case SUBTITLE_USERDATAOPEN:
|
|
SUBTITLE_LOGI("SUBTITLE_USERDATAOPEN");
|
|
ret = mpSubtitlecontrol->userDataOpen(paramData[0]);
|
|
break;
|
|
case SUBTITLE_USERDATACLOSE:
|
|
SUBTITLE_LOGI("SUBTITLE_USERDATACLOSE");
|
|
ret = mpSubtitlecontrol->userDataClose(paramData[0]);
|
|
break;
|
|
case SUBTITLE_SETSUBTYPE:
|
|
ret = mpSubtitlecontrol->setSubType(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_REGISTER_DATA_CB:
|
|
ret = mpSubtitlecontrol->registerOnDataCB(paramData[0]);
|
|
break;
|
|
case SUBTITLE_SETPIPID:
|
|
ret = mpSubtitlecontrol->setPipId(paramData[0], paramData[1], paramData[2]);
|
|
break;
|
|
case SUBTITLE_GETSUBPID:
|
|
ret = mpSubtitlecontrol->setSubPid(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_GETSUBTITLESTATUS:
|
|
ret =
|
|
mpSubtitlecontrol->getSubtitleStatus(paramData[0], paramData[1], paramData[2]);
|
|
break;
|
|
case SUBTITLE_SETSECURELEVEL:
|
|
ret = mpSubtitlecontrol->setSecureLevel(paramData[0], paramData[1]);
|
|
break;
|
|
case SUBTITLE_UISHOW:
|
|
ret = mpSubtitlecontrol->show(paramData[0]);
|
|
break;
|
|
case SUBTITLE_UIHIDE:
|
|
ret = mpSubtitlecontrol->hide(paramData[0]);
|
|
break;
|
|
case SUBTITLE_SET_DVB_COUNTRYCODE:
|
|
ret = mpSubtitlecontrol->setDvbCountryCode(paramData[0], paramData[1]);
|
|
break;
|
|
default:
|
|
SUBTITLE_LOGE("Can not be recognized moduleId: %d", moduleId);
|
|
break;
|
|
}
|
|
} else {
|
|
SUBTITLE_LOGE("invalid Subtitle cmd: %d\n", moduleId);
|
|
ret = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void SubtitleServiceLinux::join() {
|
|
if (mIpcSocket != nullptr) {
|
|
mIpcSocket->join();
|
|
}
|
|
}
|
|
|
|
int SubtitleServiceLinux::GetCmd(subtitle_module_param_t param) {
|
|
int ret = 0;
|
|
int moduleId = param.moduleId;
|
|
|
|
if ((moduleId >= SUBTITLE_MODULE_CMD_START) && (moduleId <= SUBTITLE_CMD_MAX)) {
|
|
switch (moduleId) {
|
|
case SUBTITLE_GETTYPE:
|
|
// ret = mpSubtitlecontrol->GetHue();
|
|
break;
|
|
case SUBTITLE_GETTOTALTRACKS:
|
|
// ret = mpSubtitlecontrol->GetGrayPattern();
|
|
break;
|
|
case SUBTITLE_GETLANGUAGE:
|
|
break;
|
|
case SUBTITLE_GETSUBTYPE:
|
|
break;
|
|
case SUBTITLE_GETSUBPID:
|
|
break;
|
|
case SUBTITLE_GETANCPAGE:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
SUBTITLE_LOGE("invalid SUBTITLE cmd: %d!\n", moduleId);
|
|
ret = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void SubtitleServiceLinux::onRemoteDead(int sessionId) {
|
|
if (mpSubtitlecontrol && !mpSubtitlecontrol->isClosed(sessionId)) {
|
|
if (mpSubtitlecontrol->close(sessionId) == Result::OK &&
|
|
mpSubtitlecontrol->closeConnection(sessionId) == Result::OK) {
|
|
SUBTITLE_LOGI("onRemoteDead, self close OK for id %d", sessionId);
|
|
} else {
|
|
SUBTITLE_LOGI("onRemoteDead, self close failed for id %d", sessionId);
|
|
}
|
|
} else {
|
|
SUBTITLE_LOGI("onRemoteDead, already closed for id %d", sessionId);
|
|
}
|
|
}
|
|
|
|
int SubtitleServiceLinux::ParserSubtitleCommand(const char *commandData, native_handle_t *handle) {
|
|
SUBTITLE_LOGI("cmd data is %s\n", commandData);
|
|
|
|
int cmd_size = 0;
|
|
int ret = 0;
|
|
int i = 0;
|
|
// split command
|
|
cmd_size = SplitCommand(commandData);
|
|
// parse command
|
|
subtitle_module_param_t subtitleParam;
|
|
memset(&subtitleParam, 0, sizeof(subtitle_module_param_t));
|
|
subtitleParam.moduleId = atoi(mSubtitleCommand[2].c_str());
|
|
subtitleParam.paramLength = cmd_size - 3;
|
|
for (i = 0; i < subtitleParam.paramLength; i++) {
|
|
subtitleParam.paramBuf[i] = atoi(mSubtitleCommand[i + 3].c_str());
|
|
}
|
|
SUBTITLE_LOGD("cmd command0 is %s, command1 is %s\n", mSubtitleCommand[0].c_str(),
|
|
mSubtitleCommand[1].c_str());
|
|
if (strcmp(mSubtitleCommand[0].c_str(), "subtitle") == 0) {
|
|
if ((strcmp(mSubtitleCommand[1].c_str(), "ctrl") == 0) ||
|
|
(strcmp(mSubtitleCommand[1].c_str(), "set") == 0) ||
|
|
(strcmp(mSubtitleCommand[1].c_str(), "afdcontrol") == 0)) {
|
|
ret = SetCmd(subtitleParam, handle);
|
|
} else if (strcmp(mSubtitleCommand[1].c_str(), "get") == 0) {
|
|
ret = GetCmd(subtitleParam);
|
|
} else if (strcmp(mSubtitleCommand[1].c_str(), "ttcontrol") == 0) {
|
|
ret = SetTeleCmd(subtitleParam);
|
|
} else if (strcmp(mSubtitleCommand[1].c_str(), "getSubtitleStatus") == 0) {
|
|
ret = SetCmd(subtitleParam, handle);
|
|
} else if (strcmp(mSubtitleCommand[1].c_str(), "afdctrl") == 0) {
|
|
ret = GetCmd(subtitleParam);
|
|
} else {
|
|
SUBTITLE_LOGI("invalid cmd\n");
|
|
ret = 0;
|
|
}
|
|
} else {
|
|
SUBTITLE_LOGI("invalie cmdType\n");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|