void ATEMclient::_parseGetCommands(const char *cmdStr) { uint8_t mE; uint16_t videoSource; long temp; uint8_t readBytesForTlSr; if (!strcmp_P(cmdStr, PSTR("AMLv"))) { _readToPacketBuffer(36); } else if (!strcmp_P(cmdStr, PSTR("TlSr"))) { readBytesForTlSr = ((ATEM_packetBufferLength-2)/3)*3+2; _readToPacketBuffer(readBytesForTlSr); } else { _readToPacketBuffer(); // Default } if(!strcmp_P(cmdStr, PSTR("PrgI"))) { mE = _packetBuffer[0]; if (mE<=1) { #if ATEM_debug temp = atemProgramInputVideoSource[mE]; #endif atemProgramInputVideoSource[mE] = word(_packetBuffer[2], _packetBuffer[3]); #if ATEM_debug if ((_serialOutput==0x80 && atemProgramInputVideoSource[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemProgramInputVideoSource[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemProgramInputVideoSource[mE]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("PrvI"))) { mE = _packetBuffer[0]; if (mE<=1) { #if ATEM_debug temp = atemPreviewInputVideoSource[mE]; #endif atemPreviewInputVideoSource[mE] = word(_packetBuffer[2], _packetBuffer[3]); #if ATEM_debug if ((_serialOutput==0x80 && atemPreviewInputVideoSource[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemPreviewInputVideoSource[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemPreviewInputVideoSource[mE]); } #endif } } }
void ATEMmin::_parseGetCommands(const char *cmdStr) { uint8_t mE,keyer,aUXChannel; uint16_t sources; long temp; uint8_t readBytesForTlSr; _readToPacketBuffer(_cmdLength); if (!strcmp_P(cmdStr, PSTR("_pin"))) { if (_packetBuffer[5]=='T') { _ATEMmodel = 0; } else if (_packetBuffer[5]=='1') { _ATEMmodel = _packetBuffer[29]=='4' ? 4 : 1; } else if (_packetBuffer[5]=='2') { _ATEMmodel = _packetBuffer[29]=='4' ? 5 : 2; } else if (_packetBuffer[5]=='P') { _ATEMmodel = 3; } #if ATEM_debug if (_serialOutput>0) { Serial.print(F("Switcher type: ")); Serial.print(_ATEMmodel); switch(_ATEMmodel) { case 0: Serial.println(F(" - TeleVision Studio")); break; case 1: Serial.println(F(" - ATEM 1 M/E")); break; case 2: Serial.println(F(" - ATEM 2 M/E")); break; case 3: Serial.println(F(" - ATEM Production Studio 4K")); break; case 4: Serial.println(F(" - ATEM 1 M/E 4K")); break; case 5: Serial.println(F(" - ATEM 2 M/E 4K")); break; } } #endif } if(!strcmp_P(cmdStr, PSTR("PrgI"))) { mE = _packetBuffer[0]; if (mE<=1) { #if ATEM_debug temp = atemProgramInputVideoSource[mE]; #endif atemProgramInputVideoSource[mE] = word(_packetBuffer[2], _packetBuffer[3]); #if ATEM_debug if ((_serialOutput==0x80 && atemProgramInputVideoSource[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemProgramInputVideoSource[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemProgramInputVideoSource[mE]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("PrvI"))) { mE = _packetBuffer[0]; if (mE<=1) { #if ATEM_debug temp = atemPreviewInputVideoSource[mE]; #endif atemPreviewInputVideoSource[mE] = word(_packetBuffer[2], _packetBuffer[3]); #if ATEM_debug if ((_serialOutput==0x80 && atemPreviewInputVideoSource[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemPreviewInputVideoSource[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemPreviewInputVideoSource[mE]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("TrPs"))) { mE = _packetBuffer[0]; if (mE<=1) { #if ATEM_debug temp = atemTransitionInTransition[mE]; #endif atemTransitionInTransition[mE] = _packetBuffer[1]; #if ATEM_debug if ((_serialOutput==0x80 && atemTransitionInTransition[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemTransitionInTransition[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemTransitionInTransition[mE]); } #endif #if ATEM_debug temp = atemTransitionFramesRemaining[mE]; #endif atemTransitionFramesRemaining[mE] = _packetBuffer[2]; #if ATEM_debug if ((_serialOutput==0x80 && atemTransitionFramesRemaining[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemTransitionFramesRemaining[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemTransitionFramesRemaining[mE]); } #endif #if ATEM_debug temp = atemTransitionPosition[mE]; #endif atemTransitionPosition[mE] = word(_packetBuffer[4], _packetBuffer[5]); #if ATEM_debug if ((_serialOutput==0x80 && atemTransitionPosition[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemTransitionPosition[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemTransitionPosition[mE]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("KeOn"))) { mE = _packetBuffer[0]; keyer = _packetBuffer[1]; if (mE<=1 && keyer<=3) { #if ATEM_debug temp = atemKeyerOnAirEnabled[mE][keyer]; #endif atemKeyerOnAirEnabled[mE][keyer] = _packetBuffer[2]; #if ATEM_debug if ((_serialOutput==0x80 && atemKeyerOnAirEnabled[mE][keyer]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemKeyerOnAirEnabled[mE=")); Serial.print(mE); Serial.print(F("][keyer=")); Serial.print(keyer); Serial.print(F("] = ")); Serial.println(atemKeyerOnAirEnabled[mE][keyer]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("DskS"))) { keyer = _packetBuffer[0]; if (keyer<=1) { #if ATEM_debug temp = atemDownstreamKeyerOnAir[keyer]; #endif atemDownstreamKeyerOnAir[keyer] = _packetBuffer[1]; #if ATEM_debug if ((_serialOutput==0x80 && atemDownstreamKeyerOnAir[keyer]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemDownstreamKeyerOnAir[keyer=")); Serial.print(keyer); Serial.print(F("] = ")); Serial.println(atemDownstreamKeyerOnAir[keyer]); } #endif #if ATEM_debug temp = atemDownstreamKeyerInTransition[keyer]; #endif atemDownstreamKeyerInTransition[keyer] = _packetBuffer[2]; #if ATEM_debug if ((_serialOutput==0x80 && atemDownstreamKeyerInTransition[keyer]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemDownstreamKeyerInTransition[keyer=")); Serial.print(keyer); Serial.print(F("] = ")); Serial.println(atemDownstreamKeyerInTransition[keyer]); } #endif #if ATEM_debug temp = atemDownstreamKeyerIsAutoTransitioning[keyer]; #endif atemDownstreamKeyerIsAutoTransitioning[keyer] = _packetBuffer[3]; #if ATEM_debug if ((_serialOutput==0x80 && atemDownstreamKeyerIsAutoTransitioning[keyer]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemDownstreamKeyerIsAutoTransitioning[keyer=")); Serial.print(keyer); Serial.print(F("] = ")); Serial.println(atemDownstreamKeyerIsAutoTransitioning[keyer]); } #endif #if ATEM_debug temp = atemDownstreamKeyerFramesRemaining[keyer]; #endif atemDownstreamKeyerFramesRemaining[keyer] = _packetBuffer[4]; #if ATEM_debug if ((_serialOutput==0x80 && atemDownstreamKeyerFramesRemaining[keyer]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemDownstreamKeyerFramesRemaining[keyer=")); Serial.print(keyer); Serial.print(F("] = ")); Serial.println(atemDownstreamKeyerFramesRemaining[keyer]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("FtbS"))) { mE = _packetBuffer[0]; if (mE<=1) { #if ATEM_debug temp = atemFadeToBlackStateFullyBlack[mE]; #endif atemFadeToBlackStateFullyBlack[mE] = _packetBuffer[1]; #if ATEM_debug if ((_serialOutput==0x80 && atemFadeToBlackStateFullyBlack[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemFadeToBlackStateFullyBlack[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemFadeToBlackStateFullyBlack[mE]); } #endif #if ATEM_debug temp = atemFadeToBlackStateInTransition[mE]; #endif atemFadeToBlackStateInTransition[mE] = _packetBuffer[2]; #if ATEM_debug if ((_serialOutput==0x80 && atemFadeToBlackStateInTransition[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemFadeToBlackStateInTransition[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemFadeToBlackStateInTransition[mE]); } #endif #if ATEM_debug temp = atemFadeToBlackStateFramesRemaining[mE]; #endif atemFadeToBlackStateFramesRemaining[mE] = _packetBuffer[3]; #if ATEM_debug if ((_serialOutput==0x80 && atemFadeToBlackStateFramesRemaining[mE]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemFadeToBlackStateFramesRemaining[mE=")); Serial.print(mE); Serial.print(F("] = ")); Serial.println(atemFadeToBlackStateFramesRemaining[mE]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("AuxS"))) { aUXChannel = _packetBuffer[0]; if (aUXChannel<=5) { #if ATEM_debug temp = atemAuxSourceInput[aUXChannel]; #endif atemAuxSourceInput[aUXChannel] = word(_packetBuffer[2], _packetBuffer[3]); #if ATEM_debug if ((_serialOutput==0x80 && atemAuxSourceInput[aUXChannel]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemAuxSourceInput[aUXChannel=")); Serial.print(aUXChannel); Serial.print(F("] = ")); Serial.println(atemAuxSourceInput[aUXChannel]); } #endif } } else if(!strcmp_P(cmdStr, PSTR("TlIn"))) { sources = word(_packetBuffer[0],_packetBuffer[1]); if (sources<=20) { #if ATEM_debug temp = atemTallyByIndexSources; #endif atemTallyByIndexSources = word(_packetBuffer[0], _packetBuffer[1]); #if ATEM_debug if ((_serialOutput==0x80 && atemTallyByIndexSources!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemTallyByIndexSources = ")); Serial.println(atemTallyByIndexSources); } #endif for(uint8_t a=0;a<sources;a++) { #if ATEM_debug temp = atemTallyByIndexTallyFlags[a]; #endif atemTallyByIndexTallyFlags[a] = _packetBuffer[2+a]; #if ATEM_debug if ((_serialOutput==0x80 && atemTallyByIndexTallyFlags[a]!=temp) || (_serialOutput==0x81 && !hasInitialized())) { Serial.print(F("atemTallyByIndexTallyFlags[a=")); Serial.print(a); Serial.print(F("] = ")); Serial.println(atemTallyByIndexTallyFlags[a]); } #endif } } } else {} }
/** * If a package longer than a normal acknowledgement is received from the ATEM Switcher we must read through the contents. * Usually such a package contains updated state information about the mixer * Selected information is extracted in this function and transferred to internal variables in this library. */ void ATEM::_parsePacket(uint16_t packetLength) { uint8_t idx; // General reusable index usable for keyers, mediaplayer etc below. // If packet is more than an ACK packet (= if its longer than 12 bytes header), lets parse it: uint16_t indexPointer = 12; // 12 bytes has already been read from the packet... while (indexPointer < packetLength) { // Read the length of segment (first word): _Udp.read(_packetBuffer, 8); _cmdLength = word(_packetBuffer[0], _packetBuffer[1]); _cmdPointer = 0; // Get the "command string", basically this is the 4 char variable name in the ATEM memory holding the various state values of the system: char cmdStr[] = { _packetBuffer[4], _packetBuffer[5], _packetBuffer[6], _packetBuffer[7], '\0'}; // If length of segment larger than 8 (should always be...!) if (_cmdLength>8) { _readToPacketBuffer(); // Extract the specific state information we like to know about: if(strcmp(cmdStr, "PrgI") == 0) { // Program Bus status _ATEM_PrgI = _packetBuffer[1]; if (_serialOutput) Serial.print(F("Program Bus: ")); if (_serialOutput) Serial.println(_ATEM_PrgI, DEC); } else if(strcmp(cmdStr, "PrvI") == 0) { // Preview Bus status _ATEM_PrvI = _packetBuffer[1]; if (_serialOutput) Serial.print(F("Preview Bus: ")); if (_serialOutput) Serial.println(_ATEM_PrvI, DEC); } else if(strcmp(cmdStr, "TlIn") == 0) { // Tally status for inputs 1-8 uint8_t count = _packetBuffer[1]; // Number of inputs // Currently is only 8 inputs supported so make sure to read max 8. if(count > 8) { count = 8; } // Inputs 1-8, bit 0 = Prg tally, bit 1 = Prv tally. Both can be set simultaneously. for(uint8_t i = 0; i < count; ++i) { _ATEM_TlIn[i] = _packetBuffer[2+i]; } if (_serialOutput) Serial.println(F("Tally updated: ")); } else if(strcmp(cmdStr, "Time") == 0) { // Time. What is this anyway? } else if(strcmp(cmdStr, "TrPr") == 0) { // Transition Preview _ATEM_TrPr = _packetBuffer[1] > 0 ? true : false; if (_serialOutput) Serial.print(F("Transition Preview: ")); if (_serialOutput) Serial.println(_ATEM_TrPr, BIN); } else if(strcmp(cmdStr, "TrPs") == 0) { // Transition Position _ATEM_TrPs_frameCount = _packetBuffer[2]; // Frames count down _ATEM_TrPs_position = _packetBuffer[4]*256 + _packetBuffer[5]; // Position 0-1000 - maybe more in later firmwares? } else if(strcmp(cmdStr, "TrSS") == 0) { // Transition Style and Keyer on next transition _ATEM_TrSS_KeyersOnNextTransition = _packetBuffer[2] & B11111; // Bit 0: Background; Bit 1-4: Key 1-4 if (_serialOutput) Serial.print(F("Keyers on Next Transition: ")); if (_serialOutput) Serial.println(_ATEM_TrSS_KeyersOnNextTransition, BIN); _ATEM_TrSS_TransitionStyle = _packetBuffer[1]; if (_serialOutput) Serial.print(F("Transition Style: ")); // 0=MIX, 1=DIP, 2=WIPE, 3=DVE, 4=STING if (_serialOutput) Serial.println(_ATEM_TrSS_TransitionStyle, DEC); } else if(strcmp(cmdStr, "FtbS") == 0) { // Fade To Black State _ATEM_FtbS_state = _packetBuffer[1]; // State of Fade To Black, 0 = off and 1 = activated _ATEM_FtbS_frameCount = _packetBuffer[2]; // Frames count down } else if(strcmp(cmdStr, "FtbP") == 0) { // Fade To Black - Positions(?) (Transition Time in frames for FTB): 0x01-0xFA _ATEM_FtbP_time = _packetBuffer[1]; } else if(strcmp(cmdStr, "TMxP") == 0) { // Mix Transition Position(?) (Transition Time in frames for Mix transitions.): 0x01-0xFA _ATEM_TMxP_time = _packetBuffer[1]; } else if(strcmp(cmdStr, "DskS") == 0) { // Downstream Keyer state. Also contains information about the frame count in case of "Auto" idx = _packetBuffer[0]; if (idx >=0 && idx <=1) { _ATEM_DskOn[idx] = _packetBuffer[1] > 0 ? true : false; if (_serialOutput) Serial.print(F("Dsk Keyer ")); if (_serialOutput) Serial.print(idx+1); if (_serialOutput) Serial.print(F(": ")); if (_serialOutput) Serial.println(_ATEM_DskOn[idx], BIN); } } else if(strcmp(cmdStr, "DskP") == 0) { // Downstream Keyer Tie idx = _packetBuffer[0]; if (idx >=0 && idx <=1) { _ATEM_DskTie[idx] = _packetBuffer[1] > 0 ? true : false; if (_serialOutput) Serial.print(F("Dsk Keyer")); if (_serialOutput) Serial.print(idx+1); if (_serialOutput) Serial.print(F(" Tie: ")); if (_serialOutput) Serial.println(_ATEM_DskTie[idx], BIN); } } else if(strcmp(cmdStr, "KeOn") == 0) { // Upstream Keyer on idx = _packetBuffer[1]; if (idx >=0 && idx <=3) { _ATEM_KeOn[idx] = _packetBuffer[2] > 0 ? true : false; if (_serialOutput) Serial.print(F("Upstream Keyer ")); if (_serialOutput) Serial.print(idx+1); if (_serialOutput) Serial.print(F(": ")); if (_serialOutput) Serial.println(_ATEM_KeOn[idx], BIN); } } else if(strcmp(cmdStr, "ColV") == 0) { // Color Generator Change // Todo: Relatively easy: 8 bytes, first is the color generator, the last 6 is hsl words } else if(strcmp(cmdStr, "MPCE") == 0) { // Media Player Clip Enable idx = _packetBuffer[0]; if (idx >=0 && idx <=1) { _ATEM_MPType[idx] = _packetBuffer[1]; _ATEM_MPStill[idx] = _packetBuffer[2]; _ATEM_MPClip[idx] = _packetBuffer[3]; } } else if(strcmp(cmdStr, "AuxS") == 0) { // Aux Output Source uint8_t auxInput = _packetBuffer[0]; if (auxInput >=0 && auxInput <=2) { _ATEM_AuxS[auxInput] = _packetBuffer[1]; if (_serialOutput) Serial.print(F("Aux ")); if (_serialOutput) Serial.print(auxInput+1); if (_serialOutput) Serial.print(F(" Output: ")); if (_serialOutput) Serial.println(_ATEM_AuxS[auxInput], DEC); } } else if(strcmp(cmdStr, "_ver") == 0) { // Firmware version _ATEM_ver_m = _packetBuffer[1]; // Firmware version, "left of decimal point" (what is that called anyway?) _ATEM_ver_l = _packetBuffer[3]; // Firmware version, decimals ("right of decimal point") } else if(strcmp(cmdStr, "_pin") == 0) { // Name for(uint8_t i=0;i<16;i++) { _ATEM_pin[i] = _packetBuffer[i]; } _ATEM_pin[16] = 0; // Termination } else if(strcmp(cmdStr, "AMTl") == 0) { // Audio Monitor Tally (on/off settings) // Same system as for video: "TlIn"... just implement when time. } else // Note for future reveng: For master control, volume at least comes back in "AMMO" (CAMM is the command code.) if(strcmp(cmdStr, "AMIP") == 0) { // Audio Monitor Input P... (state) (On, Off, AFV) if (_packetBuffer[0]<13) { _ATEM_AudioChannelMode[_packetBuffer[0]] = _packetBuffer[3]; } /* for(uint8_t a=0;a<_cmdLength-8;a++) { if (_serialOutput) Serial.print((uint8_t)_packetBuffer[a], HEX); if (_serialOutput) Serial.print(" "); } if (_serialOutput) Serial.println(""); */ /* 1M/E: 0: MASTER 1: (Monitor?) 2-9: HDMI1 - SDI8 10: MP1 11: MP2 12: EXT TVS: 0: MASTER 1: (Monitor?) 2-7: INPUT1-6 (HDMI - HDMI - HDMI/SDI - HDMI/SDI - SDI - SDI) 8: EXT */ /* Serial.print("Audio Channel: "); Serial.println(_packetBuffer[0]); // _packetBuffer[2] seems to be input number (one higher...) Serial.print(" - State: "); Serial.println(_packetBuffer[3] == 0x01 ? "ON" : (_packetBuffer[3] == 0x02 ? "AFV" : (_packetBuffer[3] > 0 ? "???" : "OFF"))); Serial.print(" - Volume: "); Serial.print((uint16_t)_packetBuffer[4]*256+_packetBuffer[5]); Serial.print("/"); Serial.println((uint16_t)_packetBuffer[6]*256+_packetBuffer[7]); */ } else if(strcmp(cmdStr, "AMLv") == 0) { // Audio Monitor Levels uint16_t readingOffset = 4+(_ATEM_AMLv_channel << 4); // *16 while (readingOffset+4 > 96) { readingOffset-=96; _readToPacketBuffer(); } _ATEM_AMLv[0] = ((uint16_t)(_packetBuffer[readingOffset+1]<<8) | _packetBuffer[readingOffset+2]); //drops the 8 least sign. bits! -> 15 bit resolution for VU purposes. fine enough. readingOffset+=4; while (readingOffset+4 > 96) { readingOffset-=96; _readToPacketBuffer(); } _ATEM_AMLv[1] = ((uint16_t)(_packetBuffer[readingOffset+1]<<8) | _packetBuffer[readingOffset+2]); //drops the 8 least sign. bits! -> 15 bit resolution for VU purposes. fine enough. } else if(strcmp(cmdStr, "VidM") == 0) { // Video format (SD, HD, framerate etc.) _ATEM_VidM = _packetBuffer[0]; } else { // SHOULD ONLY THE UNCOMMENTED for development and with a high Baud rate on serial - 115200 for instance. Otherwise it will not connect due to serial writing speeds. /* if (_serialOutput) { Serial.print(("???? Unknown token: ")); Serial.print(cmdStr); Serial.print(" : "); } for(uint8_t a=(-2+8);a<_cmdLength-2;a++) { if (_serialOutput) Serial.print((uint8_t)_packetBuffer[a], HEX); if (_serialOutput) Serial.print(" "); } if (_serialOutput) Serial.println(""); */ } // Empty, if long packet and not read yet: while (_readToPacketBuffer()) {} indexPointer+=_cmdLength; } else { indexPointer = 2000; // Flushing the buffer: // TODO: Other way? _Udp.flush() ?? while(_Udp.available()) { _Udp.read(_packetBuffer, 96); } } } }