[TV][Channel] tune implementation
authorLukasz Foniok <l.foniok@samsung.com>
Wed, 17 Dec 2014 17:02:25 +0000 (18:02 +0100)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Mon, 2 Feb 2015 11:08:16 +0000 (20:08 +0900)
[Verification]
tizen.tvchannel.tune( {major:someChannleNo }, function(){} ) should work.

Change-Id: If845fe810847af11941fceb354584a7fdeca56b6
Signed-off-by: Lukasz Foniok <l.foniok@samsung.com>
src/tvchannel/tune_option.cc [new file with mode: 0644]
src/tvchannel/tune_option.h [new file with mode: 0644]
src/tvchannel/tvchannel.gyp
src/tvchannel/tvchannel_instance.cc
src/tvchannel/tvchannel_instance.h
src/tvchannel/tvchannel_manager.cc
src/tvchannel/tvchannel_manager.h

diff --git a/src/tvchannel/tune_option.cc b/src/tvchannel/tune_option.cc
new file mode 100644 (file)
index 0000000..0de5250
--- /dev/null
@@ -0,0 +1,171 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "tvchannel/tune_option.h"
+#include <stdint.h>
+#include <common/logger.h>
+
+namespace extension {
+namespace tvchannel {
+
+TuneOption::TuneOption() {
+    initialize();
+}
+
+void TuneOption::initialize() {
+    m_ptc = 0;
+    m_major = 0;
+    m_minor = 0;
+    m_sourceID = 0;
+    m_programNumber = 0;
+    m_transportStreamID = 0;
+    m_originalNetworkID = 0;
+    m_ptc_is_set = false;
+    m_major_is_set = false;
+    m_minor_is_set = false;
+    m_sourceID_is_set = false;
+    m_programNumber_is_set = false;
+    m_transportStreamID_is_set = false;
+    m_originalNetworkID_is_set = false;
+}
+
+TuneOption::~TuneOption() {
+}
+
+TuneOption::TuneOption(picojson::object const& _tuneDict) {
+    LOGD("Enter");
+    initialize();
+    picojson::object tuneDict = _tuneDict;
+    if (tuneDict.find("major") != tuneDict.end()) {
+        setMajor(static_cast<int64_t>(tuneDict["major"].get<double>()));
+    }
+    if (tuneDict.find("minor") != tuneDict.end()) {
+        setMinor(static_cast<int64_t>(tuneDict["minor"].get<double>()));
+    }
+    if (tuneDict.find("sourceID") != tuneDict.end()) {
+        setSourceID(static_cast<int64_t>(tuneDict["sourceID"].get<double>()));
+    }
+    if (tuneDict.find("programNumber") != tuneDict.end()) {
+        setProgramNumber(
+            static_cast<int64_t>(tuneDict["programNumber"].get<double>()));
+    }
+    if (tuneDict.find("transportStreamID") != tuneDict.end()) {
+        setTransportStreamID(
+            static_cast<int64_t>(tuneDict["transportStreamID"].get<double>()));
+    }
+    if (tuneDict.find("ptc") != tuneDict.end()) {
+        setPtc(static_cast<int64_t>(tuneDict["ptc"].get<double>()));
+    }
+    if (tuneDict.find("originalNetworkID") != tuneDict.end()) {
+        setOriginalNetworkID(
+            static_cast<int64_t>(tuneDict["originalNetworkID"].get<double>()));
+    }
+}
+
+int64_t TuneOption::getPtc() const {
+    return m_ptc;
+}
+
+bool TuneOption::isPtcSet() const {
+    return m_ptc_is_set;
+}
+
+void TuneOption::setPtc(int64_t ptc) {
+    m_ptc = ptc;
+    m_ptc_is_set = true;
+}
+
+int64_t TuneOption::getMajor() const {
+    return m_major;
+}
+
+bool TuneOption::isMajorSet() const {
+    return m_major_is_set;
+}
+
+void TuneOption::setMajor(int64_t major) {
+    m_major = major;
+    m_major_is_set = true;
+}
+
+int64_t TuneOption::getMinor() const {
+    return m_minor;
+}
+
+bool TuneOption::isMinorSet() const {
+    return m_minor_is_set;
+}
+
+void TuneOption::setMinor(int64_t minor) {
+    m_minor = minor;
+    m_minor_is_set = true;
+}
+
+int64_t TuneOption::getSourceID() const {
+    return m_sourceID;
+}
+
+bool TuneOption::isSourceIDSet() const {
+    return m_sourceID_is_set;
+}
+
+void TuneOption::setSourceID(int64_t sourceID) {
+    m_sourceID = sourceID;
+    m_sourceID_is_set = true;
+}
+
+int64_t TuneOption::getProgramNumber() const {
+    return m_programNumber;
+}
+
+bool TuneOption::isProgramNumberSet() const {
+    return m_programNumber_is_set;
+}
+
+void TuneOption::setProgramNumber(int64_t programNumber) {
+    m_programNumber = programNumber;
+    m_programNumber_is_set = true;
+}
+
+int64_t TuneOption::getTransportStreamID() const {
+    return m_transportStreamID;
+}
+
+bool TuneOption::isTransportStreamIDSet() const {
+    return m_transportStreamID_is_set;
+}
+
+void TuneOption::setTransportStreamID(int64_t transportStreamID) {
+    m_transportStreamID = transportStreamID;
+    m_transportStreamID_is_set = true;
+}
+
+int64_t TuneOption::getOriginalNetworkID() const {
+    return m_originalNetworkID;
+}
+
+bool TuneOption::isOriginalNetworkIDSet() const {
+    return m_originalNetworkID_is_set;
+}
+
+void TuneOption::setOriginalNetworkID(int64_t originalNetworkID) {
+    m_originalNetworkID = originalNetworkID;
+    m_originalNetworkID_is_set = true;
+}
+
+}  //  namespace tvchannel
+}  //  namespace extension
diff --git a/src/tvchannel/tune_option.h b/src/tvchannel/tune_option.h
new file mode 100644 (file)
index 0000000..6d2ea45
--- /dev/null
@@ -0,0 +1,86 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef SRC_TVCHANNEL_TUNE_OPTION_H_
+#define SRC_TVCHANNEL_TUNE_OPTION_H_
+
+#include <memory>
+#include "common/picojson.h"
+#include "tvchannel/types.h"
+
+namespace extension {
+namespace tvchannel {
+
+class TuneOption {
+ public:
+    TuneOption();
+    virtual ~TuneOption();
+
+    explicit TuneOption(picojson::object const& _tuneDict);
+
+    int64_t getPtc() const;
+    bool isPtcSet() const;
+    void setPtc(int64_t ptc);
+
+    int64_t getMajor() const;
+    bool isMajorSet() const;
+    void setMajor(int64_t major);
+
+    int64_t getMinor() const;
+    bool isMinorSet() const;
+    void setMinor(int64_t minor);
+
+    int64_t getSourceID() const;
+    bool isSourceIDSet() const;
+    void setSourceID(int64_t sourceID);
+
+    int64_t getProgramNumber() const;
+    bool isProgramNumberSet() const;
+    void setProgramNumber(int64_t programNumber);
+
+    int64_t getTransportStreamID() const;
+    bool isTransportStreamIDSet() const;
+    void setTransportStreamID(int64_t transportStreamID);
+
+    int64_t getOriginalNetworkID() const;
+    bool isOriginalNetworkIDSet() const;
+    void setOriginalNetworkID(int64_t originalNetworkID);
+
+ private:
+    int64_t m_ptc;
+    int64_t m_major;
+    int64_t m_minor;
+    int64_t m_sourceID;
+    int64_t m_programNumber;
+    int64_t m_transportStreamID;
+    int64_t m_originalNetworkID;
+    bool m_ptc_is_set;
+    bool m_major_is_set;
+    bool m_minor_is_set;
+    bool m_sourceID_is_set;
+    bool m_programNumber_is_set;
+    bool m_transportStreamID_is_set;
+    bool m_originalNetworkID_is_set;
+    void initialize();
+};
+
+typedef std::shared_ptr<TuneOption> TuneOptionPtr;
+
+}  //  namespace tvchannel
+}  //  namespace extension
+
+#endif  //  SRC_TVCHANNEL_TUNE_OPTION_H_
index f0c2f75..fe641bc 100644 (file)
@@ -41,7 +41,9 @@
         'tvchannel_manager.h',
         'tvchannel_manager.cc',
         'types.h',
