bool TinyAmixerControlValue::writeControl(struct mixer_ctl *mixerControl, size_t elementCount, std::string &error) { uint32_t elementNumber; // Write element // Go through all elements for (elementNumber = 0; elementNumber < elementCount; elementNumber++) { int32_t value; // Read data from blackboard (beware this code is OK on Little Endian machines only) value = fromBlackboard(); if (isDebugEnabled()) { info() << "Writing alsa element " << getControlName() << ", index " << elementNumber << " with value " << value; } // Write element int err; if ((err = mixer_ctl_set_value(mixerControl, elementNumber, value)) < 0) { error = "Failed to write value in mixer control: " + getControlName() + ": " + strerror(-err); return false; } } return true; }
bool TinyAmixerControlValue::readControl(struct mixer_ctl *mixerControl, size_t elementCount, std::string &error) { uint32_t elementNumber; // Read element // Go through all elements for (elementNumber = 0; elementNumber < elementCount; elementNumber++) { int32_t value; if ((value = mixer_ctl_get_value(mixerControl, elementNumber)) < 0) { error = "Failed to read value in mixer control: " + getControlName(); return false; } if (isDebugEnabled()) { info() << "Reading alsa element " << getControlName() << ", index " << elementNumber << " with value " << value; } toBlackboard(value); } return true; }
void TinyAmixerControlArray::logControlValues(bool receive, const void *array, uint32_t elementCount) const { const unsigned char *buffer = reinterpret_cast<const unsigned char *>(array); unsigned int idx; std::stringstream log; log << (receive ? "Reading" : "Writing"); log << " alsa element: " << getControlName() << " with value: "; displayAndCleanString(log); for (idx = 0; idx < elementCount; idx++) { log.width(2); log.fill('0'); // cast to uint16_t necessary in order to avoid 'buffer[idx]' to be // treated as a printable character, apparently log << hex << static_cast<unsigned short>(buffer[idx]) << " "; if ((idx != 0) && ((idx % maxLogLine) == 0)) { log << '\n'; displayAndCleanString(log); } } if (log.str().length() > 0) { log << '\n'; displayAndCleanString(log); } log << "[" << dec << elementCount << " bytes]" << endl; displayAndCleanString(log); }
QStringList ControllableDeviceList::getControlList() { QStringList reply; for (int i=0;i<deviceList.size();i++) { reply.append(getControlName(i)); } return reply; }
ofxWToggle & ofxWFrame::addToggle(const string & title, string controlName, string _style){ controlName=getControlName(controlName,title); ofxWToggle * toggle = new ofxWToggle(controlName); toggle->init(title,_style==""?style:_style); toggle->setPosition(getNextPosition()); addWidget(toggle,controlName); return *toggle; }
ofxWButton & ofxWFrame::addButton(const string & title, string controlName, string _style){ controlName=getControlName(controlName,title); ofxWButton * button = new ofxWButton(controlName); button->init(title,_style==""?style:_style); button->setPosition(getNextPosition()); addWidget(button,controlName); return *button; }
ofxW2DSlider & ofxWFrame::add2DSlider(const string & title, float xvalue, float yvalue, float xmin, float xmax, float ymin, float ymax, string controlName, const string & _style){ controlName=getControlName(controlName,title); ofxW2DSlider * slider = new ofxW2DSlider(controlName); slider->init(title,xvalue,yvalue,xmin,xmax,ymin,ymax,_style==""?style:_style); slider->setPosition(getNextPosition()); addWidget(slider,controlName); return *slider; }
ofxWSpinSlider & ofxWFrame::addSpinSlider(const string & title, float value, float min, float max, float step, string controlName, const string & _style){ controlName=getControlName(controlName,title); ofxWSpinSlider * slider = new ofxWSpinSlider(controlName); slider->init(title,value,min,max,step,_style==""?style:_style); slider->setPosition(getNextPosition()); addWidget(slider,controlName); return *slider; }
ofxWTextBox & ofxWFrame::addTextBox(const string & title, string text, string controlName, string _style){ controlName=getControlName(controlName,title); ofxWTextBox * textBox = new ofxWTextBox(controlName); textBox->init(title,_style==""?style:_style); textBox->setPosition(getNextPosition()); textBox->setText(text); addWidget(textBox,controlName); return *textBox; }
bool TinyAmixerControlArray::readControl(struct mixer_ctl *mixerControl, uint32_t elementCount, string &error) { int err; if ((err = getArrayMixer(mixerControl, elementCount)) < 0) { error = "Failed to read value in mixer control: " + getControlName() + ": " + strerror(-err); return false; } return true; }
int32_t CamConfig::readControlValue(uint32_t const id) { std::string control_name; getControlName(id, &control_name); LOG_DEBUG("CamConfig: readControlValue %s (%d)", control_name.c_str(), id); struct v4l2_control control; memset(&control, 0, sizeof(struct v4l2_control)); control.id = id; if (0 != ioctl (mFd, VIDIOC_G_CTRL, &control)) { std::string err_str(strerror(errno)); throw std::runtime_error(err_str.insert(0, "Could not read control object value: ")); } LOG_DEBUG("Control %s(0x%x(%d)) value: %d", control_name.c_str(), id, id, control.value); return control.value; }
ofxWidgetFps & ofxWFrame::addFps(string controlName){ controlName=getControlName(controlName,"fps"); ofxWidgetFps * fps = new ofxWidgetFps(controlName); /*fps->setEnabledStyle(buttonStyle); fps->setDisabledStyle(buttonStyle); fps->setFocusedStyle(buttonFocusedStyle); fps->setPressedStyle(buttonPressedStyle); fps->setOutStyle(buttonPressedStyle);*/ fps->setPosition(getNextPosition()); addWidget(fps,controlName); return *fps; }
void CamConfig::listControls() { std::map<uint32_t, struct CamCtrl>::iterator it; printf("CAMERA CONTROLS\n"); for(it = mCamCtrls.begin(); it != mCamCtrls.end(); it++) { struct v4l2_queryctrl* pq = &(it->second.mCtrl); std::string name; getControlName(it->first, &name); printf("0x%x(%d): %s, values: %d to %d (step %d), default: %d, current: %d, writeable: %s, readable: %s\n", pq->id, pq->id, name.c_str(), pq->minimum, pq->maximum, pq->step, pq->default_value, it->second.mValue, it->second.mWriteable ? "true" : "false", it->second.mReadable ? "true" : "false"); if(it->second.mMenuItems.size() > 0) { printf("\tMenu-Entries\n"); } for(unsigned int i=0; i < it->second.mMenuItems.size(); i++) { printf("\t%d: %s\n", i, it->second.mMenuItems[i].c_str()); } } printf("\n"); }
bool LegacyAmixerControl::accessHW(bool receive, string &error) { CAutoLog autoLog(getConfigurableElement(), "ALSA", isDebugEnabled()); #ifdef SIMULATION if (receive) { memset(getBlackboardLocation(), 0, getSize()); } log_info("%s ALSA Element Instance: %s\t\t(Control Element: %s)", receive ? "Reading" : "Writing", getConfigurableElement()->getPath().c_str(), getControlName().c_str()); return true; #endif int ret; // Mixer handle snd_ctl_t *sndCtrl; uint32_t value; uint32_t index; uint32_t elementCount; snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *control; logControlInfo(receive); // Check parameter type is ok (deferred error, no exceptions available :-() if (!isTypeSupported()) { error = "Parameter type not supported."; return false; } int cardNumber = getCardNumber(); if (cardNumber < 0) { error = "Card " + getCardName() + " not found. Error: " + strerror(cardNumber); return false; } #ifdef ANDROID if ((ret = snd_ctl_hw_open(&sndCtrl, NULL, cardNumber, 0)) < 0) { error = snd_strerror(ret); return false; } #else // Create device name ostringstream deviceName; deviceName << "hw:" << cardNumber; // Open sound control if ((ret = snd_ctl_open(&sndCtrl, deviceName.str().c_str(), 0)) < 0) { error = snd_strerror(ret); return false; } #endif // Allocate in stack snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_value_alloca(&control); // Set interface snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); string controlName = getControlName(); // Set name or id if (isdigit(controlName[0])) { snd_ctl_elem_id_set_numid(id, asInteger(controlName)); } else { snd_ctl_elem_id_set_name(id, controlName.c_str()); } // Init info id snd_ctl_elem_info_set_id(info, id); // Get info if ((ret = snd_ctl_elem_info(sndCtrl, info)) < 0) { error = "ALSA: Unable to get element info " + controlName + ": " + snd_strerror(ret); // Close sound control snd_ctl_close(sndCtrl); return false; } // Get type snd_ctl_elem_type_t eType = snd_ctl_elem_info_get_type(info); // Get element count elementCount = snd_ctl_elem_info_get_count(info); uint32_t scalarSize = getScalarSize(); // If size defined in the PFW different from alsa mixer control size, return an error if (elementCount * scalarSize != getSize()) { error = "ALSA: Control element count (" + asString(elementCount) + ") and configurable scalar element count (" + asString(getSize() / scalarSize) + ") mismatch"; // Close sound control snd_ctl_close(sndCtrl); return false; } // Set value id snd_ctl_elem_value_set_id(control, id); if (receive) { // Read element if ((ret = snd_ctl_elem_read(sndCtrl, control)) < 0) { error = "ALSA: Unable to read element " + controlName + ": " + snd_strerror(ret); // Close sound control snd_ctl_close(sndCtrl); return false; } // Go through all indexes for (index = 0; index < elementCount; index++) { switch (eType) { case SND_CTL_ELEM_TYPE_BOOLEAN: value = snd_ctl_elem_value_get_boolean(control, index); break; case SND_CTL_ELEM_TYPE_INTEGER: value = snd_ctl_elem_value_get_integer(control, index); break; case SND_CTL_ELEM_TYPE_INTEGER64: value = snd_ctl_elem_value_get_integer64(control, index); break; case SND_CTL_ELEM_TYPE_ENUMERATED: value = snd_ctl_elem_value_get_enumerated(control, index); break; case SND_CTL_ELEM_TYPE_BYTES: value = snd_ctl_elem_value_get_byte(control, index); break; default: error = "ALSA: Unknown control element type while reading alsa element " + controlName; return false; } if (isDebugEnabled()) { log_info("Reading alsa element %s, index %u with value %u", controlName.c_str(), index, value); } // Write data to blackboard (beware this code is OK on Little Endian machines only) toBlackboard(value); } } else { // Go through all indexes for (index = 0; index < elementCount; index++) { // Read data from blackboard (beware this code is OK on Little Endian machines only) value = fromBlackboard(); if (isDebugEnabled()) { log_info("Writing alsa element %s, index %u with value %u", controlName.c_str(), index, value); } switch (eType) { case SND_CTL_ELEM_TYPE_BOOLEAN: snd_ctl_elem_value_set_boolean(control, index, value); break; case SND_CTL_ELEM_TYPE_INTEGER: snd_ctl_elem_value_set_integer(control, index, value); break; case SND_CTL_ELEM_TYPE_INTEGER64: snd_ctl_elem_value_set_integer64(control, index, value); break; case SND_CTL_ELEM_TYPE_ENUMERATED: snd_ctl_elem_value_set_enumerated(control, index, value); break; case SND_CTL_ELEM_TYPE_BYTES: snd_ctl_elem_value_set_byte(control, index, value); break; default: error = "ALSA: Unknown control element type while writing alsa element " + controlName; return false; } } // Write element if ((ret = snd_ctl_elem_write(sndCtrl, control)) < 0) { error = "ALSA: Unable to write element " + controlName + ": " + snd_strerror(ret); // Close sound control snd_ctl_close(sndCtrl); return false; } } // Close sound control snd_ctl_close(sndCtrl); return true; }
bool TinyAmixerControl::accessHW(bool receive, std::string &error) { CAutoLog autoLog(getConfigurableElement(), "ALSA", isDebugEnabled()); // Mixer handle struct mixer *mixer; // Mixer control handle struct mixer_ctl *mixerControl; uint32_t elementCount; std::string controlName = getControlName(); // Debug conditionnaly enabled in XML logControlInfo(receive); // Check parameter type is ok (deferred error, no exceptions available :-() if (!isTypeSupported()) { error = "Parameter type not supported."; return false; } // Check card number int32_t cardIndex = getCardNumber(); if (cardIndex < 0) { error = "Card " + getCardName() + " not found. Error: " + strerror(-cardIndex); return false; } // Open alsa mixer // getMixerHandle is non-const; we need to forcefully remove the constness // then, we need to cast the generic subsystem into a TinyAlsaSubsystem. mixer = static_cast<TinyAlsaSubsystem *>( const_cast<CSubsystem *>(getSubsystem()))->getMixerHandle(cardIndex); if (!mixer) { error = "Failed to open mixer for card: " + getCardName(); return false; } // Get control handle if (isdigit(controlName[0])) { mixerControl = mixer_get_ctl(mixer, asInteger(controlName)); } else { mixerControl = mixer_get_ctl_by_name(mixer, controlName.c_str()); } // Check control has been found if (!mixerControl) { error = "Failed to open mixer control: " + controlName; return false; } // Get element count elementCount = getNumValues(mixerControl); uint32_t scalarSize = getScalarSize(); // Check available size if (elementCount * scalarSize != getSize()) { error = "ALSA: Control element count (" + asString(elementCount) + ") and configurable scalar element count (" + asString(getSize() / scalarSize) + ") mismatch"; return false; } // Read/Write element bool success; if (receive) { success = readControl(mixerControl, elementCount, error); } else { success = writeControl(mixerControl, elementCount, error); } return success; }
void CamConfig::writeControlValue(uint32_t const id, int32_t value, bool just_write) { std::string control_name; getControlName(id, &control_name); LOG_DEBUG("CamConfig: writeControlValue %s (%d) to %d", control_name.c_str(), id, value); struct v4l2_control control; control.id = id; control.value = value; // Problem setting control parameter V4L2_CID_WHITE_BALANCE_TEMPERATURE // on Microsoft LifeCam Cinema(TM), will be ignored. /* Should be handled by read/write only parameters. if(id == V4L2_CID_WHITE_BALANCE_TEMPERATURE) { LOG_WARN("Writing of control V4L2_CID_WHITE_BALANCE_TEMPERATURE is ignored!"); return; } */ std::map<uint32_t, struct CamCtrl>::iterator it; if(!just_write) { // Request internally stored control. it = mCamCtrls.find(id); // id unknown? if(it == mCamCtrls.end()) { throw std::runtime_error("Passed id unknown"); } // read-only control? if(!it->second.mWriteable) { std::stringstream ss; ss << "Writing is deactivated for control " << control_name << std::endl; throw std::runtime_error(ss.str().c_str()); } // Check borders. if(value < it->second.mCtrl.minimum) { LOG_INFO("Control %s (%d) value %d set to minimum %d", control_name.c_str(), id, value, it->second.mCtrl.minimum); control.value = it->second.mCtrl.minimum; } if(value > it->second.mCtrl.maximum) { LOG_INFO("Control %s (%d) value %d set to maximum %d", control_name.c_str(), id, value, it->second.mCtrl.maximum); control.value = it->second.mCtrl.maximum; } } if(0 == ioctl (mFd, VIDIOC_S_CTRL, &control)) { if(!just_write) { // Change internally stored value as well. it->second.mValue = value; } LOG_DEBUG("Control value %s (0x%x (%d)) set to %d", control_name.c_str(), id, id, value); } else { std::string err_str(strerror(errno)); // ID unknown? Should not happen or data would be out of sync. if(errno == EINVAL) { throw CamConfigException(err_str.insert(0, "VIDIOC_S_CTRL is not supported by device driver: ")); } // Some controls may only be changed in manual mode. This is not an error. if(mAutoManualDependentControlIds.find(id) != mAutoManualDependentControlIds.end()) { LOG_WARN("Control value %s (0x%x (%d)) cannot be changed, auto-mode active?", control_name.c_str(), id, id); } else { throw std::runtime_error(err_str.insert(0, "Could not write control object: ")); } } }