2 * This file is part of the libCEC(R) library.
4 * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
9 * This program is dual-licensed; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
36 #include <msclr/marshal.h>
40 using namespace System
;
41 using namespace System::Runtime::InteropServices
;
43 using namespace msclr::interop
;
45 public enum class CecDeviceType
55 public enum class CecLogLevel
66 public enum class CecLogicalAddress
68 Unknown
= -1, //not a valid logical address
88 public enum class CecPowerStatus
92 InTransitionStandbyToOn
= 0x02,
93 InTransitionOnToStandby
= 0x03,
97 public enum class CecVersion
107 public enum class CecDisplayControl
109 DisplayForDefaultTime
= 0x00,
110 DisplayUntilCleared
= 0x40,
111 ClearPreviousMessage
= 0x80,
112 ReservedForFutureUse
= 0xC0
115 public enum class CecMenuState
121 public enum class CecDeckControlMode
124 SkipReverseRewind
= 2,
129 public enum class CecDeckInfo
141 SkipForwardWind
= 0x1B,
142 SkipReverseRewind
= 0x1C,
143 IndexSearchForward
= 0x1D,
144 IndexSearchReverse
= 0x1E,
148 public enum class CecUserControlCode
180 PreviousChannel
= 0x32,
183 DisplayInformation
= 0x35,
204 VideoOnDemand
= 0x52,
205 ElectronicProgramGuide
= 0x53,
206 TimerProgramming
= 0x54,
207 InitialConfiguration
= 0x55,
209 PausePlayFunction
= 0x61,
210 RecordFunction
= 0x62,
211 PauseRecordFunction
= 0x63,
214 RestoreVolumeFunction
= 0x66,
216 SelectMediaFunction
= 0x68,
217 SelectAVInputFunction
= 0x69,
218 SelectAudioInputFunction
= 0x6A,
219 PowerToggleFunction
= 0x6B,
220 PowerOffFunction
= 0x6C,
221 PowerOnFunction
= 0x6D,
232 public enum class CecVendorId
244 public enum class CecAudioStatus
246 MuteStatusMask
= 0x80,
247 VolumeStatusMask
= 0x7F,
250 VolumeStatusUnknown
= 0x7F
253 public enum class CecOpcode
258 InactiveSource
= 0x9D,
259 RequestActiveSource
= 0x85,
260 RoutingChange
= 0x80,
261 RoutingInformation
= 0x81,
262 SetStreamPath
= 0x86,
267 RecordTvScreen
= 0x0F,
268 ClearAnalogueTimer
= 0x33,
269 ClearDigitalTimer
= 0x99,
270 ClearExternalTimer
= 0xA1,
271 SetAnalogueTimer
= 0x34,
272 SetDigitalTimer
= 0x97,
273 SetExternalTimer
= 0xA2,
274 SetTimerProgramTitle
= 0x67,
275 TimerClearedStatus
= 0x43,
278 GetCecVersion
= 0x9F,
279 GivePhysicalAddress
= 0x83,
280 GetMenuLanguage
= 0x91,
281 ReportPhysicalAddress
= 0x84,
282 SetMenuLanguage
= 0x32,
285 GiveDeckStatus
= 0x1A,
287 GiveTunerDeviceStatus
= 0x08,
288 SelectAnalogueService
= 0x92,
289 SelectDigtalService
= 0x93,
290 TunerDeviceStatus
= 0x07,
291 TunerStepDecrement
= 0x06,
292 TunerStepIncrement
= 0x05,
293 DeviceVendorId
= 0x87,
294 GiveDeviceVendorId
= 0x8C,
295 VendorCommand
= 0x89,
296 VendorCommandWithId
= 0xA0,
297 VendorRemoteButtonDown
= 0x8A,
298 VendorRemoteButtonUp
= 0x8B,
304 UserControlPressed
= 0x44,
305 UserControlRelease
= 0x45,
306 GiveDevicePowerStatus
= 0x8F,
307 ReportPowerStatus
= 0x90,
310 GiveAudioStatus
= 0x71,
311 GiveSystemAudioMode
= 0x7D,
312 ReportAudioStatus
= 0x7A,
313 SetSystemAudioMode
= 0x72,
314 SystemAudioModeRequest
= 0x70,
315 SystemAudioModeStatus
= 0x7E,
317 /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
321 public enum class CecSystemAudioStatus
327 public ref
class CecAdapter
330 CecAdapter(String
^ strPath
, String
^ strComPort
)
333 ComPort
= strComPort
;
336 property String
^ Path
;
337 property String
^ ComPort
;
340 public ref
class CecDeviceTypeList
343 CecDeviceTypeList(void)
345 Types
= gcnew array
<CecDeviceType
>(5);
346 for (unsigned int iPtr
= 0; iPtr
< 5; iPtr
++)
347 Types
[iPtr
] = CecDeviceType::Reserved
;
350 property array
<CecDeviceType
> ^ Types
;
353 public ref
class CecLogicalAddresses
356 CecLogicalAddresses(void)
358 Addresses
= gcnew array
<CecLogicalAddress
>(16);
359 for (unsigned int iPtr
= 0; iPtr
< 16; iPtr
++)
360 Addresses
[iPtr
] = CecLogicalAddress::Unregistered
;
363 bool IsSet(CecLogicalAddress iAddress
)
365 return Addresses
[(unsigned int)iAddress
] != CecLogicalAddress::Unregistered
;
368 property array
<CecLogicalAddress
> ^ Addresses
;
371 public ref
class CecDatapacket
376 Data
= gcnew array
<uint8_t>(100);
380 void PushBack(uint8_t data
)
389 property array
<uint8_t> ^ Data
;
390 property
uint8_t Size
;
393 public ref
class CecCommand
396 CecCommand(CecLogicalAddress iInitiator
, CecLogicalAddress iDestination
, bool bAck
, bool bEom
, CecOpcode iOpcode
, int32_t iTransmitTimeout
)
398 Initiator
= iInitiator
;
399 Destination
= iDestination
;
404 TransmitTimeout
= iTransmitTimeout
;
405 Parameters
= gcnew CecDatapacket
;
411 Initiator
= CecLogicalAddress::Unknown
;
412 Destination
= CecLogicalAddress::Unknown
;
415 Opcode
= CecOpcode::None
;
418 Parameters
= gcnew CecDatapacket
;
422 void PushBack(uint8_t data
)
424 if (Initiator
== CecLogicalAddress::Unknown
&& Destination
== CecLogicalAddress::Unknown
)
426 Initiator
= (CecLogicalAddress
) (data
>> 4);
427 Destination
= (CecLogicalAddress
) (data
& 0xF);
432 Opcode
= (CecOpcode
)data
;
436 Parameters
->PushBack(data
);
441 property CecLogicalAddress Initiator
;
442 property CecLogicalAddress Destination
;
445 property CecOpcode Opcode
;
446 property CecDatapacket
^ Parameters
;
447 property
bool OpcodeSet
;
448 property
int32_t TransmitTimeout
;
451 public ref
class CecKeypress
454 CecKeypress(int iKeycode
, unsigned int iDuration
)
457 Duration
= iDuration
;
469 property
int Keycode
;
470 property
unsigned int Duration
;
473 public ref
class CecLogMessage
476 CecLogMessage(String
^ strMessage
, CecLogLevel iLevel
, int64_t iTime
)
478 Message
= strMessage
;
487 Level
= CecLogLevel::None
;
493 property String
^ Message
;
494 property CecLogLevel Level
;
495 property
int64_t Time
;
498 public ref
class CecCallbackMethods
501 virtual int ReceiveLogMessage(CecLogMessage
^ message
)
506 virtual int ReceiveKeypress(CecKeypress
^ key
)
511 virtual int ReceiveCommand(CecCommand
^ command
)
518 // unmanaged callback methods
519 typedef int (__stdcall
*LOGCB
) (const cec_log_message
&message
);
520 typedef int (__stdcall
*KEYCB
) (const cec_keypress
&key
);
521 typedef int (__stdcall
*COMMANDCB
)(const cec_command
&command
);
523 static LOGCB g_logCB
;
524 static KEYCB g_keyCB
;
525 static COMMANDCB g_commandCB
;
526 static ICECCallbacks g_cecCallbacks
;
528 int CecLogMessageCB(const cec_log_message
&message
)
531 return g_logCB(message
);
535 int CecKeyPressCB(const cec_keypress
&key
)
542 int CecCommandCB(const cec_command
&command
)
545 return g_commandCB(command
);
550 // delegates for the unmanaged callback methods
551 public delegate
int CecLogMessageManagedDelegate(const cec_log_message
&);
552 public delegate
int CecKeyPressManagedDelegate(const cec_keypress
&);
553 public delegate
int CecCommandManagedDelegate(const cec_command
&);
555 public ref
class LibCecSharp
558 LibCecSharp(String
^ strDeviceName
, CecDeviceTypeList
^ deviceTypes
)
560 marshal_context
^ context
= gcnew
marshal_context();
561 m_bHasCallbacks
= false;
562 const char* strDeviceNameC
= context
->marshal_as
<const char*>(strDeviceName
);
564 cec_device_type_list types
;
565 for (unsigned int iPtr
= 0; iPtr
< 5; iPtr
++)
566 types
.types
[iPtr
] = (cec_device_type
)deviceTypes
->Types
[iPtr
];
567 m_libCec
= (ICECAdapter
*) CECInit(strDeviceNameC
, types
);
569 // create the delegate method for the log message callback
570 m_logMessageDelegate
= gcnew
CecLogMessageManagedDelegate(this, &LibCecSharp::CecLogMessageManaged
);
571 m_logMessageGCHandle
= GCHandle::Alloc(m_logMessageDelegate
);
572 g_logCB
= static_cast<LOGCB
>(Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate
).ToPointer());
573 g_cecCallbacks
.CBCecLogMessage
= CecLogMessageCB
;
575 // create the delegate method for the keypress callback
576 m_keypressDelegate
= gcnew
CecKeyPressManagedDelegate(this, &LibCecSharp::CecKeyPressManaged
);
577 m_keypressGCHandle
= GCHandle::Alloc(m_keypressDelegate
);
578 g_keyCB
= static_cast<KEYCB
>(Marshal::GetFunctionPointerForDelegate(m_keypressDelegate
).ToPointer());
579 g_cecCallbacks
.CBCecKeyPress
= CecKeyPressCB
;
581 // create the delegate method for the command callback
582 m_commandDelegate
= gcnew
CecCommandManagedDelegate(this, &LibCecSharp::CecCommandManaged
);
583 m_commandGCHandle
= GCHandle::Alloc(m_commandDelegate
);
584 g_commandCB
= static_cast<COMMANDCB
>(Marshal::GetFunctionPointerForDelegate(m_commandDelegate
).ToPointer());
585 g_cecCallbacks
.CBCecCommand
= CecCommandCB
;
592 CECDestroy(m_libCec
);
600 CECDestroy(m_libCec
);
606 array
<CecAdapter
^> ^ FindAdapters(String
^ path
)
608 cec_adapter
*devices
= new cec_adapter
[10];
610 marshal_context
^ context
= gcnew
marshal_context();
611 const char* strPathC
= path
->Length
> 0 ? context
->marshal_as
<const char*>(path
) : NULL
;
613 uint8_t iDevicesFound
= m_libCec
->FindAdapters(devices
, 10, NULL
);
615 array
<CecAdapter
^> ^ adapters
= gcnew array
<CecAdapter
^>(iDevicesFound
);
616 for (unsigned int iPtr
= 0; iPtr
< iDevicesFound
; iPtr
++)
617 adapters
[iPtr
] = gcnew
CecAdapter(gcnew
String(devices
[iPtr
].path
), gcnew
String(devices
[iPtr
].comm
));
624 bool Open(String
^ strPort
, int iTimeoutMs
)
626 marshal_context
^ context
= gcnew
marshal_context();
627 const char* strPortC
= context
->marshal_as
<const char*>(strPort
);
628 bool bReturn
= m_libCec
->Open(strPortC
, iTimeoutMs
);
638 bool EnableCallbacks(CecCallbackMethods
^ callbacks
)
640 if (m_libCec
&& !m_bHasCallbacks
)
642 m_bHasCallbacks
= true;
643 m_callbacks
= callbacks
;
644 return m_libCec
->EnableCallbacks(&g_cecCallbacks
);
650 bool PingAdapter(void)
652 return m_libCec
->PingAdapter();
655 bool StartBootloader(void)
657 return m_libCec
->StartBootloader();
660 int GetMinLibVersion(void)
662 return m_libCec
->GetMinLibVersion();
665 int GetLibVersionMajor(void)
667 return m_libCec
->GetLibVersionMajor();
670 int GetLibVersionMinor(void)
672 return m_libCec
->GetLibVersionMinor();
675 CecLogMessage
^ GetNextLogMessage(void)
678 if (m_libCec
->GetNextLogMessage(&msg
))
680 return gcnew
CecLogMessage(gcnew
String(msg
.message
), (CecLogLevel
)msg
.level
, msg
.time
);
683 return gcnew
CecLogMessage();
686 CecKeypress
^ GetNextKeypress(void)
689 if (m_libCec
->GetNextKeypress(&key
))
691 return gcnew
CecKeypress(key
.keycode
, key
.duration
);
694 return gcnew
CecKeypress();
697 CecCommand
^ GetNextCommand(void)
700 if (m_libCec
->GetNextCommand(&command
))
702 CecCommand
^ retVal
= gcnew
CecCommand((CecLogicalAddress
)command
.initiator
, (CecLogicalAddress
)command
.destination
, command
.ack
== 1 ? true : false, command
.eom
== 1 ? true : false, (CecOpcode
)command
.opcode
, command
.transmit_timeout
);
703 for (uint8_t iPtr
= 0; iPtr
< command
.parameters
.size
; iPtr
++)
704 retVal
->Parameters
->PushBack(command
.parameters
[iPtr
]);
708 return gcnew
CecCommand();
711 bool Transmit(CecCommand
^ command
)
713 cec_command ccommand
;
714 cec_command::Format(ccommand
, (cec_logical_address
)command
->Initiator
, (cec_logical_address
)command
->Destination
, (cec_opcode
)command
->Opcode
);
715 ccommand
.transmit_timeout
= command
->TransmitTimeout
;
716 ccommand
.eom
= command
->Eom
;
717 ccommand
.ack
= command
->Ack
;
718 for (unsigned int iPtr
= 0; iPtr
< command
->Parameters
->Size
; iPtr
++)
719 ccommand
.parameters
.PushBack(command
->Parameters
->Data
[iPtr
]);
721 return m_libCec
->Transmit(ccommand
);
724 bool SetLogicalAddress(CecLogicalAddress logicalAddress
)
726 return m_libCec
->SetLogicalAddress((cec_logical_address
) logicalAddress
);
729 bool SetPhysicalAddress(int16_t physicalAddress
)
731 return m_libCec
->SetPhysicalAddress(physicalAddress
);
734 bool PowerOnDevices(CecLogicalAddress logicalAddress
)
736 return m_libCec
->PowerOnDevices((cec_logical_address
) logicalAddress
);
739 bool StandbyDevices(CecLogicalAddress logicalAddress
)
741 return m_libCec
->StandbyDevices((cec_logical_address
) logicalAddress
);
744 bool PollDevice(CecLogicalAddress logicalAddress
)
746 return m_libCec
->PollDevice((cec_logical_address
) logicalAddress
);
749 bool SetActiveSource(CecDeviceType type
)
751 return m_libCec
->SetActiveSource((cec_device_type
) type
);
754 bool SetDeckControlMode(CecDeckControlMode mode
, bool sendUpdate
)
756 return m_libCec
->SetDeckControlMode((cec_deck_control_mode
) mode
, sendUpdate
);
759 bool SetDeckInfo(CecDeckInfo info
, bool sendUpdate
)
761 return m_libCec
->SetDeckInfo((cec_deck_info
) info
, sendUpdate
);
764 bool SetInactiveView(void)
766 return m_libCec
->SetInactiveView();
769 bool SetMenuState(CecMenuState state
, bool sendUpdate
)
771 return m_libCec
->SetMenuState((cec_menu_state
) state
, sendUpdate
);
774 bool SetOSDString(CecLogicalAddress logicalAddress
, CecDisplayControl duration
, String
^ message
)
776 marshal_context
^ context
= gcnew
marshal_context();
777 const char* strMessageC
= context
->marshal_as
<const char*>(message
);
779 bool bReturn
= m_libCec
->SetOSDString((cec_logical_address
) logicalAddress
, (cec_display_control
) duration
, strMessageC
);
785 bool SwitchMonitoring(bool enable
)
787 return m_libCec
->SwitchMonitoring(enable
);
790 CecVersion
GetDeviceCecVersion(CecLogicalAddress logicalAddress
)
792 return (CecVersion
) m_libCec
->GetDeviceCecVersion((cec_logical_address
) logicalAddress
);
795 String
^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress
)
797 cec_menu_language lang
;
798 if (m_libCec
->GetDeviceMenuLanguage((cec_logical_address
) logicalAddress
, &lang
))
800 return gcnew
String(lang
.language
);
803 return gcnew
String("");
806 CecVendorId
GetDeviceVendorId(CecLogicalAddress logicalAddress
)
808 return (CecVendorId
)m_libCec
->GetDeviceVendorId((cec_logical_address
) logicalAddress
);
811 CecPowerStatus
GetDevicePowerStatus(CecLogicalAddress logicalAddress
)
813 return (CecPowerStatus
) m_libCec
->GetDevicePowerStatus((cec_logical_address
) logicalAddress
);
816 CecLogicalAddresses
^ GetActiveDevices(void)
818 CecLogicalAddresses
^ retVal
= gcnew
CecLogicalAddresses();
819 unsigned int iDevices
= 0;
821 cec_logical_addresses activeDevices
= m_libCec
->GetActiveDevices();
823 for (uint8_t iPtr
= 0; iPtr
< 16; iPtr
++)
824 if (activeDevices
[iPtr
])
825 retVal
->Addresses
[iDevices
++] = (CecLogicalAddress
)iPtr
;
830 bool IsActiveDevice(CecLogicalAddress logicalAddress
)
832 return m_libCec
->IsActiveDevice((cec_logical_address
)logicalAddress
);
835 bool IsActiveDeviceType(CecDeviceType type
)
837 return m_libCec
->IsActiveDeviceType((cec_device_type
)type
);
840 bool SetHDMIPort(CecLogicalAddress address
, uint8_t port
)
842 return m_libCec
->SetHDMIPort((cec_logical_address
)address
, port
);
845 uint8_t VolumeUp(bool wait
)
847 return m_libCec
->VolumeUp(wait
);
850 uint8_t VolumeDown(bool wait
)
852 return m_libCec
->VolumeDown(wait
);
855 uint8_t MuteAudio(bool wait
)
857 return m_libCec
->MuteAudio(wait
);
860 bool SendKeypress(CecLogicalAddress destination
, CecUserControlCode key
, bool wait
)
862 return m_libCec
->SendKeypress((cec_logical_address
)destination
, (cec_user_control_code
)key
, wait
);
865 bool SendKeyRelease(CecLogicalAddress destination
, bool wait
)
867 return m_libCec
->SendKeyRelease((cec_logical_address
)destination
, wait
);
870 String
^ GetDeviceOSDName(CecLogicalAddress logicalAddress
)
872 cec_osd_name osd
= m_libCec
->GetDeviceOSDName((cec_logical_address
) logicalAddress
);
873 return gcnew
String(osd
.name
);
876 CecLogicalAddress
GetActiveSource()
878 return (CecLogicalAddress
)m_libCec
->GetActiveSource();
881 bool IsActiveSource(CecLogicalAddress logicalAddress
)
883 return m_libCec
->IsActiveSource((cec_logical_address
)logicalAddress
);
886 uint16_t GetDevicePhysicalAddress(CecLogicalAddress iAddress
)
888 return m_libCec
->GetDevicePhysicalAddress((cec_logical_address
)iAddress
);
891 String
^ ToString(CecLogicalAddress iAddress
)
893 const char *retVal
= m_libCec
->ToString((cec_logical_address
)iAddress
);
894 return gcnew
String(retVal
);
897 String
^ ToString(CecVendorId iVendorId
)
899 const char *retVal
= m_libCec
->ToString((cec_vendor_id
)iVendorId
);
900 return gcnew
String(retVal
);
903 String
^ ToString(CecVersion iVersion
)
905 const char *retVal
= m_libCec
->ToString((cec_version
)iVersion
);
906 return gcnew
String(retVal
);
909 String
^ ToString(CecPowerStatus iState
)
911 const char *retVal
= m_libCec
->ToString((cec_power_status
)iState
);
912 return gcnew
String(retVal
);
915 String
^ ToString(CecMenuState iState
)
917 const char *retVal
= m_libCec
->ToString((cec_menu_state
)iState
);
918 return gcnew
String(retVal
);
921 String
^ ToString(CecDeckControlMode iMode
)
923 const char *retVal
= m_libCec
->ToString((cec_deck_control_mode
)iMode
);
924 return gcnew
String(retVal
);
927 String
^ ToString(CecDeckInfo status
)
929 const char *retVal
= m_libCec
->ToString((cec_deck_info
)status
);
930 return gcnew
String(retVal
);
933 String
^ ToString(CecOpcode opcode
)
935 const char *retVal
= m_libCec
->ToString((cec_opcode
)opcode
);
936 return gcnew
String(retVal
);
939 String
^ ToString(CecSystemAudioStatus mode
)
941 const char *retVal
= m_libCec
->ToString((cec_system_audio_status
)mode
);
942 return gcnew
String(retVal
);
945 String
^ ToString(CecAudioStatus status
)
947 const char *retVal
= m_libCec
->ToString((cec_audio_status
)status
);
948 return gcnew
String(retVal
);
952 void DestroyDelegates()
954 m_logMessageGCHandle
.Free();
955 m_keypressGCHandle
.Free();
956 m_commandGCHandle
.Free();
959 // managed callback methods
960 int CecLogMessageManaged(const cec_log_message
&message
)
964 iReturn
= m_callbacks
->ReceiveLogMessage(gcnew
CecLogMessage(gcnew
String(message
.message
), (CecLogLevel
)message
.level
, message
.time
));
968 int CecKeyPressManaged(const cec_keypress
&key
)
972 iReturn
= m_callbacks
->ReceiveKeypress(gcnew
CecKeypress(key
.keycode
, key
.duration
));
976 int CecCommandManaged(const cec_command
&command
)
981 CecCommand
^ newCommand
= gcnew
CecCommand((CecLogicalAddress
)command
.initiator
, (CecLogicalAddress
)command
.destination
, command
.ack
== 1 ? true : false, command
.eom
== 1 ? true : false, (CecOpcode
)command
.opcode
, command
.transmit_timeout
);
982 for (uint8_t iPtr
= 0; iPtr
< command
.parameters
.size
; iPtr
++)
983 newCommand
->Parameters
->PushBack(command
.parameters
[iPtr
]);
984 iReturn
= m_callbacks
->ReceiveCommand(newCommand
);
989 ICECAdapter
* m_libCec
;
990 CecCallbackMethods
^ m_callbacks
;
991 bool m_bHasCallbacks
;
993 CecLogMessageManagedDelegate
^ m_logMessageDelegate
;
994 static GCHandle m_logMessageGCHandle
;
995 LOGCB m_logMessageCallback
;
997 CecKeyPressManagedDelegate
^ m_keypressDelegate
;
998 static GCHandle m_keypressGCHandle
;
999 KEYCB m_keypressCallback
;
1001 CecCommandManagedDelegate
^ m_commandDelegate
;
1002 static GCHandle m_commandGCHandle
;
1003 COMMANDCB m_commandCallback
;