-        'types.cc'
+        'types.cc',
+        'tune_option.h',
+        'tune_option.cc'
       ],
     },
   ],
index 9c06d2d..bff3953 100644 (file)
@@ -9,31 +9,89 @@
 #include "common/picojson.h"
 #include "tvchannel/channel_info.h"
 #include "tvchannel/program_info.h"
+#include "tvchannel/types.h"
+#include "common/task-queue.h"
 
 namespace extension {
 namespace tvchannel {
 
 TVChannelInstance::TVChannelInstance() {
-    LOGE("Entered");
+    LOGD("Entered");
     RegisterSyncHandler("TVChannelManager_getCurrentChannel",
         std::bind(&TVChannelInstance::getCurrentChannel, this,
-            std::placeholders::_1,
-            std::placeholders::_2));
+            std::placeholders::_1, std::placeholders::_2));
     RegisterSyncHandler("TVChannelManager_getCurrentProgram",
         std::bind(&TVChannelInstance::getCurrentProgram, this,
-            std::placeholders::_1,
+            std::placeholders::_1, std::placeholders::_2));
+    RegisterHandler("TVChannelManager_tune",
+        std::bind(&TVChannelInstance::tune, this, std::placeholders::_1,
             std::placeholders::_2));
-    TVChannelManager::getInstance()->registerListener(this);
+
+    m_pSubscriber = TVChannelManager::getInstance()->createSubscriber(this);
+    TVChannelManager::getInstance()->registerListener(m_pSubscriber);
 }
 
 TVChannelInstance::~TVChannelInstance() {
-    LOGE("Entered");
+    LOGD("Entered");
+}
+
+void TVChannelInstance::tune(picojson::value const& args,
+    picojson::object& out) {
+    LOGD("Enter");
+    picojson::object tuneOption =
+        args.get("tuneOption").get<picojson::object>();
+    double callbackId = args.get("callbackId").get<double>();
+    std::string windowType;
+    if (args.contains("windowType")) {
+        windowType = args.get("windowType").get<std::string>();
+    } else {
+        windowType = "MAIN";
+    }
+
+    LOGD("CallbackID %f", callbackId);
+    std::shared_ptr<TVChannelManager::TuneData> pTuneData(
+        new TVChannelManager::TuneData(TuneOption(tuneOption),
+            stringToWindowType(windowType), callbackId));
+
+    std::function<void(std::shared_ptr<
+        TVChannelManager::TuneData> const&)> task = std::bind(
+            &TVChannelInstance::tuneTask, this, std::placeholders::_1);
+    std::function<void(std::shared_ptr<
+            TVChannelManager::TuneData> const&)> taskAfter = std::bind(
+                &TVChannelInstance::tuneTaskAfter, this, std::placeholders::_1);
+
+    common::TaskQueue::GetInstance().Queue<TVChannelManager::TuneData>(task,
+        taskAfter, pTuneData);
+
+    picojson::value v;
+    ReportSuccess(v, out);
+}
+
+void TVChannelInstance::tuneTaskAfter(
+    std::shared_ptr<TVChannelManager::TuneData> const& _tuneData) {
+    LOGD("Enter");
+    if (_tuneData->pError) {
+        picojson::value event = picojson::value(picojson::object());
+        picojson::object& obj = event.get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", picojson::value(
+            _tuneData->callbackId)));
+        obj.insert(std::make_pair("error", _tuneData->pError->ToJSON()));
+        PostMessage(event.serialize().c_str());
+    }
+}
+
+void TVChannelInstance::tuneTask(
+    std::shared_ptr<TVChannelManager::TuneData> const& _tuneData) {
+    LOGD("Enter");
+    TVChannelManager::getInstance()->tune(_tuneData);
 }
 
 void TVChannelInstance::getCurrentChannel(picojson::value const& args,
     picojson::object& out) {
-    std::unique_ptr< ChannelInfo > pChannel = TVChannelManager::getInstance()->getCurrentChannel(
-        args.get("windowType").get<std::string>());
+
+    std::unique_ptr<ChannelInfo> pChannel =
+        TVChannelManager::getInstance()->getCurrentChannel(
+            stringToWindowType(args.get("windowType").get<std::string>()));
 
     picojson::value v = channelInfoToJson(pChannel);
     ReportSuccess(v, out);
@@ -79,15 +137,10 @@ picojson::value TVChannelInstance::channelInfoToJson(
     return picojson::value(channel);
 }
 
-
-void TVChannelInstance::getCurrentProgram(const picojson::value& args,
-    picojson::object& out) {
-    std::unique_ptr<ProgramInfo> pInfo(TVChannelManager::getInstance()
-        ->getCurrentProgram(args.get("windowType").get<std::string>()));
+picojson::value TVChannelInstance::programInfoToJson(
+    const std::unique_ptr<ProgramInfo>& pInfo) {
     picojson::value::object program;
-    program.insert(
-        std::make_pair("title",
-            picojson::value(pInfo->getTitle())));
+    program.insert(std::make_pair("title", picojson::value(pInfo->getTitle())));
     program.insert(
         std::make_pair("startTime",
             picojson::value(static_cast<double>(pInfo->getStartTimeMs()))));
@@ -98,25 +151,71 @@ void TVChannelInstance::getCurrentProgram(const picojson::value& args,
         std::make_pair("detailedDescription",
             picojson::value(pInfo->getDetailedDescription())));
     program.insert(
-        std::make_pair("language",
-            picojson::value(pInfo->getLanguage())));
+        std::make_pair("language", picojson::value(pInfo->getLanguage())));
     program.insert(
-        std::make_pair("rating",
-            picojson::value(pInfo->getRating())));
+        std::make_pair("rating", picojson::value(pInfo->getRating())));
 
     picojson::value result(program);
-    ReportSuccess(result, out);
+    return result;
+}
+
+void TVChannelInstance::getCurrentProgram(const picojson::value& args,
+    picojson::object& out) {
+    std::unique_ptr<ProgramInfo> pInfo(
+        TVChannelManager::getInstance()->getCurrentProgram(
+            stringToWindowType(args.get("windowType").get<std::string>())));
+    ReportSuccess(programInfoToJson(pInfo), out);
 }
 
