void WaveformMarkSet::setup(const QString& group, const QDomNode& node, const WaveformSignalColors& signalColors) { m_defaultMark = WaveformMark(); m_marks.clear(); m_defaultMark = WaveformMark(); m_marks.clear(); #if QT_VERSION >= 0x040700 m_marks.reserve(NUM_HOT_CUES); #endif std::set<QString> controlItemSet; bool hasDefaultMark = false; QDomNode child = node.firstChild(); while (!child.isNull()) { if (child.nodeName() == "DefaultMark") { m_defaultMark.setup(group, child, signalColors); hasDefaultMark = true; } else if (child.nodeName() == "Mark") { m_marks.push_back(WaveformMark()); WaveformMark& mark = m_marks.back(); mark.setup(group, child, signalColors); if (mark.m_pointControl) { // guarantee uniqueness even if there is a misdesigned skin QString item = mark.m_pointControl->getKey().item; if (!controlItemSet.insert(item).second) { qWarning() << "WaveformRenderMark::setup - redefinition of" << item; m_marks.removeAt(m_marks.size() - 1); } } } child = child.nextSibling(); } //check if there is a default mark and compare declared //and to create all missing hot_cues if (hasDefaultMark) { for (int i = 1; i < NUM_HOT_CUES; ++i) { QString hotCueControlItem = "hotcue_" + QString::number(i) + "_position"; ControlObject* pHotcue = ControlObject::getControl( ConfigKey(group, hotCueControlItem)); if (pHotcue == NULL) { continue; } if (controlItemSet.insert(hotCueControlItem).second) { //qDebug() << "WaveformRenderMark::setup - Automatic mark" << hotCueControlItem; m_marks.push_back(m_defaultMark); WaveformMark& mark = m_marks.back(); mark.m_pointControl = new ControlObjectThreadMain(pHotcue->getKey()); mark.m_text = mark.m_text.arg(i); } } } }
bool MixxxKeyboard::eventFilter(QObject*, QEvent* e) { if (e->type() == QEvent::FocusOut) { // If we lose focus, we need to clear out the active key list // because we might not get Key Release events. m_qActiveKeyList.clear(); } else if (e->type() == QEvent::KeyPress) { QKeyEvent* ke = (QKeyEvent *)e; #ifdef __APPLE__ // On Mac OSX the nativeScanCode is empty (const 1) http://doc.qt.nokia.com/4.7/qkeyevent.html#nativeScanCode // We may loose the release event if a the shift key is pressed later // and there is character shift like "1" -> "!" int keyId = ke->key(); #else int keyId = ke->nativeScanCode(); #endif //qDebug() << "KeyPress event =" << ke->key() << "KeyId =" << keyId; // Run through list of active keys to see if the pressed key is already active // Just for returning true if we are consuming this key event foreach (const KeyDownInformation& keyDownInfo, m_qActiveKeyList) { if (keyDownInfo.keyId == keyId) { return true; } } QKeySequence ks = getKeySeq(ke); if (!ks.isEmpty()) { ConfigValueKbd ksv(ks); // Check if a shortcut is defined bool result = false; // using const_iterator here is faster than QMultiHash::values() for (QMultiHash<ConfigValueKbd, ConfigKey>::const_iterator it = m_keySequenceToControlHash.find(ksv); it != m_keySequenceToControlHash.end() && it.key() == ksv; ++it) { const ConfigKey& configKey = it.value(); if (configKey.group != "[KeyboardShortcuts]") { ControlObject* control = ControlObject::getControl(configKey); if (control) { //qDebug() << configKey << "MIDI_NOTE_ON" << 1; // Add key to active key list m_qActiveKeyList.append(KeyDownInformation( keyId, ke->modifiers(), control)); // Since setting the value might cause us to go down // a route that would eventually clear the active // key list, do that last. control->setValueFromMidi(MIDI_NOTE_ON, 1); result = true; } else { qDebug() << "Warning: Keyboard key is configured for nonexistent control:" << configKey.group << configKey.item; } } } return result; } } else if (e->type()==QEvent::KeyRelease) {
void DlgPrefVinyl::VinylGainSlotApply() { qDebug() << "in VinylGainSlotApply()" << "with gain:" << VinylGain->value(); //Update the config key... config->set(ConfigKey(VINYL_PREF_KEY,"gain"), ConfigValue(VinylGain->value())); //Update the ControlObject... ControlObject* pControlObjectVinylControlGain = ControlObject::getControl(ConfigKey(VINYL_PREF_KEY, "gain")); pControlObjectVinylControlGain->set(VinylGain->value()); }
TEST_F(ControllerEngineTest, scriptSetValue) { ScopedTemporaryFile script(makeTemporaryFile( "setValue = function() { engine.setValue('[Channel1]', 'co', 1.0); }\n")); cEngine->evaluate(script->fileName()); EXPECT_FALSE(cEngine->hasErrors(script->fileName())); ControlObject *co = new ControlObject(ConfigKey("[Channel1]", "co")); co->set(0.0); execute("setValue"); EXPECT_DOUBLE_EQ(co->get(), 1.0); delete co; }
void WWaveformViewer::dragEnterEvent(QDragEnterEvent * event) { // Accept the enter event if the thing is a filepath. if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() > 0) { ControlObject *pPlayCO = ControlObject::getControl( ConfigKey(m_pGroup, "play")); // Accept if the Deck isn't playing or the settings allow to interupt a playing deck if (pPlayCO && (!pPlayCO->get() || m_pConfig->getValueString(ConfigKey("[Controls]","AllowTrackLoadToPlayingDeck")).toInt())) { event->acceptProposedAction(); } else { event->ignore(); } } }
void LADSPAPresetInstance::addControl(int i, LADSPAPresetKnob * knob, EngineLADSPA * engine) { ConfigKey * key = new ConfigKey("[LADSPA]", knob->getLabel()); ControlObject * potmeter = new ControlPotmeter(*key, knob->getMin(), knob->getMax()); ControlObjectThreadMain * potmeterThreadMain = new ControlObjectThreadMain(potmeter->getKey()); LADSPAControl * control = new LADSPAControl; control->setValue(knob->getDefault()); potmeterThreadMain->slotSet(knob->getDefault()); m_Keys[i] = key; LADSPAPortConnectionVector * portConnections = knob->getConnections(); for (LADSPAPortConnectionVector::iterator connection = portConnections->begin(); connection != portConnections->end(); connection++) { m_Instances[(*connection).plugin]->connect((*connection).port, control->getBuffer()); } m_Connections[i] = engine->addControl(potmeter, control); }
void Control_processControlActions(MmsMapping* self, uint64_t currentTimeInMs) { LinkedList element = LinkedList_getNext(self->controlObjects); while (element != NULL) { ControlObject* controlObject = (ControlObject*) element->data; if (controlObject->state == STATE_WAIT_FOR_ACTIVATION_TIME) { if (controlObject->operateTime <= currentTimeInMs) { if (DEBUG_IED_SERVER) printf("time activated operate: start operation\n"); controlObject->timeActivatedOperate = false; CheckHandlerResult checkResult = CONTROL_ACCEPTED; if (controlObject->checkHandler != NULL) { /* perform operative tests */ checkResult = controlObject->checkHandler( controlObject->checkHandlerParameter, controlObject->ctlVal, controlObject->testMode, controlObject->interlockCheck, (ClientConnection) controlObject->mmsConnection); } if (checkResult == CONTROL_ACCEPTED) { executeControlTask(controlObject); } else { ControlObject_sendLastApplError(controlObject, controlObject->mmsConnection, "Oper", CONTROL_ERROR_NO_ERROR, ADD_CAUSE_BLOCKED_BY_INTERLOCKING, controlObject->ctlNum, controlObject->origin, false); abortControlOperation(controlObject); } } } /* if (controlObject->state == STATE_WAIT_FOR_ACTICATION_TIME) */ else if (!((controlObject->state == STATE_UNSELECTED) || (controlObject->state == STATE_READY))) { executeControlTask(controlObject); } element = LinkedList_getNext(element); } }
bool MixxxKeyboard::eventFilter(QObject*, QEvent* e) { if (e->type() == QEvent::KeyPress) { QKeyEvent* ke = (QKeyEvent *)e; #ifdef __APPLE__ // On Mac OSX the nativeScanCode is empty (const 1) http://doc.qt.nokia.com/4.7/qkeyevent.html#nativeScanCode // We may loose the release event if a the shift key is pressed later // and there is character shift like "1" -> "!" int keyId = ke->key(); #else int keyId = ke->nativeScanCode(); #endif //qDebug() << "KeyPress event =" << ke->key() << "KeyId =" << keyId; // Run through list of active keys to see if the pressed key is already active // Just for returning true if we are consuming this key event foreach (const KeyDownInformation& keyDownInfo, m_qActiveKeyList) { if (keyDownInfo.keyId == keyId) { return true; } } QKeySequence ks = getKeySeq(ke); if (!ks.isEmpty()) { // Check if a shortcut is defined ConfigKey* pConfigKey = m_pKbdConfigObject->get(ConfigValueKbd(ks)); if (pConfigKey && pConfigKey->group != "[KeyboardShortcuts]") { ControlObject* control = ControlObject::getControl(*pConfigKey); if (control) { //qDebug() << pConfigKey->group << pConfigKey->item << "MIDI_NOTE_ON" << 1; control->setValueFromMidi(MIDI_NOTE_ON, 1); // Add key to active key list m_qActiveKeyList.append(KeyDownInformation( keyId, ke->modifiers(), pConfigKey)); return true; } else { qDebug() << "Warning: Keyboard key is configured for nonexistent control: " << pConfigKey->group << " " << pConfigKey->item; return false; } } } } else if (e->type()==QEvent::KeyRelease) {
static int MainProcess( const wchar_t *lpwszEditName, const wchar_t *lpwszViewName, const wchar_t *lpwszDestName1, const wchar_t *lpwszDestName2, int StartLine, int StartChar ) { { ChangePriority ChPriority(ChangePriority::NORMAL); ControlObject CtrlObj; WORD InitAttributes=0; Console.GetTextAttributes(InitAttributes); SetRealColor(COL_COMMANDLINEUSERSCREEN); if (*lpwszEditName || *lpwszViewName) { Opt.OnlyEditorViewerUsed=1; Panel *DummyPanel=new Panel; _tran(SysLog(L"create dummy panels")); CtrlObj.CreateFilePanels(); CtrlObj.Cp()->LeftPanel=CtrlObj.Cp()->RightPanel=CtrlObj.Cp()->ActivePanel=DummyPanel; CtrlObj.Plugins.LoadPlugins(); CtrlObj.Macro.LoadMacros(TRUE,FALSE); if (*lpwszEditName) { FileEditor *ShellEditor=new FileEditor(lpwszEditName,CP_AUTODETECT,FFILEEDIT_CANNEWFILE|FFILEEDIT_ENABLEF6,StartLine,StartChar); _tran(SysLog(L"make shelleditor %p",ShellEditor)); if (!ShellEditor->GetExitCode()) // ???????????? { FrameManager->ExitMainLoop(0); } } // TODO: Этот else убрать только после разборок с возможностью задавать несколько /e и /v в ком.строке else if (*lpwszViewName) { FileViewer *ShellViewer=new FileViewer(lpwszViewName,FALSE); if (!ShellViewer->GetExitCode()) { FrameManager->ExitMainLoop(0); } _tran(SysLog(L"make shellviewer, %p",ShellViewer)); } FrameManager->EnterMainLoop(); CtrlObj.Cp()->LeftPanel=CtrlObj.Cp()->RightPanel=CtrlObj.Cp()->ActivePanel=nullptr; delete DummyPanel; _tran(SysLog(L"editor/viewer closed, delete dummy panels")); } else { Opt.OnlyEditorViewerUsed=0; Opt.SetupArgv=0; FARString strPath; // воспользуемся тем, что ControlObject::Init() создает панели // юзая Opt.* if (*lpwszDestName1) // актиная панель { Opt.SetupArgv++; strPath = lpwszDestName1; CutToNameUNC(strPath); DeleteEndSlash(strPath); //BUGBUG!! если конечный слешь не убрать - получаем забавный эффект - отсутствует ".." // if ((strPath.At(1)==L':' && !strPath.At(2)) || (HasPathPrefix(strPath) && strPath.At(5)==L':' && !strPath.At(6))) // AddEndSlash(strPath); // Та панель, которая имеет фокус - активна (начнем по традиции с Левой Панели ;-) if (Opt.LeftPanel.Focus) { Opt.LeftPanel.Type=FILE_PANEL; // сменим моду панели Opt.LeftPanel.Visible=TRUE; // и включим ее Opt.strLeftFolder = strPath; } else { Opt.RightPanel.Type=FILE_PANEL; Opt.RightPanel.Visible=TRUE; Opt.strRightFolder = strPath; } if (*lpwszDestName2) // пассивная панель { Opt.SetupArgv++; strPath = lpwszDestName2; CutToNameUNC(strPath); DeleteEndSlash(strPath); //BUGBUG!! если конечный слешь не убрать - получаем забавный эффект - отсутствует ".." // if ((strPath.At(1)==L':' && !strPath.At(2)) || (HasPathPrefix(strPath) && strPath.At(5)==L':' && !strPath.At(6))) // AddEndSlash(strPath); // а здесь с точнотью наоборот - обрабатываем пассивную панель if (Opt.LeftPanel.Focus) { Opt.RightPanel.Type=FILE_PANEL; // сменим моду панели Opt.RightPanel.Visible=TRUE; // и включим ее Opt.strRightFolder = strPath; } else { Opt.LeftPanel.Type=FILE_PANEL; Opt.LeftPanel.Visible=TRUE; Opt.strLeftFolder = strPath; } } } // теперь все готово - создаем панели! CtrlObj.Init(); // а теперь "провалимся" в каталог или хост-файл (если получится ;-) if (*lpwszDestName1) // актиная панель { FARString strCurDir; Panel *ActivePanel=CtrlObject->Cp()->ActivePanel; Panel *AnotherPanel=CtrlObject->Cp()->GetAnotherPanel(ActivePanel); if (*lpwszDestName2) // пассивная панель { AnotherPanel->GetCurDir(strCurDir); FarChDir(strCurDir); if (IsPluginPrefixPath(lpwszDestName2)) { AnotherPanel->SetFocus(); CtrlObject->CmdLine->ExecString(lpwszDestName2,0); ActivePanel->SetFocus(); } else { strPath = PointToNameUNC(lpwszDestName2); if (!strPath.IsEmpty()) { if (AnotherPanel->GoToFile(strPath)) AnotherPanel->ProcessKey(KEY_CTRLPGDN); } } } ActivePanel->GetCurDir(strCurDir); FarChDir(strCurDir); if (IsPluginPrefixPath(lpwszDestName1)) { CtrlObject->CmdLine->ExecString(lpwszDestName1,0); } else { strPath = PointToNameUNC(lpwszDestName1); if (!strPath.IsEmpty()) { if (ActivePanel->GoToFile(strPath)) ActivePanel->ProcessKey(KEY_CTRLPGDN); } } // !!! ВНИМАНИЕ !!! // Сначала редравим пассивную панель, а потом активную! AnotherPanel->Redraw(); ActivePanel->Redraw(); } FrameManager->EnterMainLoop(); } // очистим за собой! SetScreen(0,0,ScrX,ScrY,L' ',COL_COMMANDLINEUSERSCREEN); Console.SetTextAttributes(InitAttributes); ScrBuf.ResetShadow(); ScrBuf.Flush(); MoveRealCursor(0,0); } CloseConsole(); return 0; }
bool ControllerLearningEventFilter::eventFilter(QObject* pObject, QEvent* pEvent) { //qDebug() << "ControllerLearningEventFilter::eventFilter" << pObject << pEvent; WWidget* pWidget = dynamic_cast<WWidget*>(pObject); if (!pWidget || !m_bListening) { return false; } WKnob* pKnob = dynamic_cast<WKnob*>(pObject); WSliderComposed* pSlider = dynamic_cast<WSliderComposed*>(pObject); bool has_right_click_reset = pKnob || pSlider; if (pEvent->type() == QEvent::KeyPress) { // TODO(XXX): handle keypresses? } else if (pEvent->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = reinterpret_cast<QMouseEvent*>(pEvent); qDebug() << "MouseButtonPress" << pWidget; const ControlInfo& info = m_widgetControlInfo[pWidget]; if (mouseEvent->button() & Qt::LeftButton) { if (info.leftClickControl) { ConfigKey key = info.leftClickControl->getKey(); qDebug() << "Left-click maps MIDI to:" << key.group << key.item; emit(controlClicked(info.leftClickControl)); } else if (info.clickControl) { ConfigKey key = info.clickControl->getKey(); emit(controlClicked(info.clickControl)); qDebug() << "Default-click maps MIDI to:" << key.group << key.item; } else { qDebug() << "No control bound to left-click for" << pWidget; } } if (mouseEvent->button() & Qt::RightButton) { if (info.rightClickControl) { ConfigKey key = info.rightClickControl->getKey(); qDebug() << "Right-click maps MIDI to:" << key.group << key.item; emit(controlClicked(info.rightClickControl)); } else if (has_right_click_reset && (info.leftClickControl || info.clickControl)) { // WKnob and WSliderComposed emits a reset signal on // right-click. For controls that are derived from // ControlPotmeter, we can hack this by appending "_set_default" // to the ConfigKey item. ControlObject* pControl = info.leftClickControl; if (!pControl) { pControl = info.clickControl; } ConfigKey key = pControl->getKey(); key.item = key.item + "_set_default"; ControlObject* pResetControl = ControlObject::getControl(key); if (pResetControl) { qDebug() << "Right-click reset maps MIDI to:" << key.group << key.item; emit(controlClicked(pResetControl)); } } else if (info.clickControl) { ConfigKey key = info.clickControl->getKey(); qDebug() << "Default-click maps MIDI to:" << key.group << key.item; emit(controlClicked(info.clickControl)); } else { qDebug() << "No control bound to right-click for" << pWidget; } } } else if (pEvent->type() == QEvent::MouseButtonRelease) { qDebug() << "MouseButtonRelease" << pWidget; } else if (pEvent->type() == QEvent::MouseMove) { qDebug() << "MouseMoveEvent" << pWidget; } return false; }
LADSPAPresetSlot::LADSPAPresetSlot(QWidget *parent, QDomElement element, int slot, LADSPAPresetManager *presetManager, QPalette palette) : QWidget(parent) { m_pPresetManager = presetManager; m_qPalette = palette; m_iSlotNumber = slot; setAcceptDrops(true); m_pScrollArea = new QScrollArea(this); m_pScrollWidget = new QWidget(m_pScrollArea); m_pScrollArea->setWidget(m_pScrollWidget); //m_pScrollArea->setWidgetResizable(true); m_pScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QDomElement posElement = element.firstChildElement("Pos"); QString pos = posElement.text(); int x = pos.left(pos.indexOf(",")).toInt(); int y = pos.mid(pos.indexOf(",") + 1).toInt(); if (x < 0) { x = parent->width() + x; } if (y < 0) { y = parent->height() + y; } QDomElement spacingElement = element.firstChildElement("Spacing"); QString spacing = spacingElement.text(); int spacingWidth = spacing.left(spacing.indexOf(",")).toInt(); int spacingHeight = spacing.mid(spacing.indexOf(",") + 1).toInt(); QDomElement sizeElement = element.firstChildElement("Size"); QString size = sizeElement.text(); int width = size.left(size.indexOf(",")).toInt(); int height = size.mid(size.indexOf(",") + 1).toInt(); if (width <= 0) { width = parent->width() + width; } if (height <= 0) { height = parent->height() + height; } move(x + slot * spacingWidth, y + slot * (height + spacingHeight)); resize(width, height); m_pScrollArea->resize(width, height); m_pScrollWidget->resize(width - 5, height - 5); m_iBaseWidth = width; QString slotString; slotString.setNum(slot); QDomNodeList buttonNodeList = element.elementsByTagName("PushButton"); for (int i = 0; i < buttonNodeList.count(); i++) { QDomElement buttonElement = buttonNodeList.item(i).toElement(); QString configKey = buttonElement.firstChildElement("Connection").firstChildElement("ConfigKey").text(); if (configKey.startsWith("[LADSPA],RemoveEffect")) { QString keyString = QString("RemoveEffect") + slotString; ConfigKey *key = new ConfigKey("[LADSPA]", keyString); ControlPushButton *control = new ControlPushButton(*key, false); m_pRemoveButton = new WPushButton(m_pScrollWidget); buttonElement.firstChildElement("Connection").firstChildElement("ConfigKey").firstChild().setNodeValue("[LADSPA]," + keyString); m_pRemoveButton->setup(buttonElement); m_pRemoveButton->setVisible(false); } else if (configKey.startsWith("[LADSPA],EnableEffect")) { qDebug() << "Setting up LADSPA EnableEffect" << slotString; QString keyString = QString("EnableEffect") + slotString; ConfigKey *key = new ConfigKey("[LADSPA]", keyString); qDebug() << "Key string:" << keyString; ControlObject *control = new ControlPushButton(*key, false); control->set(1.0f); m_pEnableButton = new WPushButton(m_pScrollWidget); buttonElement.firstChildElement("Connection").firstChildElement("ConfigKey").firstChild().setNodeValue("[LADSPA]," + keyString); m_pEnableButton->setup(buttonElement); } else { qDebug() << "LADSPA: Invalid skin (unknown button: " << configKey << ")"; } } QDomElement labelElement = element.firstChildElement("Label"); m_pLabel = new QLabel(m_pScrollWidget); m_pLabel->setText(tr("Drag a preset from the list & drop it here")); posElement = labelElement.firstChildElement("Pos"); pos = posElement.text(); x = pos.left(pos.indexOf(",")).toInt(); y = pos.mid(pos.indexOf(",") + 1).toInt(); if (x < 0) { x = this->width() + x; } if (y < 0) { y = this->height() + y; } m_pLabel->move(x, y); QDomElement widthElement = labelElement.firstChildElement("Width"); if (!(widthElement.isNull())) { width = widthElement.text().toInt(); m_pLabel->setMaximumWidth(width); } m_pLabel->setPalette(palette); m_qKnobElement = element.firstChildElement("Knob"); m_pPresetInstance = NULL; ConfigKey *key = new ConfigKey("[LADSPA]", "DryWet" + slotString); ControlPotmeter *control = new ControlPotmeter(*key, 0.0, 1.0); m_pDryWetKnob = new WKnob(m_pScrollWidget); QString keyString = QString("[LADSPA],DryWet") + slotString; m_qKnobElement.firstChildElement(QString("Connection")).firstChildElement(QString("ConfigKey")).firstChild().setNodeValue(keyString); m_qKnobElement.firstChildElement(QString("Tooltip")).firstChild().setNodeValue("Dry/wet"); m_pDryWetKnob->setup(m_qKnobElement); m_pDryWetKnob->show(); posElement = m_qKnobElement.firstChildElement("Pos"); pos = posElement.text(); x = pos.left(pos.indexOf(",")).toInt(); y = pos.mid(pos.indexOf(",") + 1).toInt(); if (x < 0) { x = this->width() + x; } if (y < 0) { y = this->height() + y; } m_pDryWetKnob->move(x, y); spacingElement = m_qKnobElement.firstChildElement("Spacing"); spacing = spacingElement.text(); spacingWidth = spacing.left(spacing.indexOf(",")).toInt(); m_pDryWetLabel = new QLabel("Dry/wet", m_pScrollWidget); m_pDryWetLabel->setMaximumWidth(spacingWidth + m_pDryWetKnob->width() - 4); m_pDryWetLabel->show(); x += m_pDryWetKnob->width() / 2 - m_pDryWetLabel->width() / 2; m_pDryWetLabel->move(x, y + m_pDryWetKnob->height() + 1); m_pDryWetLabel->setPalette(m_qPalette); connect(m_pRemoveButton, SIGNAL(valueChangedLeftUp(double)), this, SLOT(slotRemove())); }
MmsDataAccessError Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, MmsValue* value, MmsServerConnection connection) { MmsDataAccessError indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; if (DEBUG_IED_SERVER) printf("IED_SERVER: writeAccessControlObject: %s\n", variableIdOrig); char variableId[65]; strncpy(variableId, variableIdOrig, 64); variableId[64] = 0; char* separator = strchr(variableId, '$'); if (separator == NULL) goto free_and_return; *separator = 0; char* lnName = variableId; if (lnName == NULL) goto free_and_return; char* objectName = MmsMapping_getNextNameElement(separator + 1); if (objectName == NULL) goto free_and_return; char* varName = MmsMapping_getNextNameElement(objectName); if (varName != NULL) { bool foundVar = false; char* nextVarName = varName; do { if (doesElementEquals(varName, "Oper") || doesElementEquals(varName, "SBO") || doesElementEquals(varName, "SBOw") || doesElementEquals(varName, "Cancel")) { *(varName - 1) = 0; foundVar = true; break; } nextVarName = MmsMapping_getNextNameElement(varName); if (nextVarName != NULL) varName = nextVarName; } while (nextVarName != NULL); if (foundVar == false) varName = NULL; } if (DEBUG_IED_SERVER) printf("IED_SERVER: write access control: objectName: (%s) varName: (%s)\n", objectName, varName); if (varName == NULL) { indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; goto free_and_return; } ControlObject* controlObject = Control_lookupControlObject(self, domain, lnName, objectName); if (controlObject == NULL) { indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; goto free_and_return; } initialize(controlObject); if (strcmp(varName, "SBOw") == 0) { /* select with value */ if (controlObject->ctlModel == 4) { MmsValue* ctlVal = getCtlVal(value); if (ctlVal != NULL) { MmsValue* ctlNum = getOperParameterCtlNum(value); MmsValue* origin = getOperParameterOrigin(value); MmsValue* check = getOperParameterCheck(value); MmsValue* test = getOperParameterTest(value); if (checkValidityOfOriginParameter(origin) == false) { indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; goto free_and_return; } uint64_t currentTime = Hal_getTimeInMs(); checkSelectTimeout(controlObject, currentTime); int state = getState(controlObject); if (state != STATE_UNSELECTED) { indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; if (connection != controlObject->mmsConnection) ControlObject_sendLastApplError(controlObject, connection, "SBOw", 0, ADD_CAUSE_LOCKED_BY_OTHER_CLIENT, ctlNum, origin, true); else ControlObject_sendLastApplError(controlObject, connection, "SBOw", 0, ADD_CAUSE_OBJECT_ALREADY_SELECTED, ctlNum, origin, true); if (DEBUG_IED_SERVER) printf("SBOw: select failed!\n"); } else { CheckHandlerResult checkResult = CONTROL_ACCEPTED; bool interlockCheck = MmsValue_getBitStringBit(check, 1); bool testCondition = MmsValue_getBoolean(test); if (controlObject->checkHandler != NULL) { /* perform operative tests */ ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); checkResult = controlObject->checkHandler( controlObject->checkHandlerParameter, ctlVal, testCondition, interlockCheck, clientConnection); } if (checkResult == CONTROL_ACCEPTED) { selectObject(controlObject, currentTime, connection); updateControlParameters(controlObject, ctlVal, ctlNum, origin); indication = DATA_ACCESS_ERROR_SUCCESS; if (DEBUG_IED_SERVER) printf("SBOw: selected successful\n"); } else { indication = getDataAccessErrorFromCheckHandlerResult(checkResult); ControlObject_sendLastApplError(controlObject, connection, "SBOw", 0, ADD_CAUSE_SELECT_FAILED, ctlNum, origin, true); if (DEBUG_IED_SERVER) printf("SBOw: select rejected by application!\n"); } } } else { indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; } } else { indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; goto free_and_return; } } else if (strcmp(varName, "Oper") == 0) { MmsValue* ctlVal = getCtlVal(value); MmsValue* test = getOperParameterTest(value); MmsValue* ctlNum = getOperParameterCtlNum(value); MmsValue* origin = getOperParameterOrigin(value); MmsValue* check = getOperParameterCheck(value); MmsValue* timeParameter = getOperParameterTime(value); if ((ctlVal == NULL) || (test == NULL) || (ctlNum == NULL) || (origin == NULL) || (check == NULL) || (timeParameter == NULL)) { indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; goto free_and_return; } if (checkValidityOfOriginParameter(origin) == false) { indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; goto free_and_return; } uint64_t currentTime = Hal_getTimeInMs(); checkSelectTimeout(controlObject, currentTime); int state = getState(controlObject); if (state == STATE_WAIT_FOR_ACTIVATION_TIME) { indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; ControlObject_sendLastApplError(controlObject, connection, "Oper", CONTROL_ERROR_NO_ERROR, ADD_CAUSE_COMMAND_ALREADY_IN_EXECUTION, ctlNum, origin, true); goto free_and_return; } else if (state == STATE_READY) { bool interlockCheck = MmsValue_getBitStringBit(check, 1); bool synchroCheck = MmsValue_getBitStringBit(check, 0); bool testCondition = MmsValue_getBoolean(test); controlObject->testMode = testCondition; if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4)) { if (controlObject->mmsConnection != connection) { indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; if (DEBUG_IED_SERVER) printf("Oper: operate from wrong client connection!\n"); goto free_and_return; } if (controlObject->ctlModel == 4) { /* select-before-operate with enhanced security */ if ((MmsValue_equals(ctlVal, controlObject->ctlVal) && MmsValue_equals(origin, controlObject->origin) && MmsValue_equals(ctlNum, controlObject->ctlNum)) == false) { indication = DATA_ACCESS_ERROR_TYPE_INCONSISTENT; ControlObject_sendLastApplError(controlObject, connection, "Oper", CONTROL_ERROR_NO_ERROR, ADD_CAUSE_INCONSISTENT_PARAMETERS, ctlNum, origin, true); goto free_and_return; } } } updateControlParameters(controlObject, ctlVal, ctlNum, origin); MmsValue* operTm = getOperParameterOperTime(value); if (operTm != NULL) { controlObject->operateTime = MmsValue_getUtcTimeInMs(operTm); if (controlObject->operateTime != 0) { controlObject->timeActivatedOperate = true; controlObject->synchroCheck = synchroCheck; controlObject->interlockCheck = interlockCheck; controlObject->mmsConnection = connection; initiateControlTask(controlObject); setState(controlObject, STATE_WAIT_FOR_ACTIVATION_TIME); if (DEBUG_IED_SERVER) printf("Oper: activate time activated control\n"); indication = DATA_ACCESS_ERROR_SUCCESS; } } MmsValue_update(controlObject->oper, value); if (controlObject->timeActivatedOperate == false) { CheckHandlerResult checkResult = CONTROL_ACCEPTED; if (controlObject->checkHandler != NULL) { /* perform operative tests */ ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection); checkResult = controlObject->checkHandler( controlObject->checkHandlerParameter, ctlVal, testCondition, interlockCheck, clientConnection); } if (checkResult == CONTROL_ACCEPTED) { indication = DATA_ACCESS_ERROR_NO_RESPONSE; controlObject->mmsConnection = connection; controlObject->operateInvokeId = MmsServerConnection_getLastInvokeId(connection); setState(controlObject, STATE_WAIT_FOR_EXECUTION); initiateControlTask(controlObject); #if (CONFIG_MMS_THREADLESS_STACK == 1) //TODO call this in single threaded version to increase response time!? //executeControlTask(controlObject); #endif } else { indication = getDataAccessErrorFromCheckHandlerResult(checkResult); abortControlOperation(controlObject); } } } else if (state == STATE_UNSELECTED) { if (DEBUG_IED_SERVER) printf("IED_SERVER: Oper failed - control not selected!\n"); indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; ControlObject_sendLastApplError(controlObject, connection, "Oper", CONTROL_ERROR_NO_ERROR, ADD_CAUSE_OBJECT_NOT_SELECTED, ctlNum, origin, true); goto free_and_return; } } else if (strcmp(varName, "Cancel") == 0) { if (DEBUG_IED_SERVER) printf("IED_SERVER: control received cancel!\n"); int state = getState(controlObject); MmsValue* ctlNum = getCancelParameterCtlNum(value); MmsValue* origin = getCancelParameterOrigin(value); if ((ctlNum == NULL) || (origin == NULL)) { indication = DATA_ACCESS_ERROR_TYPE_INCONSISTENT; if (DEBUG_IED_SERVER) printf("IED_SERVER: Invalid cancel message!\n"); goto free_and_return; } if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4)) { if (state != STATE_UNSELECTED) { if (controlObject->mmsConnection == connection) { indication = DATA_ACCESS_ERROR_SUCCESS; setState(controlObject, STATE_UNSELECTED); goto free_and_return; } else { indication = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; ControlObject_sendLastApplError(controlObject, connection, "Cancel", CONTROL_ERROR_NO_ERROR, ADD_CAUSE_LOCKED_BY_OTHER_CLIENT, ctlNum, origin, true); } } } if (controlObject->timeActivatedOperate) { controlObject->timeActivatedOperate = false; abortControlOperation(controlObject); indication = DATA_ACCESS_ERROR_SUCCESS; goto free_and_return; } } free_and_return: return indication; }
MmsValue* Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, MmsServerConnection connection) { MmsValue* value = NULL; if (DEBUG_IED_SERVER) printf("IED_SERVER: readAccessControlObject: %s\n", variableIdOrig); char variableId[129]; strncpy(variableId, variableIdOrig, 128); variableId[128] = 0; char* separator = strchr(variableId, '$'); if (separator == NULL) return NULL; *separator = 0; char* lnName = variableId; if (lnName == NULL) return NULL; char* objectName = MmsMapping_getNextNameElement(separator + 1); if (objectName == NULL) return NULL; char* varName = MmsMapping_getNextNameElement(objectName); if (varName != NULL) { bool foundVar = false; char* nextVarName = varName; do { if (doesElementEquals(varName, "Oper") || doesElementEquals(varName, "SBO") || doesElementEquals(varName, "SBOw") || doesElementEquals(varName, "Cancel")) { *(varName - 1) = 0; foundVar = true; break; } nextVarName = MmsMapping_getNextNameElement(varName); if (nextVarName != NULL) varName = nextVarName; } while (nextVarName != NULL); if (foundVar == false) varName = NULL; } if (DEBUG_IED_SERVER) printf("IED_SERVER: read_access control object: objectName: (%s) varName: (%s)\n", objectName, varName); ControlObject* controlObject = Control_lookupControlObject(self, domain, lnName, objectName); if (controlObject != NULL) { initialize(controlObject); if (varName != NULL) { if (strcmp(varName, "Oper") == 0) value = ControlObject_getOper(controlObject); else if (strcmp(varName, "SBOw") == 0) value = ControlObject_getSBOw(controlObject); else if (strcmp(varName, "SBO") == 0) { if (controlObject->ctlModel == 2) { uint64_t currentTime = Hal_getTimeInMs(); value = controlObject->emptyString; checkSelectTimeout(controlObject, currentTime); if (getState(controlObject) == STATE_UNSELECTED) { CheckHandlerResult checkResult = CONTROL_ACCEPTED; if (controlObject->checkHandler != NULL) { /* perform operative tests */ checkResult = controlObject->checkHandler( controlObject->checkHandlerParameter, NULL, false, false, (ClientConnection) connection); } if (checkResult == CONTROL_ACCEPTED) { selectObject(controlObject, currentTime, connection); value = ControlObject_getSBO(controlObject); } } } else { if (DEBUG_IED_SERVER) printf("IED_SERVER: select not applicable for control model %i\n", controlObject->ctlModel); value = ControlObject_getSBO(controlObject); } } else if (strcmp(varName, "Cancel") == 0) value = ControlObject_getCancel(controlObject); else { value = MmsValue_getSubElement(ControlObject_getMmsValue(controlObject), ControlObject_getTypeSpec(controlObject), varName); } } else value = ControlObject_getMmsValue(controlObject); } return value; }