1 #pragma once
2 /*
3  * This file is part of the libCEC(R) library.
4  *
5  * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited.  All rights reserved.
6  * libCEC(R) is an original work, containing original code.
7  *
8  * libCEC(R) is a trademark of Pulse-Eight Limited.
9  *
10  * This program is dual-licensed; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301  USA
24  *
25  *
26  * Alternatively, you can license this library under a commercial license,
27  * please contact Pulse-Eight Licensing for more information.
28  *
29  * For more information contact:
30  * Pulse-Eight Licensing       <license@pulse-eight.com>
31  *     http://www.pulse-eight.com/
32  *     http://www.pulse-eight.net/
33  */
34 
35 #include "env.h"
36 #include "p8-platform/threads/mutex.h"
37 #include <set>
38 #include <map>
39 #include <string>
40 #include <memory>
41 
42 namespace CEC
43 {
44   class CCECClient;
45   class CCECProcessor;
46   class CCECCommandHandler;
47   class CCECAudioSystem;
48   class CCECPlaybackDevice;
49   class CCECRecordingDevice;
50   class CCECTuner;
51   class CCECTV;
52   typedef std::shared_ptr<CCECClient> CECClientPtr;
53 
54   class CResponse
55   {
56   public:
57     CResponse(cec_opcode opcode);
58     ~CResponse(void);
59 
60     bool Wait(uint32_t iTimeout);
61     void Broadcast(void);
62 
63   private:
64     cec_opcode         m_opcode;
65     P8PLATFORM::CEvent m_event;
66   };
67 
68   class CWaitForResponse
69   {
70   public:
71     CWaitForResponse(void);
72     ~CWaitForResponse(void);
73 
74     void Clear();
75     bool Wait(cec_opcode opcode, uint32_t iTimeout = CEC_DEFAULT_TRANSMIT_WAIT);
76     void Received(cec_opcode opcode);
77 
78   private:
79     CResponse *GetEvent(cec_opcode opcode);
80 
81     P8PLATFORM::CMutex               m_mutex;
82     std::map<cec_opcode, CResponse*> m_waitingFor;
83   };
84 
85   class CCECBusDevice
86   {
87     friend class CCECProcessor;
88 
89   public:
90     CCECBusDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = CEC_INVALID_PHYSICAL_ADDRESS);
91     virtual ~CCECBusDevice(void);
92 
93     virtual bool                  ReplaceHandler(bool bActivateSource = true);
94 
95     // TODO use something smarter than this
96     /*!
97      * @brief Get the command handler for this device. Call MarkHandlerReady() when done with it.
98      * @return The current handler.
99      */
100     virtual CCECCommandHandler *  GetHandler(void);
101 
102     /*!
103      * @brief To be called after GetHandler(), when no longer using it.
104      */
MarkHandlerReady(void)105     virtual void                  MarkHandlerReady(void) { MarkReady(); }
106 
GetProcessor(void)107     virtual CCECProcessor *       GetProcessor(void) const      { return m_processor; }
GetLastActive(void)108     virtual uint64_t              GetLastActive(void) const     { return m_iLastActive; }
GetType(void)109     virtual cec_device_type       GetType(void) const           { return m_type; }
GetLogicalAddress(void)110     virtual cec_logical_address   GetLogicalAddress(void) const { return m_iLogicalAddress; }
111     virtual const char*           GetLogicalAddressName(void) const;
112     virtual bool                  IsPresent(void);
113     virtual bool                  IsHandledByLibCEC(void);
114     virtual bool                  IsActive(bool suppressPoll = true);
115 
116     virtual bool                  HandleCommand(const cec_command &command);
117     virtual bool                  IsUnsupportedFeature(cec_opcode opcode);
118     virtual void                  SetUnsupportedFeature(cec_opcode opcode);
119 
120     virtual bool                  TransmitKeypress(const cec_logical_address initiator, cec_user_control_code key, bool bWait = true);
121     virtual bool                  TransmitKeyRelease(const cec_logical_address initiator, bool bWait = true);
122 
123     virtual cec_version           GetCecVersion(const cec_logical_address initiator, bool bUpdate = false);
124     virtual void                  SetCecVersion(const cec_version newVersion);
125     virtual bool                  RequestCecVersion(const cec_logical_address initiator, bool bWaitForResponse = true);
126     virtual bool                  TransmitCECVersion(const cec_logical_address destination, bool bIsReply);
127 
128     virtual std::string           GetMenuLanguage(const cec_logical_address initiator, bool bUpdate = false);
129     virtual void                  SetMenuLanguage(const std::string& strLanguage);
130     virtual void                  SetMenuLanguage(const cec_menu_language &menuLanguage);
131     virtual bool                  RequestMenuLanguage(const cec_logical_address initiator, bool bWaitForResponse = true);
132     virtual bool                  TransmitSetMenuLanguage(const cec_logical_address destination, bool bIsReply);
133 
134     virtual bool                  TransmitOSDString(const cec_logical_address destination, cec_display_control duration, const char *strMessage, bool bIsReply);
135 
136     virtual std::string           GetCurrentOSDName(void);
137     virtual std::string           GetOSDName(const cec_logical_address initiator, bool bUpdate = false);
138     virtual void                  SetOSDName(const std::string& strName);
139     virtual bool                  RequestOSDName(const cec_logical_address source, bool bWaitForResponse = true);
140     virtual bool                  TransmitOSDName(const cec_logical_address destination, bool bIsReply);
141 
142     virtual uint16_t              GetCurrentPhysicalAddress(void);
143     virtual bool                  HasValidPhysicalAddress(void);
144     virtual uint16_t              GetPhysicalAddress(const cec_logical_address initiator, bool bSuppressUpdate = false);
145     virtual bool                  SetPhysicalAddress(uint16_t iNewAddress);
146     virtual bool                  RequestPhysicalAddress(const cec_logical_address initiator, bool bWaitForResponse = true);
147     virtual bool                  TransmitPhysicalAddress(bool bIsReply);
148 
149     virtual cec_power_status      GetCurrentPowerStatus(void);
150     virtual cec_power_status      GetPowerStatus(const cec_logical_address initiator, bool bUpdate = false);
151     virtual void                  SetPowerStatus(const cec_power_status powerStatus);
152     virtual void                  OnImageViewOnSent(bool bSentByLibCEC);
153     virtual bool                  ImageViewOnSent(void);
154     virtual bool                  RequestPowerStatus(const cec_logical_address initiator, bool bUpdate, bool bWaitForResponse = true);
155     virtual bool                  TransmitPowerState(const cec_logical_address destination, bool bIsReply);
156 
157     virtual cec_vendor_id         GetCurrentVendorId(void);
158     virtual cec_vendor_id         GetVendorId(const cec_logical_address initiator, bool bUpdate = false);
159     virtual const char *          GetVendorName(const cec_logical_address initiator, bool bUpdate = false);
160     virtual bool                  SetVendorId(uint64_t iVendorId);
161     virtual bool                  RequestVendorId(const cec_logical_address initiator, bool bWaitForResponse = true);
162     virtual bool                  TransmitVendorID(const cec_logical_address destination, bool bSendAbort, bool bIsReply);
163 
GetCurrentStatus(void)164     virtual cec_bus_device_status GetCurrentStatus(void) { return GetStatus(false, true); }
165     virtual cec_bus_device_status GetStatus(bool bForcePoll = false, bool bSuppressPoll = false);
166     virtual void                  SetDeviceStatus(const cec_bus_device_status newStatus, cec_version libCECSpecVersion = CEC_VERSION_1_4);
167     virtual void                  ResetDeviceStatus(bool bClientUnregistered = false);
168     virtual bool                  TransmitPoll(const cec_logical_address destination, bool bUpdateDeviceStatus);
169     virtual void                  HandlePoll(const cec_logical_address destination);
170     virtual void                  HandlePollFrom(const cec_logical_address initiator);
171     virtual bool                  HandleReceiveFailed(void);
172 
173     virtual cec_menu_state        GetMenuState(const cec_logical_address initiator);
174     virtual void                  SetMenuState(const cec_menu_state state);
175     virtual bool                  TransmitMenuState(const cec_logical_address destination, bool bIsReply);
176 
177     virtual bool                  ActivateSource(uint64_t iDelay = 0);
IsActiveSource(void)178     virtual bool                  IsActiveSource(void) const    { return m_bActiveSource; }
179     virtual bool                  RequestActiveSource(bool bWaitForResponse = true);
180     virtual void                  MarkAsActiveSource(void);
181     virtual void                  MarkAsInactiveSource(bool bClientUnregistered = false);
182     virtual bool                  TransmitActiveSource(bool bIsReply);
183     virtual bool                  TransmitImageViewOn(void);
184     virtual bool                  TransmitInactiveSource(void);
185     virtual bool                  TransmitPendingActiveSourceCommands(void);
186     virtual void                  SetActiveRoute(uint16_t iRoute);
187     virtual void                  SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress = CEC_INVALID_PHYSICAL_ADDRESS);
188 
189     virtual bool                  PowerOn(const cec_logical_address initiator);
190     virtual bool                  Standby(const cec_logical_address initiator);
191 
192     virtual bool                  SystemAudioModeRequest(void);
193     virtual bool                  TransmitVolumeUp(const cec_logical_address source, bool bSendRelease = true);
194     virtual bool                  TransmitVolumeDown(const cec_logical_address source, bool bSendRelease = true);
195     virtual bool                  TransmitMuteAudio(const cec_logical_address source);
196 
197     virtual bool                  TryLogicalAddress(cec_version libCECSpecVersion = CEC_VERSION_1_4);
198 
199     CECClientPtr                  GetClient(void);
200     void                          SignalOpcode(cec_opcode opcode);
201     bool                          WaitForOpcode(cec_opcode opcode);
202 
203     void                          SetActiveSourceSent(bool setto = true);
204     bool                          ActiveSourceSent(void) const;
205 
206            CCECAudioSystem *      AsAudioSystem(void);
207     static CCECAudioSystem *      AsAudioSystem(CCECBusDevice *device);
208            CCECPlaybackDevice *   AsPlaybackDevice(void);
209     static CCECPlaybackDevice *   AsPlaybackDevice(CCECBusDevice *device);
210            CCECRecordingDevice *  AsRecordingDevice(void);
211     static CCECRecordingDevice *  AsRecordingDevice(CCECBusDevice *device);
212            CCECTuner *            AsTuner(void);
213     static CCECTuner *            AsTuner(CCECBusDevice *device);
214            CCECTV *               AsTV(void);
215     static CCECTV *               AsTV(CCECBusDevice *device);
216 
217   protected:
218     void CheckVendorIdRequested(const cec_logical_address source);
219     void MarkBusy(void);
220     void MarkReady(void);
221 
222     bool NeedsPoll(void);
223 
224     cec_device_type       m_type;
225     std::string           m_strDeviceName;
226     uint16_t              m_iPhysicalAddress;
227     uint16_t              m_iStreamPath;
228     cec_logical_address   m_iLogicalAddress;
229     cec_power_status      m_powerStatus;
230     std::string           m_menuLanguage;
231     CCECProcessor      *  m_processor;
232     CCECCommandHandler *  m_handler;
233     cec_vendor_id         m_vendor;
234     bool                  m_bReplaceHandler;
235     cec_menu_state        m_menuState;
236     bool                  m_bActiveSource;
237     int64_t               m_iLastActive;
238     int64_t               m_iLastPowerStateUpdate;
239     cec_version           m_cecVersion;
240     cec_bus_device_status m_deviceStatus;
241     std::set<cec_opcode>  m_unsupportedFeatures;
242     P8PLATFORM::CMutex    m_mutex;
243     P8PLATFORM::CMutex    m_handlerMutex;
244     P8PLATFORM::CEvent    m_replacing;
245     unsigned              m_iHandlerUseCount;
246     bool                  m_bAwaitingReceiveFailed;
247     bool                  m_bVendorIdRequested;
248     CWaitForResponse     *m_waitForResponse;
249     bool                  m_bImageViewOnSent;
250     bool                  m_bActiveSourceSent;
251   };
252 };
253