-void TVChannelInstance::onChannelChange() {
+void TVChannelInstance::onChannelChange(double callbackId) {
     LOGD("Enter");
     try {
+        WindowType windowType = stringToWindowType("MAIN");
+
         picojson::value::object dict;
-        std::unique_ptr<ChannelInfo> pChannel = TVChannelManager::getInstance()
-            ->getCurrentChannel("MAIN");
+        std::unique_ptr<ChannelInfo> pChannel =
+            TVChannelManager::getInstance()->getCurrentChannel(windowType);
         dict["listenerId"] = picojson::value("ChannelChanged");
         dict["channel"] = channelInfoToJson(pChannel);
         dict["windowType"] = picojson::value("MAIN");
+        dict["success"] = picojson::value(true);
+        picojson::value resultListener(dict);
+        PostMessage(resultListener.serialize().c_str());
+        if (callbackId !=- 1) {
+            dict.erase("listenerId");
+            dict["callbackId"] = picojson::value(callbackId);
+            picojson::value resultCallback(dict);
+            PostMessage(resultCallback.serialize().c_str());
+        }
+    } catch (common::PlatformException& e) {
+        LOGW("Failed to post message: %s", e.message().c_str());
+    } catch (...) {
+        LOGW("Failed to post message, unknown error");
+    }
+}
+
+void TVChannelInstance::onEPGReceived(double callbackId) {
+    try {
+        picojson::value::object dict;
+        dict["listenerId"] = picojson::value("ProgramInfoReceived");
+        dict["windowType"] = picojson::value("MAIN");
+        std::unique_ptr<ProgramInfo> pInfo(
+            TVChannelManager::getInstance()->getCurrentProgram(MAIN));
+        dict["program"] = programInfoToJson(pInfo);
+        picojson::value result(dict);
+        PostMessage(result.serialize().c_str());
+    } catch (common::PlatformException& e) {
+        LOGW("Failed to post message: %s", e.message().c_str());
+    } catch (...) {
+        LOGW("Failed to post message, unknown error");
+    }
+}
+void TVChannelInstance::onNoSignal(double callbackId) {
+    try {
+        picojson::value::object dict;
+        dict["windowType"] = picojson::value("MAIN");
+        dict["callbackId"] = picojson::value(callbackId);
+        dict["nosignal"] = picojson::value(true);
         picojson::value result(dict);
         PostMessage(result.serialize().c_str());
     } catch (common::PlatformException& e) {
@@ -126,5 +225,5 @@ void TVChannelInstance::onChannelChange() {
     }
 }
 
-}  // namespace tvchannel
-}  // namespace extension
+}  //  namespace tvchannel
+}  //  namespace extension
index cd852ef..24fcecb 100644 (file)
@@ -10,8 +10,8 @@
 
 #include "common/extension.h"
 #include "common/picojson.h"
-#include "tvchannel/tvchannel_manager.h"
 #include "tvchannel/tvchannel_extension.h"
+#include "tvchannel/tvchannel_manager.h"
 
 namespace extension {
 namespace tvchannel {
@@ -26,9 +26,20 @@ class TVChannelInstance:
  private:
     void getCurrentChannel(const picojson::value& args, picojson::object& out);
     void getCurrentProgram(const picojson::value& args, picojson::object& out);
-    virtual void onChannelChange();
+    virtual void onChannelChange(double callbackId);
+    virtual void onEPGReceived(double callbackId);
+    virtual void onNoSignal(double callbackId);
     picojson::value channelInfoToJson(
         const std::unique_ptr<ChannelInfo> &pChannel);
+    picojson::value programInfoToJson(
+        const std::unique_ptr<ProgramInfo> &pProgram);
+    void tune(picojson::value const& args,
+        picojson::object& out);
+    void tuneTask(std::shared_ptr<TVChannelManager::TuneData> const& _tuneData);
+    void tuneTaskAfter(
+        std::shared_ptr<TVChannelManager::TuneData> const& _pTuneData);
+
+    ISignalSubscriber* m_pSubscriber;
 };
 
 }  // namespace tvchannel
index 57b15ed..14a2f2b 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "tvchannel/tvchannel_manager.h"
 #include <iconv.h>
+#include <stdint.h>
+#include <functional>
 #include "tvchannel/channel_info.h"
 #include "tvchannel/program_info.h"
 #include "common/logger.h"
 namespace extension {
 namespace tvchannel {
 
-using common::UnknownException;
-
 TVChannelManager* TVChannelManager::getInstance() {
     static TVChannelManager manager;
     return &manager;
 }
 
-std::unique_ptr<ChannelInfo> TVChannelManager::getCurrentChannel(
-        std::string const& _windowType) {
-    LOGE("Entered %s", _windowType.c_str());
+TVChannelManager::TVChannelManager() :
+    m_listener(NULL) {
+    LOGD("Enter");
+    int ret = TVServiceAPI::CreateService(&m_pService);
+    if (TV_SERVICE_API_SUCCESS != ret) {
+        LOGE("Failed to create tvs-api service: %d", ret);
+        throw common::UnknownException("Failed to create tvs-api service");
+    }
+}
 
-    TCServiceData serviceData;
-    TCCriteriaHelper criteria;
-    criteria.Fetch(SERVICE_ID);
-    criteria.Fetch(MAJOR);
-    criteria.Fetch(MINOR);
-    criteria.Fetch(PROGRAM_NUMBER);
-    criteria.Fetch(CHANNEL_NUMBER);
-    criteria.Fetch(CHANNEL_TYPE);
-    criteria.Fetch(SERVICE_NAME);
-    criteria.Fetch(SOURCE_ID);
-    criteria.Fetch(TRANSPORT_STREAM_ID);
-    criteria.Fetch(ORIGINAL_NETWORK_ID);
-    criteria.Fetch(LCN);
+IService* TVChannelManager::getService() {
+    return m_pService;
+}
 
-    //  Navigation
+void TVChannelManager::tune(std::shared_ptr<TuneData> const& _pTuneData) {
+    LOGD("Enter");
+    try {
+        std::unique_lock<std::mutex> lock(tuneMutex);
+
+        WindowType windowType = _pTuneData->windowType;
+        TuneOption tuneOption = _pTuneData->tuneOption;
+
+        TCServiceId currentServiceId =
+            getCurrentChannel(windowType)->getServiceID();
+
+        TSTvMode tvMode = getTvMode(
+            getNavigation(getProfile(windowType), SCREENID));
+
+        ENavigationMode naviMode = NAVIGATION_MODE_ALL;
+        std::unique_ptr < TCCriteriaHelper > pCriteria = getBasicCriteria(
+            tvMode, naviMode);
+        pCriteria->Fetch(SERVICE_ID);
+        pCriteria->Fetch(CHANNEL_TYPE);
+        pCriteria->Fetch(CHANNEL_NUMBER);
+
+        if (tuneOption.isMajorSet()) {
+            LOGD("MAJOR: %d", tuneOption.getMajor());
+            pCriteria->Where(MAJOR, static_cast<int>(tuneOption.getMajor()));
+        }
+        if (tuneOption.isMinorSet()) {
+            LOGD("MINOR: %d", tuneOption.getMinor());
+            pCriteria->Where(MINOR, static_cast<int>(tuneOption.getMinor()));
+        }
+        if (tuneOption.isPtcSet()) {
+            LOGD("PTC: %d", tuneOption.getPtc());
+            pCriteria->Where(CHANNEL_NUMBER,
+                static_cast<int>(tuneOption.getPtc()));
+        }
+        if (tuneOption.isOriginalNetworkIDSet()) {
+            LOGD("ORIGINAL_NETWORK_ID: %d", tuneOption.getOriginalNetworkID());
+            pCriteria->Where(ORIGINAL_NETWORK_ID,
+                static_cast<int>(tuneOption.getOriginalNetworkID()));
+        }
+        if (tuneOption.isProgramNumberSet()) {
+            LOGD("PROGRAM_NUMBER: %d", tuneOption.getProgramNumber());
+            pCriteria->Where(PROGRAM_NUMBER,
+                static_cast<int>(tuneOption.getProgramNumber()));
+        }
+        if (tuneOption.isSourceIDSet()) {
+            LOGD("SOURCE_ID: %d", tuneOption.getSourceID());
+            pCriteria->Where(SOURCE_ID,
+                static_cast<int>(tuneOption.getSourceID()));
+        }
+        if (tuneOption.isTransportStreamIDSet()) {
+            LOGD("TRANSPORT_STREAM_ID: %d", tuneOption.getTransportStreamID());
+            pCriteria->Where(TRANSPORT_STREAM_ID,
+                static_cast<int>(tuneOption.getTransportStreamID()));
+        }
+
+        TCServiceData foundService;
+        int ret = getService()->FindService(*pCriteria, foundService);
+        if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+            LOGE("Failed to find channel: %d", ret);
+            throw common::NotFoundException("Failed to find channel");
+        }
+
+        TCServiceId serviceId = foundService.Get < TCServiceId > (SERVICE_ID);
+        u_int16_t channelNumber = foundService.Get < u_int16_t
+            > (CHANNEL_NUMBER);
+        EChannelType channelType = foundService.Get < EChannelType
+            > (CHANNEL_TYPE);
+
+        ret = getNavigation(getProfile(windowType), 0)->SetService(serviceId);
+        if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+            LOGE("Failed to set selected channel: %d", ret);
+            throw new common::UnknownException(
+                "Failed to set selected channel");
+        }
+        _pTuneData->serviceId = serviceId;
+        m_callbackTuneMap[serviceId] = _pTuneData->callbackId;
+    } catch (common::PlatformException const& _error) {
+        _pTuneData->pError.reset(
+            new common::PlatformException(_error.name(), _error.message()));
+        LOGE("Some exception caught");
+    }
+}
+
+IServiceNavigation* TVChannelManager::getNavigation(EProfile profileId,
+    u_int16_t screenId) {
+    LOGD("Enter");
     IServiceNavigation* navigation;
-    int ret = TVServiceAPI::CreateServiceNavigation(
-            getProfile(stringToWindowType(_windowType)), 0, &navigation);
+    int ret = TVServiceAPI::CreateServiceNavigation(profileId, screenId,
+        &navigation);
     if (TV_SERVICE_API_SUCCESS != ret) {
-        LoggerE("Failed to create service navigation: %d", ret);
+        LOGE("Failed to create service navigation: %d", ret);
         throw common::UnknownException("Failed to create service navigation");
     }
+    return navigation;
+}
 
-    struct TSTvMode tvMode;
-    ret = navigation->GetTvMode(tvMode);
+TSTvMode TVChannelManager::getTvMode(IServiceNavigation* pNavigation) {
+    LOGD("Enter");
+    TSTvMode tvMode;
+    int ret = pNavigation->GetTvMode(tvMode);
     if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
-        LoggerE("Failed to get current tv mode: %d", ret);
+        LOGE("Failed to get current tv mode: %d", ret);
         throw common::UnknownException("Failed to get current tv mode");
     }
-    LOGE("tvMode : antenna - %d, service - %d", tvMode.antennaMode,
-            tvMode.serviceMode);
+    LOGD("tvMode : antenna - %d, service - %d", tvMode.antennaMode,
+        tvMode.serviceMode);
+    return tvMode;
+}
 
-    ret = navigation->GetCurrentServiceInfo(tvMode, criteria, serviceData);
+std::unique_ptr<TCCriteriaHelper> TVChannelManager::getBasicCriteria(
+    TSTvMode tvMode, ENavigationMode naviMode) {
+    LOGD("Enter");
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    bool found = TCNavigationModeHelper::GetNavigationCriteria(tvMode, naviMode,
+        *pCriteria);
+    if (!found) {
+        LOGE("Failed to create navigation criteria");
+        throw common::UnknownException("Failed to create navigation criteria");
+    }
+    return pCriteria;
+}
+
+TCServiceData TVChannelManager::getCurrentServiceInfo(
+    IServiceNavigation* _pNavigation, TSTvMode _mode,
+    std::unique_ptr<TCCriteriaHelper> const& _pCriteria) {
+    LOGD("Enter");
+    TCServiceData serviceData;
+    int ret = _pNavigation->GetCurrentServiceInfo(_mode, *_pCriteria,
+        serviceData);
     if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
         LOGE("Failed to get current service info: %d", ret);
         throw common::UnknownException("Failed to get current service info");
     }
-    LoggerE("Current channel id: %llu",
-            serviceData.Get < TCServiceId > (SERVICE_ID));
-    std::unique_ptr<ChannelInfo> pChannel( new ChannelInfo() );
+    return serviceData;
+}
+
+std::unique_ptr<ChannelInfo> TVChannelManager::getCurrentChannel(
+    WindowType _windowType) {
+    LOGD("Entered %d", _windowType);
+
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    pCriteria->Fetch(SERVICE_ID);
+    pCriteria->Fetch(MAJOR);
+    pCriteria->Fetch(MINOR);
+    pCriteria->Fetch(PROGRAM_NUMBER);
+    pCriteria->Fetch(CHANNEL_NUMBER);
+    pCriteria->Fetch(CHANNEL_TYPE);
+    pCriteria->Fetch(SERVICE_NAME);
+    pCriteria->Fetch(SOURCE_ID);
+    pCriteria->Fetch(TRANSPORT_STREAM_ID);
+    pCriteria->Fetch(ORIGINAL_NETWORK_ID);
+    pCriteria->Fetch(LCN);
+
+    //  Navigation
+    IServiceNavigation* navigation = getNavigation(getProfile(_windowType),
+        SCREENID);
+
+    TSTvMode tvMode = getTvMode(navigation);
+
+    TCServiceData serviceData = getCurrentServiceInfo(navigation, tvMode,
+        pCriteria);
+    LOGD("Current channel id: %llu",
+        serviceData.Get < TCServiceId > (SERVICE_ID));
+    std::unique_ptr<ChannelInfo> pChannel(new ChannelInfo());
     pChannel->fromApiData(serviceData);
     return pChannel;
 }
 
 EProfile TVChannelManager::getProfile(WindowType windowType) {
-    LOGE("Enter");
+    LOGD("Enter");
     switch (windowType) {
     case MAIN:
         return PROFILE_TYPE_MAIN;
@@ -80,43 +214,26 @@ EProfile TVChannelManager::getProfile(WindowType windowType) {
     }
 }
 
-TCServiceId TVChannelManager::getCurrentChannelId(
-    const std::string& _windowType) {
-    TCServiceData serviceData;
-    TCCriteriaHelper criteria;
-    criteria.Fetch(SERVICE_ID);
+TCServiceId TVChannelManager::getCurrentChannelId(WindowType _windowType) {
+    LOGD("Enter");
     //  Navigation
-    IServiceNavigation* navigation;
-    int ret = TVServiceAPI::CreateServiceNavigation(
-            getProfile(stringToWindowType(_windowType)), 0, &navigation);
-    if (TV_SERVICE_API_SUCCESS != ret) {
-        LOGE("Failed to create service navigation: %d", ret);
-        throw UnknownException("Failed to create service navigation");
-    }
-
-    struct TSTvMode tvMode;
-    ret = navigation->GetTvMode(tvMode);
-    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
-        LOGE("Failed to get current tv mode: %d", ret);
-        throw UnknownException("Failed to get current tv mode");
-    }
-
-    ret = navigation->GetCurrentServiceInfo(tvMode, criteria, serviceData);
-    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
-        LOGE("Failed to get current service info: %d", ret);
-        throw UnknownException("Failed to get current service info");
-    }
-    return serviceData.Get<TCServiceId>(SERVICE_ID);
+    IServiceNavigation* navigation = getNavigation(getProfile(_windowType),
+        SCREENID);
+    TSTvMode tvMode = getTvMode(navigation);
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    pCriteria->Fetch(SERVICE_ID);
+    TCServiceData serviceData = getCurrentServiceInfo(navigation, tvMode,
+        pCriteria);
+    return serviceData.Get < TCServiceId > (SERVICE_ID);
 }
 
-ProgramInfo* TVChannelManager::getCurrentProgram(
-    const std::string& _windowType) {
-
+ProgramInfo* TVChannelManager::getCurrentProgram(WindowType _windowType) {
+    LOGD("Enter");
     IServiceGuide* guide;
     int ret = TVServiceAPI::CreateServiceGuide(&guide);
     if (TV_SERVICE_API_SUCCESS != ret) {
         LOGE("Failed to create service guide: %d", ret);
-        throw UnknownException("Failed to create service guide");
+        throw common::UnknownException("Failed to create service guide");
     }
 
     TCProgramData programData;
@@ -124,47 +241,80 @@ ProgramInfo* TVChannelManager::getCurrentProgram(
         programData);
     if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
         LOGE("Failed to get current program: %d", ret);
-        throw UnknownException("Failed to get current program");
+        throw common::UnknownException("Failed to get current program");
     }
     ProgramInfo* program = new ProgramInfo();
     program->fromApiData(programData);
     return program;
 }
 
-void TVChannelManager::registerListener(EventListener* listener) {
+ISignalSubscriber* TVChannelManager::createSubscriber(
+    EventListener* pListener) {
     LOGD("Enter");
-    m_listener = listener;
-    ISignalSubscriber* subscriber;
-    int ret = TVServiceAPI::CreateSignalSubscriber(signalListener, &subscriber);
+    m_listener = pListener;
+    ISignalSubscriber* pSubscriber;
+    int ret = TVServiceAPI::CreateSignalSubscriber(signalListener,
+        &pSubscriber);
     if (TV_SERVICE_API_SUCCESS != ret) {
         LOGW("Failed to create tvs-api SignalSubscriber");
-        return;
     }
-    ret = subscriber->Subscribe(SIGNAL_TUNE_SUCCESS);
+    return pSubscriber;
+}
+
+void TVChannelManager::registerListener(ISignalSubscriber* pSubscriber) {
+    LOGD("Enter");
+    pSubscriber->Unsubscribe(SIGNAL_TUNE_SUCCESS);
+    int ret = pSubscriber->Subscribe(SIGNAL_TUNE_SUCCESS);
     if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
         LOGW("Failed to add listener: SIGNAL_TUNE_SUCCESS");
     }
+    pSubscriber->Unsubscribe(SIGNAL_TUNER_LOCK_FAIL);
+    ret = pSubscriber->Subscribe(SIGNAL_TUNER_LOCK_FAIL);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LOGW("Failed to add listener: SIGNAL_TUNER_LOCK_FAIL");
+    }
+    pSubscriber->Unsubscribe(SIGNAL_EPG_COMPLETED);
+    ret = pSubscriber->Subscribe(SIGNAL_EPG_COMPLETED);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LOGW("Failed to add listener: SIGNAL_EPG_COMPLETED");
+    }
 }
 
-int TVChannelManager::signalListener(ESignalType type,
-    TSSignalData data, void*) {
+int TVChannelManager::signalListener(ESignalType type, EProfile _profile,
+    u_int16_t _screenID, TSSignalData data, void*) {
     LOGD("Enter: %d", type);
     if (!getInstance()->m_listener) {
         LOGE("Listener is empty, ignoring message");
         return 0;
     }
+
+    TCServiceId pChannelId =
+        getInstance()->getCurrentChannelId(stringToWindowType("MAIN"));
+    double callbackID = -1;
+    auto it = getInstance()->m_callbackTuneMap.find(pChannelId);
+    if (it != getInstance()->m_callbackTuneMap.end()) {
+        callbackID = it->second;
+    }
+    LOGD("CallbackID %f", callbackID);
+
     switch (type) {
-        case SIGNAL_TUNE_SUCCESS:
-            getInstance()->m_listener->onChannelChange();
-            break;
-        default:
-            LOGW("Unrecognized event type");
+    case SIGNAL_TUNE_SUCCESS:
+        getInstance()->m_listener->onChannelChange(callbackID);
+        break;
+    case SIGNAL_TUNER_LOCK_FAIL:
+        getInstance()->m_listener->onNoSignal(callbackID);
+        break;
+    case SIGNAL_EPG_COMPLETED:
+        getInstance()->m_listener->onEPGReceived(callbackID);
+        break;
+    default:
+        LOGW("Unrecognized event type");
     }
     return 0;
 }
 
 void TVChannelManager::ucs2utf8(char *out, size_t out_len, char *in,
-        size_t in_len) {
+    size_t in_len) {
     iconv_t cd;
     size_t r;
 
index e179696..e7b2f40 100644 (file)
@@ -7,8 +7,17 @@
 
 #include <string>
 #include <memory>
+#include <mutex>
+#include <map>
 #include <TVServiceAPI.h>
+#include <ServiceNavigationDataType.h>
+#include <NavigationModeHelper.h>
 #include "tvchannel/types.h"
+#include "tvchannel/tune_option.h"
+
+namespace common {
+class PlatformException;
+}
 
 namespace extension {
 namespace tvchannel {
@@ -26,29 +35,64 @@ static const int TV_SERVICE_API_METHOD_FAILURE = -1;
 
 class EventListener {
  public:
-    virtual void onChannelChange() = 0;
+    virtual void onChannelChange(double callbackId) = 0;
+    virtual void onEPGReceived(double callbackId) = 0;
+    virtual void onNoSignal(double callbackId) = 0;
+    virtual ~EventListener() {
+    }
 };
 
 class TVChannelManager {
  public:
+    struct TuneData {
+        TuneData(TuneOption _tuneOption, WindowType _windowType,
+            double _callbackId) :
+            tuneOption(_tuneOption), windowType(_windowType),
+                callbackId(_callbackId) {
+        }
+        TuneOption tuneOption;
+        WindowType windowType;
+        double callbackId;
+        u_int64_t serviceId;
+        std::shared_ptr<common::PlatformException> pError;
+    };
+
     static TVChannelManager* getInstance();
-    std::unique_ptr<ChannelInfo> getCurrentChannel(std::string const& _windowType);
-    ProgramInfo* getCurrentProgram(std::string const& _windowType);
     static void ucs2utf8(char *out, size_t out_len, char *in, size_t in_len);
-    void registerListener(EventListener* listener);
+    void registerListener(ISignalSubscriber* pSubscriber);
+    ISignalSubscriber* createSubscriber(EventListener* pListener);
+    std::unique_ptr<ChannelInfo> getCurrentChannel(WindowType _windowType);
+    ProgramInfo* getCurrentProgram(WindowType _windowType);
+
+    void tune(std::shared_ptr<TuneData> const& _pTuneData);
+
+    EProfile getProfile(WindowType windowType);
+    IServiceNavigation* getNavigation(EProfile profileId, u_int16_t screenId);
+    TSTvMode getTvMode(IServiceNavigation* _pNavigation);
+    std::unique_ptr<TCCriteriaHelper> getBasicCriteria(TSTvMode tvMode,
+        ENavigationMode naviMode);
+    TCServiceData getCurrentServiceInfo(IServiceNavigation* _pNavigation,
+        TSTvMode _mode, std::unique_ptr<TCCriteriaHelper> const& _pCriteria);
+
+    IService* getService();
+
  private:
     EventListener* m_listener;
     //  Not copyable, assignable, movable
-    TVChannelManager():
-        m_listener(NULL) {
-    }
+    TVChannelManager();
     TVChannelManager(TVChannelManager const&) = delete;
     void operator=(TVChannelManager const&) = delete;
     TVChannelManager(TVChannelManager &&) = delete;
 
-    EProfile getProfile(WindowType windowType);
-    TCServiceId getCurrentChannelId(std::string const& _windowType);
-    static int signalListener(ESignalType type, TSSignalData data, void*);
+    TCServiceId getCurrentChannelId(WindowType _windowType);
+    static int signalListener(ESignalType type, EProfile _profile,
+        u_int16_t _screenID, TSSignalData data, void*);
+    IService* m_pService;
+
+    static const int SCREENID = 0;
+
+    std::mutex tuneMutex;
+    std::map<u_int64_t, double> m_callbackTuneMap;
 };
 
 }  // namespace tvchannel