<commit_before>/*
 * This file is part of openfx-arena <https://github.com/olear/openfx-arena>,
 * Copyright (C) 2016 INRIA
 *
 * openfx-arena is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 * openfx-arena is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with openfx-arena.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
*/

#include "MagickPlugin.h"
#include <iostream>

MagickPluginHelperBase::MagickPluginHelperBase(OfxImageEffectHandle handle)
    : ImageEffect(handle)
    , _dstClip(0)
    , _srcClip(0)
    , _enableMP(0)
    , _matte(0)
    , _vpixel(0)
{
    _dstClip = fetchClip(kOfxImageEffectOutputClipName);
    assert(_dstClip && _dstClip->getPixelComponents() == OFX::ePixelComponentRGBA);
    _srcClip = fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert(_srcClip && _srcClip->getPixelComponents() == OFX::ePixelComponentRGBA);

    _enableMP = fetchBooleanParam(kParamOpenMP);
    _matte = fetchBooleanParam(kParamMatte);
    _vpixel = fetchChoiceParam(kParamVPixel);
    assert(_enableMP && _matte && _vpixel);
}

void
MagickPluginHelperBase::changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName)
{
    if (!_renderscale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    clearPersistentMessage();
}

OFX::PageParamDescriptor*
MagickPluginHelperBase::describeInContextBegin(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum /*context*/)
{
    OFX::ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(OFX::ePixelComponentRGBA);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(false);
    srcClip->setIsMask(false);

    OFX::ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(OFX::ePixelComponentRGBA);
    dstClip->setSupportsTiles(false);

    std::string features = MagickCore::GetMagickFeatures();
    if (features.find("OpenMP") != std::string::npos) {
        _hasMP = true;
    }

    OFX::PageParamDescriptor *page = desc.definePageParam("Controls");
    {
        OFX::BooleanParamDescriptor *param = desc.defineBooleanParam(kParamOpenMP);
        param->setLabel(kParamOpenMPLabel);
        param->setHint(kParamOpenMPHint);
        param->setDefault(kParamOpenMPDefault);
        param->setAnimates(false);
        if (!_hasMP) {
            param->setEnabled(false);
        }
        if (page) {
            page->addChild(*param);
        }
    }
    {
        OFX::BooleanParamDescriptor *param = desc.defineBooleanParam(kParamMatte);
        param->setLabel(kParamMatteLabel);
        param->setHint(kParamMatteHint);
        param->setDefault(kParamMatteDefault);
        param->setAnimates(false);
        if (page) {
            page->addChild(*param);
        }
    }
    {
        OFX::ChoiceParamDescriptor *param = desc.defineChoiceParam(kParamVPixel);
        param->setLabel(kParamVPixelLabel);
        param->setHint(kParamVPixelHint);
        param->appendOption("Undefined");
        param->appendOption("Background");
        param->appendOption("Black");
        param->appendOption("CheckerTile");
        param->appendOption("Dither");
        param->appendOption("Edge");
        param->appendOption("Gray");
        param->appendOption("HorizontalTile");
        param->appendOption("HorizontalTileEdge");
        param->appendOption("Mirror");
        param->appendOption("Random");
        param->appendOption("Tile");
        param->appendOption("Transparent");
        param->appendOption("VerticalTile");
        param->appendOption("VerticalTileEdge");
        param->appendOption("White");
        param->setDefault(kParamVPixelDefault);
        param->setAnimates(false);
        param->setLayoutHint(OFX::eLayoutHintDivider);
        if (page) {
            page->addChild(*param);
        }
    }
    return page;
}

void
MagickPluginHelperBase::describeInContextEnd(OFX::ImageEffectDescriptor &/*desc*/, OFX::ContextEnum /*context*/, OFX::PageParamDescriptor* /*page*/)
{
}
<commit_msg>MagickPlugin: minor<commit_after>/*
 * This file is part of openfx-arena <https://github.com/olear/openfx-arena>,
 * Copyright (C) 2016 INRIA
 *
 * openfx-arena is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 * openfx-arena is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with openfx-arena.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
*/

#include "MagickPlugin.h"
#include <iostream>

MagickPluginHelperBase::MagickPluginHelperBase(OfxImageEffectHandle handle)
    : ImageEffect(handle)
    , _dstClip(0)
    , _srcClip(0)
    , _enableMP(0)
    , _matte(0)
    , _vpixel(0)
{
    _dstClip = fetchClip(kOfxImageEffectOutputClipName);
    assert(_dstClip && _dstClip->getPixelComponents() == OFX::ePixelComponentRGBA);
    _srcClip = fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert(_srcClip && _srcClip->getPixelComponents() == OFX::ePixelComponentRGBA);

    _enableMP = fetchBooleanParam(kParamOpenMP);
    _matte = fetchBooleanParam(kParamMatte);
    _vpixel = fetchChoiceParam(kParamVPixel);
    assert(_enableMP && _matte && _vpixel);
}

void
MagickPluginHelperBase::changedParam(const OFX::InstanceChangedArgs &args, const std::string &/*paramName*/)
{
    if (!_renderscale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    clearPersistentMessage();
}

OFX::PageParamDescriptor*
MagickPluginHelperBase::describeInContextBegin(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum /*context*/)
{
    OFX::ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(OFX::ePixelComponentRGBA);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(false);
    srcClip->setIsMask(false);

    OFX::ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(OFX::ePixelComponentRGBA);
    dstClip->setSupportsTiles(false);

    std::string features = MagickCore::GetMagickFeatures();
    if (features.find("OpenMP") != std::string::npos) {
        _hasMP = true;
    }

    OFX::PageParamDescriptor *page = desc.definePageParam("Controls");
    {
        OFX::BooleanParamDescriptor *param = desc.defineBooleanParam(kParamOpenMP);
        param->setLabel(kParamOpenMPLabel);
        param->setHint(kParamOpenMPHint);
        param->setDefault(kParamOpenMPDefault);
        param->setAnimates(false);
        if (!_hasMP) {
            param->setEnabled(false);
        }
        if (page) {
            page->addChild(*param);
        }
    }
    {
        OFX::BooleanParamDescriptor *param = desc.defineBooleanParam(kParamMatte);
        param->setLabel(kParamMatteLabel);
        param->setHint(kParamMatteHint);
        param->setDefault(kParamMatteDefault);
        param->setAnimates(false);
        if (page) {
            page->addChild(*param);
        }
    }
    {
        OFX::ChoiceParamDescriptor *param = desc.defineChoiceParam(kParamVPixel);
        param->setLabel(kParamVPixelLabel);
        param->setHint(kParamVPixelHint);
        param->appendOption("Undefined");
        param->appendOption("Background");
        param->appendOption("Black");
        param->appendOption("CheckerTile");
        param->appendOption("Dither");
        param->appendOption("Edge");
        param->appendOption("Gray");
        param->appendOption("HorizontalTile");
        param->appendOption("HorizontalTileEdge");
        param->appendOption("Mirror");
        param->appendOption("Random");
        param->appendOption("Tile");
        param->appendOption("Transparent");
        param->appendOption("VerticalTile");
        param->appendOption("VerticalTileEdge");
        param->appendOption("White");
        param->setDefault(kParamVPixelDefault);
        param->setAnimates(false);
        param->setLayoutHint(OFX::eLayoutHintDivider);
        if (page) {
            page->addChild(*param);
        }
    }
    return page;
}

void
MagickPluginHelperBase::describeInContextEnd(OFX::ImageEffectDescriptor &/*desc*/, OFX::ContextEnum /*context*/, OFX::PageParamDescriptor* /*page*/)
{
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>
#include <string>

#include "boost/filesystem.hpp"

#include "SettingsController.h"

using std::cerr;
using std::getenv;
using std::string;

using namespace boost::filesystem;

void CheckCreatePath(path p) {
	if (!exists(p)) {
		if(!create_directory(p)) {
			cerr << "Could not create '" << p << "'.\n";
			exit(1);
		}
	}
}

void SettingsController::load(path c, path d) {
	char* p;

	p = getenv("HOME");
	if(p)
		home = path(p);
	else {
		cerr << "Could not read $HOME\n";
		exit(1);
	}

	if(c.empty()) {
		p = getenv("XDG_CONFIG_HOME");
		if(!p) {
			config = path(home);
			config /= ".config";
			CheckCreatePath(config);
		}

		config /= "videocrumb";
		CheckCreatePath(config);
	}
	else
		config = c;

	if(d.empty()) {
		p = getenv("XDG_DATA_HOME");
		if(!p) {
			data = path(home);
			data /= ".local";
			CheckCreatePath(data);

			data /= "share";
			CheckCreatePath(data);
		}
		else {
			data = p;
		}

		data /= "videocrumb";
		CheckCreatePath(data);

		db = path(data);
		data /= "dbnew";
		db /= "db.sqlite";
	}
	else
		data = d;
}
<commit_msg>Settings: Style fix and make sure we use XDG_CONFIG_HOME<commit_after>#include <cstdlib>
#include <iostream>
#include <string>

#include "boost/filesystem.hpp"

#include "SettingsController.h"

using std::cerr;
using std::getenv;
using std::string;

using namespace boost::filesystem;

void CheckCreatePath(path p) {
	if (!exists(p)) {
		if(!create_directory(p)) {
			cerr << "Could not create '" << p << "'.\n";
			exit(1);
		}
	}
}

void SettingsController::load(path c, path d) {
	char* p;

	p = getenv("HOME");
	if(p)
		home = path(p);
	else {
		cerr << "Could not read $HOME\n";
		exit(1);
	}

	if(c.empty()) {
		p = getenv("XDG_CONFIG_HOME");
		if(!p) {
			config = path(home);
			config /= ".config";
			CheckCreatePath(config);
		}
		else
			config = p;

		config /= "videocrumb";
		CheckCreatePath(config);
	}
	else
		config = c;

	if(d.empty()) {
		p = getenv("XDG_DATA_HOME");
		if(!p) {
			data = path(home);
			data /= ".local";
			CheckCreatePath(data);

			data /= "share";
			CheckCreatePath(data);
		}
		else
			data = p;

		data /= "videocrumb";
		CheckCreatePath(data);

		db = path(data);
		data /= "dbnew";
		db /= "db.sqlite";
	}
	else
		data = d;
}
<|endoftext|>


<commit_before>#include "powerSleep.h"

#include <Arduino.h>
#include <avr/sleep.h>
#include <avr/power.h>

void enterSleep()
{
  /*** Setup Sleep options ***/

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // Lowest powerdown mode
  sleep_enable();                       // Enable sleep

  /*** Put processor to sleep ***/

  sleep_mode();

  /*** Continue ***/

  sleep_disable();

  return;
}
void disableUnneededPeripherals()
{
  /*** Disable Uneeded Peripherals ***/
  ADCSRA = 0;   // Disable ADC
  power_adc_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();
  power_usart0_disable();
  power_spi_disable();

  return;
}

void serialPowerUp()
{
  power_usart0_enable();
  Serial.begin(9600);
  while(!Serial);
  Serial.print(F(">> Logger: Logger ready.\n>> User:   "));

  return;
}

void serialPowerDown()
{
  power_usart0_disable();

  return;
}

void SDPowerUp()
{
  power_spi_enable();
  digitalWrite(4, LOW);

  return;
}

void SDPowerDown()
{
  digitalWrite(4, HIGH);
  power_spi_disable();

  return;
}
<commit_msg>Update powerSleep.cpp<commit_after>#include "powerSleep.h"

#include <Arduino.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <avr/power.h>

/***************************************\
 * Function Name: enterSleep()
 * Purpose:       Put the controller to
 *                "sleep" (low-power).
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *   Setup sleep options
 *   Put processor to sleep
 *   Continue on wake-up
 *   Return
\***************************************/

void enterSleep()
{
  /*** Setup Sleep options ***/

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // Lowest powerdown mode
  sleep_enable();                       // Enable sleep

  /*** Put processor to sleep ***/

  sleep_mode();

  /*** Continue ***/

  sleep_disable();

  return;
}

/**********************************************\
 * Function Name: disableUnneededPeripherals
 * Purpose:       Cut all power to peripherals
 *                to save battery life. Some
 *                will be turned on again
 *                temporarily.
 * Inputs:        None
 * Outputs:       None
 * Pseudocode:
 *   Disable ADC
 *   Disable Timer0
 *   Disable Timer1
 *   Disable Timer2
 *   Disable TWI
 *   Disable USART0
 *   Disable SPI
 *   Return
\**********************************************/

void disableUnneededPeripherals()
{
  /*** Disable Uneeded Peripherals ***/
  ADCSRA = 0;   // Disable ADC
  power_adc_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();
  power_usart0_disable();
  power_spi_disable();

  return;
}

/**********************************\
 * Function Name: twiPowerUp()
 * Purpose:       Enable power to
 *                the TWI interface
 *                when needed.
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *  Power on the TWI interface
 *  Initialize the TWI class
 *  Return
\**********************************/

void twiPowerUp()
{
  power_twi_enable();
  Wire.begin();

  return;
}

/**********************************\
 * Function Name: twiPowerDown()
 * Purpose:       Disable power to
 *                the TWI interface
 *                when finished.
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *  Power down the TWI interface
 *  Return
\**********************************/

void twiPowerDown()
{
  power_twi_disable();

  return;
}

/*************************************\
 * Function Name: serialPowerUp()
 * Purpose:       Enable power to
 *                the serial interface
 *                when needed.
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *  Power on the serial interface
 *  Pause 10 miliseconds
 *  Initialize Serial at 9600 Baud
 *  Pause 10 miliseconds
 *  Prompt user
 *  Return
\*************************************/

void serialPowerUp()
{
  power_usart0_enable();
  _delay_ms(10);
  Serial.begin(9600);
  _delay_ms(10);
  Serial.print(F(">> Logger: Logger ready.\n>> User:   "));

  return;
}

/*************************************\
 * Function Name: serialPowerDown()
 * Purpose:       Disable power to
 *                the serial interface
 *                when finished.
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *  Power down the serial interface
 *  Return
\*************************************/

void serialPowerDown()
{
  power_usart0_disable();

  return;
}

/**********************************\
 * Function Name: SDPowerUp()
 * Purpose:       Enable power to
 *                the SD Card when
 *                needed.
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *  Power on the SPI interface
 *  Enable power to the SD Card
 *  Return
\**********************************/

void SDPowerUp()
{
  power_spi_enable();
  digitalWrite(4, LOW);

  return;
}

/**********************************\
 * Function Name: SDPowerDown()
 * Purpose:       Disable power to
 *                the SD Card when
 *                finished.
 * Inputs:        None
 * Outputs:       None
 * Psuedocode:
 *  Cut power to the SD Card
 *  Power down the SPI interface
 *  Return
\**********************************/

void SDPowerDown()
{
  digitalWrite(4, HIGH);  // Cut power to the SD Card
  power_spi_disable();    // Power down the SPI interface

  return;
}
<|endoftext|>


<commit_before><commit_msg>VAAPI: disable VP8 decoding for now<commit_after><|endoftext|>


<commit_before>#include "stdafx.h"
#include "SettingsUI.h"
#include "Hotkeys.h"
#include "afxdialogex.h"

#include "HotkeyInfo.h"
#include "HotkeyPrompt.h"
#include "KeyGrabber.h"

IMPLEMENT_DYNAMIC(Hotkeys, CPropertyPage)

Hotkeys::Hotkeys() :
CPropertyPage(Hotkeys::IDD) {

}

Hotkeys::~Hotkeys() {
}

void Hotkeys::DoDataExchange(CDataExchange* pDX)
{
    CPropertyPage::DoDataExchange(pDX);
    DDX_Control(pDX, LST_KEYS, _list);
    DDX_Control(pDX, BTN_KEYS, _keys);
    DDX_Control(pDX, CMB_ACTION, _action);
}

BOOL Hotkeys::OnInitDialog() {
    CPropertyPage::OnInitDialog();

    DWORD exStyle = _list.GetExtendedStyle();
    exStyle |= LVS_EX_FULLROWSELECT;
    _list.SetExtendedStyle(exStyle);

    /* Set up listview */
    RECT r;
    _list.GetWindowRect(&r);
    int width = r.right - r.left;

    _list.InsertColumn(0, L"Hotkeys", NULL, (int) (width * .485));
    _list.InsertColumn(1, L"Action", NULL, (int) (width * .445));

    /* Set up editor area */
    for (std::wstring action : HotkeyInfo::ActionNames) {
        _action.AddString(action.c_str());
    }

    HotkeyInfo hi;
    hi.action = HotkeyInfo::DecreaseVolume;
    hi.keyCombination = 3262;
    _keyInfo.push_back(hi);

    for (HotkeyInfo hi : _keyInfo) {
        std::wstring hkStr = HotkeyManager::HotkeysToString(hi.keyCombination);
        _list.InsertItem(0, hkStr.c_str());
        _list.SetItemText(0, 1, HotkeyInfo::ActionNames[hi.action].c_str());
    }

    SelectItem(0);

    return TRUE;
}

void Hotkeys::SelectItem(int idx) {
    /* First unselect the selected item (not strictly necessary in our case) */
    int sel = _list.GetSelectionMark();
    if (sel >= 0) {
        _list.SetItemState(sel, ~LVIS_SELECTED, LVIS_SELECTED);
    }

    /* Make sure we're not selecting something out of range */
    if (idx < 0) {
        idx = 0;
    }
    int numItems = _list.GetItemCount();
    if (idx > numItems - 1) {
        idx = numItems - 1;
    }

    /* Select the item */
    _list.SetItemState(idx, LVIS_SELECTED, LVIS_SELECTED);
    _list.SetSelectionMark(idx);

    /* Scroll down to the item, if necessary */
    _list.EnsureVisible(idx, FALSE);
}

BEGIN_MESSAGE_MAP(Hotkeys, CPropertyPage)
    ON_BN_CLICKED(BTN_ADD, &Hotkeys::OnBnClickedAdd)
    ON_BN_CLICKED(BTN_REMOVE, &Hotkeys::OnBnClickedRemove)
    ON_NOTIFY(LVN_ITEMCHANGED, LST_KEYS, &Hotkeys::OnLvnItemchangedKeys)
    ON_BN_CLICKED(BTN_KEYS, &Hotkeys::OnBnClickedKeys)
END_MESSAGE_MAP()

void Hotkeys::OnBnClickedAdd() {
    int items = _list.GetItemCount();
    for (int i = 0; i < items; ++i) {
        if (_list.GetItemText(i, 0) == L""
            && _list.GetItemText(i, 1) == L"") {
            /* We found a blank item already in the list */
            SelectItem(i);
            return;
        }
    }

    HotkeyInfo hi;
    _keyInfo.push_back(hi);
    int idx = _list.InsertItem(items, L"");
    _list.SetItemText(idx, 1, L"");
    SelectItem(idx);
}

void Hotkeys::OnBnClickedRemove() {
    _keyInfo.erase(_keyInfo.begin() + _selIdx);
    _list.DeleteItem(_selIdx);

    /* Select the item closest to the previous selection: */
    SelectItem(_selIdx);
}

void Hotkeys::OnLvnItemchangedKeys(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

    if (pNMLV->uChanged & LVIF_STATE) {
        if (pNMLV->uNewState & LVIS_SELECTED) {
            int sel = pNMLV->iItem;
            OutputDebugString(std::to_wstring(sel).c_str());
            OutputDebugString(L"\n");
        }
    }

    *pResult = 0;
}

void Hotkeys::OnBnClickedKeys() {
    HotkeyPrompt hkp;
    hkp.DoModal();
    int keyCombo = KeyGrabber::Instance()->KeyCombination();
    if (keyCombo > 0) {
        std::wstring keyStr = HotkeyManager::HotkeysToString(keyCombo);
        _keys.SetWindowText(keyStr.c_str());
    }
}

void Hotkeys::OnCbnSelchangeAction() {
    _keyInfo[_selIdx].action = _action.GetCurSel();
    LoadSelection(_selIdx);
}
<commit_msg>Add LoadSelection() - loads HotkeyInfo data when items selected<commit_after>#include "stdafx.h"
#include "SettingsUI.h"
#include "Hotkeys.h"
#include "afxdialogex.h"

#include "HotkeyInfo.h"
#include "HotkeyPrompt.h"
#include "KeyGrabber.h"

IMPLEMENT_DYNAMIC(Hotkeys, CPropertyPage)

Hotkeys::Hotkeys() :
CPropertyPage(Hotkeys::IDD) {

}

Hotkeys::~Hotkeys() {
}

void Hotkeys::DoDataExchange(CDataExchange* pDX)
{
    CPropertyPage::DoDataExchange(pDX);
    DDX_Control(pDX, LST_KEYS, _list);
    DDX_Control(pDX, BTN_KEYS, _keys);
    DDX_Control(pDX, CMB_ACTION, _action);
}

BOOL Hotkeys::OnInitDialog() {
    CPropertyPage::OnInitDialog();

    DWORD exStyle = _list.GetExtendedStyle();
    exStyle |= LVS_EX_FULLROWSELECT;
    _list.SetExtendedStyle(exStyle);

    /* Set up listview */
    RECT r;
    _list.GetWindowRect(&r);
    int width = r.right - r.left;

    _list.InsertColumn(0, L"Hotkeys", NULL, (int) (width * .485));
    _list.InsertColumn(1, L"Action", NULL, (int) (width * .445));

    /* Set up editor area */
    for (std::wstring action : HotkeyInfo::ActionNames) {
        _action.AddString(action.c_str());
    }

    HotkeyInfo hi;
    hi.action = HotkeyInfo::DecreaseVolume;
    hi.keyCombination = 3262;
    _keyInfo.push_back(hi);

    for (HotkeyInfo hi : _keyInfo) {
        std::wstring hkStr = HotkeyManager::HotkeysToString(hi.keyCombination);
        _list.InsertItem(0, hkStr.c_str());
        _list.SetItemText(0, 1, HotkeyInfo::ActionNames[hi.action].c_str());
    }

    SelectItem(0);

    return TRUE;
}

void Hotkeys::SelectItem(int idx) {
    /* First unselect the selected item (not strictly necessary in our case) */
    int sel = _list.GetSelectionMark();
    if (sel >= 0) {
        _list.SetItemState(sel, ~LVIS_SELECTED, LVIS_SELECTED);
    }

    /* Make sure we're not selecting something out of range */
    if (idx < 0) {
        idx = 0;
    }
    int numItems = _list.GetItemCount();
    if (idx > numItems - 1) {
        idx = numItems - 1;
    }

    /* Select the item */
    _list.SetItemState(idx, LVIS_SELECTED, LVIS_SELECTED);
    _list.SetSelectionMark(idx);

    /* Scroll down to the item, if necessary */
    _list.EnsureVisible(idx, FALSE);
}

void Hotkeys::LoadSelection(int idx) {
    HotkeyInfo current = _keyInfo[_selIdx];

    _keys.SetWindowText(L"");

    if (current.keyCombination > 0) {
        std::wstring keyStr
            = HotkeyManager::HotkeysToString(current.keyCombination);
        _keys.SetWindowText(keyStr.c_str());
        _list.SetItemText(_selIdx, 0, keyStr.c_str());
    }

    if (current.action >= 0) {
        _list.SetItemText(_selIdx, 1,
            HotkeyInfo::ActionNames[current.action].c_str());
    }
    _action.SetCurSel(current.action);
}
BEGIN_MESSAGE_MAP(Hotkeys, CPropertyPage)
    ON_BN_CLICKED(BTN_ADD, &Hotkeys::OnBnClickedAdd)
    ON_BN_CLICKED(BTN_REMOVE, &Hotkeys::OnBnClickedRemove)
    ON_NOTIFY(LVN_ITEMCHANGED, LST_KEYS, &Hotkeys::OnLvnItemchangedKeys)
    ON_BN_CLICKED(BTN_KEYS, &Hotkeys::OnBnClickedKeys)
END_MESSAGE_MAP()

void Hotkeys::OnBnClickedAdd() {
    int items = _list.GetItemCount();
    for (int i = 0; i < items; ++i) {
        if (_list.GetItemText(i, 0) == L""
            && _list.GetItemText(i, 1) == L"") {
            /* We found a blank item already in the list */
            SelectItem(i);
            return;
        }
    }

    HotkeyInfo hi;
    _keyInfo.push_back(hi);
    int idx = _list.InsertItem(items, L"");
    _list.SetItemText(idx, 1, L"");
    SelectItem(idx);
}

void Hotkeys::OnBnClickedRemove() {
    _keyInfo.erase(_keyInfo.begin() + _selIdx);
    _list.DeleteItem(_selIdx);

    /* Select the item closest to the previous selection: */
    SelectItem(_selIdx);
}

void Hotkeys::OnLvnItemchangedKeys(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

    if (pNMLV->uChanged & LVIF_STATE) {
        if (pNMLV->uNewState & LVIS_SELECTED) {
            int sel = pNMLV->iItem;
            OutputDebugString(std::to_wstring(sel).c_str());
            OutputDebugString(L"\n");
        }
    }

    *pResult = 0;
}

void Hotkeys::OnBnClickedKeys() {
    HotkeyPrompt hkp;
    hkp.DoModal();
    int keyCombo = KeyGrabber::Instance()->KeyCombination();
    if (keyCombo > 0) {
        std::wstring keyStr = HotkeyManager::HotkeysToString(keyCombo);
        _keys.SetWindowText(keyStr.c_str());
    }
}

void Hotkeys::OnCbnSelchangeAction() {
    _keyInfo[_selIdx].action = _action.GetCurSel();
    LoadSelection(_selIdx);
}
<|endoftext|>


<commit_before>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_WS_MAC
    ui->payToLayout->setSpacing(4);
#endif

#if QT_VERSION >= 0x040700
    ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if no label is filled in yet
    if(ui->addAsLabel->text().isEmpty())
        ui->addAsLabel->setText(model->getAddressTableModel()->labelForAddress(address));}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;
    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    if(model && model->getOptionsModel())
    {
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if(!ui->payAmount->validate())
    {
        retval = false;
    }
    else
    {
        if(ui->payAmount->value() <= 0)
        {
            // Cannot send 0 coins or less
            ui->payAmount->setValid(false);
            retval = false;
        }
    }

    if(!ui->payTo->hasAcceptableInput() ||
       (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    SendCoinsRecipient rv;

    rv.address = ui->payTo->text();
    rv.label = ui->addAsLabel->text();
    rv.amount = ui->payAmount->value();

    return rv;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

<commit_msg>Set label when selecting an address that already has a label. Fixes #1080.<commit_after>#include "sendcoinsentry.h"
#include "ui_sendcoinsentry.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "addressbookpage.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h"

#include <QApplication>
#include <QClipboard>

SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::SendCoinsEntry),
    model(0)
{
    ui->setupUi(this);

#ifdef Q_WS_MAC
    ui->payToLayout->setSpacing(4);
#endif

#if QT_VERSION >= 0x040700
    ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
    ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
#endif
    setFocusPolicy(Qt::TabFocus);
    setFocusProxy(ui->payTo);

    GUIUtil::setupAddressWidget(ui->payTo, this);
}

SendCoinsEntry::~SendCoinsEntry()
{
    delete ui;
}

void SendCoinsEntry::on_pasteButton_clicked()
{
    // Paste text from clipboard into recipient field
    ui->payTo->setText(QApplication::clipboard()->text());
}

void SendCoinsEntry::on_addressBookButton_clicked()
{
    if(!model)
        return;
    AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
    dlg.setModel(model->getAddressTableModel());
    if(dlg.exec())
    {
        ui->payTo->setText(dlg.getReturnValue());
        ui->payAmount->setFocus();
    }
}

void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
    if(!model)
        return;
    // Fill in label from address book, if address has an associated label
    QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
    if(!associatedLabel.isEmpty())
        ui->addAsLabel->setText(associatedLabel);
}

void SendCoinsEntry::setModel(WalletModel *model)
{
    this->model = model;
    clear();
}

void SendCoinsEntry::setRemoveEnabled(bool enabled)
{
    ui->deleteButton->setEnabled(enabled);
}

void SendCoinsEntry::clear()
{
    ui->payTo->clear();
    ui->addAsLabel->clear();
    ui->payAmount->clear();
    ui->payTo->setFocus();
    if(model && model->getOptionsModel())
    {
        ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
    }
}

void SendCoinsEntry::on_deleteButton_clicked()
{
    emit removeEntry(this);
}

bool SendCoinsEntry::validate()
{
    // Check input validity
    bool retval = true;

    if(!ui->payAmount->validate())
    {
        retval = false;
    }
    else
    {
        if(ui->payAmount->value() <= 0)
        {
            // Cannot send 0 coins or less
            ui->payAmount->setValid(false);
            retval = false;
        }
    }

    if(!ui->payTo->hasAcceptableInput() ||
       (model && !model->validateAddress(ui->payTo->text())))
    {
        ui->payTo->setValid(false);
        retval = false;
    }

    return retval;
}

SendCoinsRecipient SendCoinsEntry::getValue()
{
    SendCoinsRecipient rv;

    rv.address = ui->payTo->text();
    rv.label = ui->addAsLabel->text();
    rv.amount = ui->payAmount->value();

    return rv;
}

QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
{
    QWidget::setTabOrder(prev, ui->payTo);
    QWidget::setTabOrder(ui->payTo, ui->addressBookButton);
    QWidget::setTabOrder(ui->addressBookButton, ui->pasteButton);
    QWidget::setTabOrder(ui->pasteButton, ui->deleteButton);
    QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
    return ui->payAmount->setupTabChain(ui->addAsLabel);
}

void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{
    ui->payTo->setText(value.address);
    ui->addAsLabel->setText(value.label);
    ui->payAmount->setValue(value.amount);
}

bool SendCoinsEntry::isClear()
{
    return ui->payTo->text().isEmpty();
}

void SendCoinsEntry::setFocus()
{
    ui->payTo->setFocus();
}

<|endoftext|>


<commit_before>// FRAGMENT(includes)
#include <iostream>

#include <seqan/sequence.h>
#include <seqan/file.h>
#include <seqan/stream.h>

using namespace seqan;

// FRAGMENT(tags)
struct BlastnTab_;
typedef Tag<BlastnTab_> BlastnTab;

struct BlastnTabComment_;
typedef Tag<BlastnTabComment_> BlastnTabComment;

struct BlastnTabAlignment_;
typedef Tag<BlastnTabAlignment_> BlastnTabAlignment;

// FRAGMENT(record)
struct BlastnTabAlignmentRecord
{
    CharString queryName;
    CharString subjectName;
    double identity;
    unsigned alignmentLength;
    unsigned mismatches;
    unsigned gapOpens;
    unsigned queryBegin;
    unsigned queryEnd;
    unsigned subjectBegin;
    unsigned subjectEnd;
    double eValue;
    double bitScore;

    BlastnTabAlignmentRecord() :
            identity(0), alignmentLength(0), mismatches(0), gapOpens(0),
            queryBegin(0), queryEnd(0), subjectBegin(0), subjectEnd(0),
            eValue(0), bitScore(0)
    {}
};

template <typename TStream>
int write(TStream & stream, BlastnTabAlignmentRecord & record)
{
    streamPut(stream, "query name: ");
    streamPut(stream, record.queryName);
    streamPut(stream, "\nsubject name: ");
    streamPut(stream, record.subjectName);
    streamPut(stream, "\nidentity: ");
    streamPut(stream, record.identity);
    streamPut(stream, "\nalignment length: ");
    streamPut(stream, record.alignmentLength);
    streamPut(stream, "\nmismatches: ");
    streamPut(stream, record.mismatches);
    streamPut(stream, "\ngap opens: ");
    streamPut(stream, record.gapOpens);
    streamPut(stream, "\nquery begin: ");
    streamPut(stream, record.queryBegin);
    streamPut(stream, "\nquery end: ");
    streamPut(stream, record.queryEnd);
    streamPut(stream, "\nsubject begin: ");
    streamPut(stream, record.subjectBegin);
    streamPut(stream, "\nsubject end: ");
    streamPut(stream, record.subjectEnd);
    streamPut(stream, "\nevalue: ");
    streamPut(stream, record.eValue);
    streamPut(stream, "\nbit score: ");
    streamPut(stream, record.bitScore);
    int res = streamPut(stream, "\n\n");
    return res;
}

void clear(BlastnTabAlignmentRecord & record)
{
    clear(record.queryName);
    clear(record.subjectName);
}

// FRAGMENT(next-is)
template <typename TStream, typename TSpec>
inline bool
nextIs(RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabComment const & /*tag*/)
{
    return !atEnd(reader) && value(reader) == '#';
}

template <typename TStream, typename TSpec>
inline bool
nextIs(RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabAlignment const & /*tag*/)
{
    return !atEnd(reader) && value(reader) != '#';
}

// FRAGMENT(read-record)
template <typename TCharSequence, typename TStream, typename TSpec>
inline int
readRecord(TCharSequence & buffer, RecordReader<TStream, SinglePass<TSpec> > const & reader, BlastnTabComment const & /*tag*/)
{
    SEQAN_ASSERT(nextIs(reader, BlastnTabComment()));
    clear(buffer);
    return readLine(buffer, reader);
}

/*
 // FRAGMENT(record)
 struct BlastnTabAlignmentRecord
 {
 unsigned alignmentLength;
 unsigned mismatches;
 unsigned gapOpens;
 unsigned queryBegin;
 unsigned queryEnd;
 unsigned subjectBegin;
 unsigned subjectEnd;
*/

template <typename TStream, typename TSpec>
inline bool
readRecord(BlastnTabAlignmentRecord & record, RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabAlignment const & /*tag*/)
{
    SEQAN_ASSERT(nextIs(reader, BlastnTabAlignment()));
    int res = 0;
    CharString buffer;
    clear(record);

    // Read query name.
    res = readUntilChar(record.queryName, reader, '\t');
    if (res != 0)
        return res;
    goNext(reader);

    // Read subject name.
    res = readUntilChar(record.subjectName, reader, '\t');
    if (res != 0)
        return res;
    goNext(reader);

    // Read identity.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<double>(record.identity, buffer))
        return 1;  // Could not cast identity to double.
    goNext(reader);

    // Read alignment length.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.alignmentLength, buffer))
        return 1;  // Could not cast alignment length to unsigned.
    goNext(reader);

    // Read mismatches.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.mismatches, buffer))
        return 1;  // Could not cast mismatches to unsigned.
    goNext(reader);

    // Read gap opens.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.gapOpens, buffer))
        return 1;  // Could not cast gap opens to unsigned.
    goNext(reader);

    // Read query begin.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.queryBegin, buffer))
        return 1;  // Could not cast query begin to unsigned.
    goNext(reader);

    // Read query end.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.queryEnd, buffer))
        return 1;  // Could not cast query end to unsigned.
    goNext(reader);

    // Read subject begin.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.subjectBegin, buffer))
        return 1;  // Could not cast subject begin to unsigned.
    goNext(reader);

    // Read subject end.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.subjectEnd, buffer))
        return 1;  // Could not cast subject end to unsigned.
    goNext(reader);

    // Read evalue.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<double>(record.eValue, buffer))
        return 1;  // Could not cast evalue to double.
    goNext(reader);

    // Read bit score, up to end of the line.
    clear(buffer);
    res = readLine(buffer, reader);
    if (res != 0)
        return res;
    if (!lexicalCast2<double>(record.bitScore, buffer))
        return 1;  // Could not cast bit score to double.

    return 0;
}

// FRAGMENT(skip-record)
template <typename TStream, typename TSpec>
inline int
skipRecord(RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabComment const & /*tag*/)
{
    return skipLine(reader);
}

template <typename TStream, typename TPass>
inline int
skipRecord(RecordReader<TStream, TPass> & reader, BlastnTabAlignment const & /*tag*/)
{
    return skipLine(reader);
}

// FRAGMENT(batch-read)
template <typename TBlastnTabRecords, typename TStream, typename TSpec>
int read(TBlastnTabRecords & records, RecordReader<TStream, SinglePass<TSpec> > & reader)
{
    BlastnTabAlignmentRecord record;
    while (!atEnd(reader))
    {
        if (nextIs(reader, BlastnTabComment()))
        {
            skipRecord(reader, BlastnTabComment());
            continue;
        }
        if (!nextIs(reader, BlastnTabAlignment()))
            return 1;
        if (readRecord(record, reader, BlastnTabAlignment()) != 0)
            return 1;
        appendValue(records, record);
    }
    return 0;
}

// FRAGMENT(main)
int main(int argc, char const ** argv)
{
    // Process command line arguments, open file.
    if (argc != 2)
    {
        std::cerr << "Incorrect argument count!" << std::endl;
        std::cerr << "USAGE: tutorial_parse_blastn INPUT.txt" << std::endl;
        return 1;
    }
    std::fstream stream(argv[1], std::ios::binary | std::ios::in);
    if (!stream.good())
    {
        std::cerr << "Could not open file " << argv[1] << std::endl;
        return 1;
    }

    // Read file.
    RecordReader<std::fstream, SinglePass<> > reader(stream);
    String<BlastnTabAlignmentRecord> records;
    int res = read(records, reader);
    if (res != 0)
    {
        std::cerr << "Could not read BLASTN records." << std::endl;
        return 1;
    }

    // Write read records.
    for (unsigned i = 0; i < length(records); ++i)
        write(std::cout, records[i]);

    return 0;
}
<commit_msg>Fixing some comments in parse_blastn.cpp demo.<commit_after>// FRAGMENT(includes)
#include <iostream>

#include <seqan/sequence.h>
#include <seqan/file.h>
#include <seqan/stream.h>

using namespace seqan;

// FRAGMENT(tags)
struct BlastnTab_;
typedef Tag<BlastnTab_> BlastnTab;

struct BlastnTabComment_;
typedef Tag<BlastnTabComment_> BlastnTabComment;

struct BlastnTabAlignment_;
typedef Tag<BlastnTabAlignment_> BlastnTabAlignment;

// FRAGMENT(record)
struct BlastnTabAlignmentRecord
{
    CharString queryName;
    CharString subjectName;
    double identity;
    unsigned alignmentLength;
    unsigned mismatches;
    unsigned gapOpens;
    unsigned queryBegin;
    unsigned queryEnd;
    unsigned subjectBegin;
    unsigned subjectEnd;
    double eValue;
    double bitScore;

    BlastnTabAlignmentRecord() :
            identity(0), alignmentLength(0), mismatches(0), gapOpens(0),
            queryBegin(0), queryEnd(0), subjectBegin(0), subjectEnd(0),
            eValue(0), bitScore(0)
    {}
};

template <typename TStream>
int write(TStream & stream, BlastnTabAlignmentRecord & record)
{
    streamPut(stream, "query name: ");
    streamPut(stream, record.queryName);
    streamPut(stream, "\nsubject name: ");
    streamPut(stream, record.subjectName);
    streamPut(stream, "\nidentity: ");
    streamPut(stream, record.identity);
    streamPut(stream, "\nalignment length: ");
    streamPut(stream, record.alignmentLength);
    streamPut(stream, "\nmismatches: ");
    streamPut(stream, record.mismatches);
    streamPut(stream, "\ngap opens: ");
    streamPut(stream, record.gapOpens);
    streamPut(stream, "\nquery begin: ");
    streamPut(stream, record.queryBegin);
    streamPut(stream, "\nquery end: ");
    streamPut(stream, record.queryEnd);
    streamPut(stream, "\nsubject begin: ");
    streamPut(stream, record.subjectBegin);
    streamPut(stream, "\nsubject end: ");
    streamPut(stream, record.subjectEnd);
    streamPut(stream, "\nevalue: ");
    streamPut(stream, record.eValue);
    streamPut(stream, "\nbit score: ");
    streamPut(stream, record.bitScore);
    int res = streamPut(stream, "\n\n");
    return res;
}

void clear(BlastnTabAlignmentRecord & record)
{
    clear(record.queryName);
    clear(record.subjectName);
}

// FRAGMENT(next-is)
template <typename TStream, typename TSpec>
inline bool
nextIs(RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabComment const & /*tag*/)
{
    return !atEnd(reader) && value(reader) == '#';
}

template <typename TStream, typename TSpec>
inline bool
nextIs(RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabAlignment const & /*tag*/)
{
    return !atEnd(reader) && value(reader) != '#';
}

// FRAGMENT(read-record)
template <typename TCharSequence, typename TStream, typename TSpec>
inline int
readRecord(TCharSequence & buffer, RecordReader<TStream, SinglePass<TSpec> > const & reader, BlastnTabComment const & /*tag*/)
{
    SEQAN_ASSERT(nextIs(reader, BlastnTabComment()));
    clear(buffer);
    return readLine(buffer, reader);
}

// FRAGMENT(record)
template <typename TStream, typename TSpec>
inline bool
readRecord(BlastnTabAlignmentRecord & record, RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabAlignment const & /*tag*/)
{
    SEQAN_ASSERT(nextIs(reader, BlastnTabAlignment()));
    int res = 0;
    CharString buffer;
    clear(record);

    // Read query name.
    res = readUntilChar(record.queryName, reader, '\t');
    if (res != 0)
        return res;
    goNext(reader);

    // Read subject name.
    res = readUntilChar(record.subjectName, reader, '\t');
    if (res != 0)
        return res;
    goNext(reader);

    // Read identity.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<double>(record.identity, buffer))
        return 1;  // Could not cast identity to double.
    goNext(reader);

    // Read alignment length.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.alignmentLength, buffer))
        return 1;  // Could not cast alignment length to unsigned.
    goNext(reader);

    // Read mismatches.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.mismatches, buffer))
        return 1;  // Could not cast mismatches to unsigned.
    goNext(reader);

    // Read gap opens.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.gapOpens, buffer))
        return 1;  // Could not cast gap opens to unsigned.
    goNext(reader);

    // Read query begin.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.queryBegin, buffer))
        return 1;  // Could not cast query begin to unsigned.
    goNext(reader);

    // Read query end.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.queryEnd, buffer))
        return 1;  // Could not cast query end to unsigned.
    goNext(reader);

    // Read subject begin.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.subjectBegin, buffer))
        return 1;  // Could not cast subject begin to unsigned.
    goNext(reader);

    // Read subject end.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<unsigned>(record.subjectEnd, buffer))
        return 1;  // Could not cast subject end to unsigned.
    goNext(reader);

    // Read evalue.
    clear(buffer);
    res = readUntilChar(buffer, reader, '\t');
    if (res != 0)
        return res;
    if (!lexicalCast2<double>(record.eValue, buffer))
        return 1;  // Could not cast evalue to double.
    goNext(reader);

    // Read bit score, up to end of the line.
    clear(buffer);
    res = readLine(buffer, reader);
    if (res != 0)
        return res;
    if (!lexicalCast2<double>(record.bitScore, buffer))
        return 1;  // Could not cast bit score to double.

    return 0;
}

// FRAGMENT(skip-record)
template <typename TStream, typename TSpec>
inline int
skipRecord(RecordReader<TStream, SinglePass<TSpec> > & reader, BlastnTabComment const & /*tag*/)
{
    return skipLine(reader);
}

template <typename TStream, typename TPass>
inline int
skipRecord(RecordReader<TStream, TPass> & reader, BlastnTabAlignment const & /*tag*/)
{
    return skipLine(reader);
}

// FRAGMENT(batch-read)
template <typename TBlastnTabRecords, typename TStream, typename TSpec>
int read(TBlastnTabRecords & records, RecordReader<TStream, SinglePass<TSpec> > & reader)
{
    BlastnTabAlignmentRecord record;
    while (!atEnd(reader))
    {
        if (nextIs(reader, BlastnTabComment()))
        {
            skipRecord(reader, BlastnTabComment());
            continue;
        }
        if (!nextIs(reader, BlastnTabAlignment()))
            return 1;
        if (readRecord(record, reader, BlastnTabAlignment()) != 0)
            return 1;
        appendValue(records, record);
    }
    return 0;
}

// FRAGMENT(main)
int main(int argc, char const ** argv)
{
    // Process command line arguments, open file.
    if (argc != 2)
    {
        std::cerr << "Incorrect argument count!" << std::endl;
        std::cerr << "USAGE: tutorial_parse_blastn INPUT.txt" << std::endl;
        return 1;
    }
    std::fstream stream(argv[1], std::ios::binary | std::ios::in);
    if (!stream.good())
    {
        std::cerr << "Could not open file " << argv[1] << std::endl;
        return 1;
    }

    // Read file.
    RecordReader<std::fstream, SinglePass<> > reader(stream);
    String<BlastnTabAlignmentRecord> records;
    int res = read(records, reader);
    if (res != 0)
    {
        std::cerr << "Could not read BLASTN records." << std::endl;
        return 1;
    }

    // Write read records.
    for (unsigned i = 0; i < length(records); ++i)
        write(std::cout, records[i]);

    return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <memory>

#include <anyode/anyode.hpp>
#include <anyode/anyode_blas_lapack.hpp>  // dgemv, dgesvd
#include <anyode/anyode_matrix.hpp> // DenseMatrix
#include <anyode/anyode_decomposition.hpp>  // SVD

namespace AnyODE {

    template <typename Real_t=double, typename JacMat_t=DenseMatrix<Real_t>, typename Decomp_t=SVD<Real_t>>
    struct OdeSysIterativeBase : public OdeSysBase<Real_t> {
        int m_njacvec_dot=0, m_nprec_setup=0, m_nprec_solve=0;
        std::unique_ptr<JacMat_t> m_jac_cache {nullptr};
        std::unique_ptr<JacMat_t> m_M_cache {nullptr};
        std::unique_ptr<Decomp_t> m_decomp_cache {nullptr};

        virtual Status jac_times_vec(const Real_t * const __restrict__ vec,
                                     Real_t * const __restrict__ out,
                                     Real_t t,
                                     const Real_t * const __restrict__ y,
                                     const Real_t * const __restrict__ fy
                                     ) override
        {
            // See "Jacobian information (matrix-vector product)"
            //     (4.6.8 in cvs_guide.pdf for sundials 2.7.0)
            auto status = AnyODE::Status::success;
            const int ny = this->get_ny();
            auto jac = std::make_unique<JacMat_t>(nullptr, ny, ny, ny, true);
            status = this->dense_jac_cmaj(t, y, fy, jac->m_data, jac->m_ld);
            jac->dot_vec(vec, out);
            m_njacvec_dot++;
            return status;
        }

        virtual Status prec_setup(Real_t t,
                                  const Real_t * const __restrict__ y,
                                  const Real_t * const __restrict__ fy,
                                  bool jac_ok,
                                  bool& jac_recomputed,
                                  Real_t gamma) override
        {
            const int ny = this->get_ny();
            auto status = AnyODE::Status::success;
            ignore(gamma);
            // See "Preconditioning (Jacobian data)" in cvs_guide.pdf (4.6.10 for 2.7.0)
            if (m_jac_cache == nullptr)
                m_jac_cache = std::make_unique<JacMat_t>(nullptr, ny, ny, ny, true);

            if (jac_ok){
                jac_recomputed = false;
            } else {
                status = this->dense_jac_cmaj(t, y, fy, m_jac_cache->m_data, m_jac_cache->m_ld);
                jac_recomputed = true;
            }
            if (m_M_cache == nullptr)
                m_M_cache = std::make_unique<JacMat_t>(nullptr, ny, ny, ny, true);
            m_M_cache->set_to_eye_plus_scaled_mtx(-gamma, *m_jac_cache);
            m_decomp_cache = std::make_unique<Decomp_t>(m_M_cache.get());
            m_decomp_cache->factorize();
            m_nprec_setup++;
            return status;
        }

        virtual Status prec_solve_left(const Real_t t,
                                       const Real_t * const __restrict__ y,
                                       const Real_t * const __restrict__ fy,
                                       const Real_t * const __restrict__ r,
                                       Real_t * const __restrict__ z,
                                       Real_t /* gamma */,
                                       Real_t /* delta */,
                                       const Real_t * const __restrict__ ewt
                                       ) override
        {
            // See 4.6.9 on page 75 in cvs_guide.pdf (Sundials 2.6.2)
            // Solves P*z = r, where P ~= I - gamma*J
            const int ny = this->get_ny();
            if (ewt)
                throw std::runtime_error("Not implemented.");
            m_nprec_solve++;

            ignore(t); ignore(fy); ignore(y);
            int info = m_decomp_cache->solve(r, z);
            if (info == 0)
                return AnyODE::Status::success;
            return AnyODE::Status::recoverable_error;
        }

    };
}
<commit_msg>Avoid warning about unused variable<commit_after>#pragma once

#include <memory>

#include <anyode/anyode.hpp>
#include <anyode/anyode_blas_lapack.hpp>  // dgemv, dgesvd
#include <anyode/anyode_matrix.hpp> // DenseMatrix
#include <anyode/anyode_decomposition.hpp>  // SVD

namespace AnyODE {

    template <typename Real_t=double, typename JacMat_t=DenseMatrix<Real_t>, typename Decomp_t=SVD<Real_t>>
    struct OdeSysIterativeBase : public OdeSysBase<Real_t> {
        int m_njacvec_dot=0, m_nprec_setup=0, m_nprec_solve=0;
        std::unique_ptr<JacMat_t> m_jac_cache {nullptr};
        std::unique_ptr<JacMat_t> m_M_cache {nullptr};
        std::unique_ptr<Decomp_t> m_decomp_cache {nullptr};

        virtual Status jac_times_vec(const Real_t * const __restrict__ vec,
                                     Real_t * const __restrict__ out,
                                     Real_t t,
                                     const Real_t * const __restrict__ y,
                                     const Real_t * const __restrict__ fy
                                     ) override
        {
            // See "Jacobian information (matrix-vector product)"
            //     (4.6.8 in cvs_guide.pdf for sundials 2.7.0)
            auto status = AnyODE::Status::success;
            const int ny = this->get_ny();
            auto jac = std::make_unique<JacMat_t>(nullptr, ny, ny, ny, true);
            status = this->dense_jac_cmaj(t, y, fy, jac->m_data, jac->m_ld);
            jac->dot_vec(vec, out);
            m_njacvec_dot++;
            return status;
        }

        virtual Status prec_setup(Real_t t,
                                  const Real_t * const __restrict__ y,
                                  const Real_t * const __restrict__ fy,
                                  bool jac_ok,
                                  bool& jac_recomputed,
                                  Real_t gamma) override
        {
            const int ny = this->get_ny();
            auto status = AnyODE::Status::success;
            ignore(gamma);
            // See "Preconditioning (Jacobian data)" in cvs_guide.pdf (4.6.10 for 2.7.0)
            if (m_jac_cache == nullptr)
                m_jac_cache = std::make_unique<JacMat_t>(nullptr, ny, ny, ny, true);

            if (jac_ok){
                jac_recomputed = false;
            } else {
                status = this->dense_jac_cmaj(t, y, fy, m_jac_cache->m_data, m_jac_cache->m_ld);
                jac_recomputed = true;
            }
            if (m_M_cache == nullptr)
                m_M_cache = std::make_unique<JacMat_t>(nullptr, ny, ny, ny, true);
            m_M_cache->set_to_eye_plus_scaled_mtx(-gamma, *m_jac_cache);
            m_decomp_cache = std::make_unique<Decomp_t>(m_M_cache.get());
            m_decomp_cache->factorize();
            m_nprec_setup++;
            return status;
        }

        virtual Status prec_solve_left(const Real_t t,
                                       const Real_t * const __restrict__ y,
                                       const Real_t * const __restrict__ fy,
                                       const Real_t * const __restrict__ r,
                                       Real_t * const __restrict__ z,
                                       Real_t /* gamma */,
                                       Real_t /* delta */,
                                       const Real_t * const __restrict__ ewt
                                       ) override
        {
            // See 4.6.9 on page 75 in cvs_guide.pdf (Sundials 2.6.2)
            // Solves P*z = r, where P ~= I - gamma*J
            if (ewt)
                throw std::runtime_error("Not implemented.");
            m_nprec_solve++;

            ignore(t); ignore(fy); ignore(y);
            int info = m_decomp_cache->solve(r, z);
            if (info == 0)
                return AnyODE::Status::success;
            return AnyODE::Status::recoverable_error;
        }

    };
}
<|endoftext|>


<commit_before>//
//  AppleStimulusDisplay.cpp
//  MWorksCore
//
//  Created by Christopher Stawarz on 12/14/20.
//

#include "AppleStimulusDisplay.hpp"

#include "OpenGLUtilities.hpp"
#include "Stimulus.h"

NS_ASSUME_NONNULL_BEGIN

@interface MWKStimulusDisplayViewDelegate : NSObject <MTKViewDelegate>

@property(nonatomic, strong) id<MTLCommandQueue> commandQueue;
@property(nonatomic, strong) id<MTLTexture> texture;

- (BOOL)prepareWithMTKView:(MTKView *)view
        useColorManagement:(BOOL)useColorManagement
                     error:(__autoreleasing NSError **)error;

@end

NS_ASSUME_NONNULL_END

@implementation MWKStimulusDisplayViewDelegate {
    id<MTLRenderPipelineState> _pipelineState;
}

- (BOOL)prepareWithMTKView:(MTKView *)view useColorManagement:(BOOL)useColorManagement error:(NSError **)error {
    id<MTLLibrary> library = [view.device newDefaultLibraryWithBundle:[NSBundle bundleForClass:[self class]]
                                                                error:error];
    if (!library) {
        return NO;
    }

    MTLFunctionConstantValues *functionConstantValues = [[MTLFunctionConstantValues alloc] init];
    const bool convertToSRGB = useColorManagement;
    [functionConstantValues setConstantValue:&convertToSRGB
                                        type:MTLDataTypeBool
                                    withName:@"MWKStimulusDisplayViewDelegate_convertToSRGB"];

    id<MTLFunction> vertexFunction = [library newFunctionWithName:@"MWKStimulusDisplayViewDelegate_vertexShader"];

    id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"MWKStimulusDisplayViewDelegate_fragmentShader"
                                                     constantValues:functionConstantValues
                                                              error:error];
    if (!fragmentFunction) {
        return NO;
    }

    MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
    pipelineStateDescriptor.vertexFunction = vertexFunction;
    pipelineStateDescriptor.fragmentFunction = fragmentFunction;
    pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat;

    _pipelineState = [view.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:error];
    if (!_pipelineState) {
        return NO;
    }

    return YES;
}

- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
    // Stimulus display views aren't resizeable, so this should never be called
}

- (void)drawInMTKView:(MTKView *)view {
    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    if (renderPassDescriptor) {
        id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
        id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

        [renderEncoder setRenderPipelineState:_pipelineState];
        [renderEncoder setFragmentTexture:self.texture atIndex:0];

        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];

        [renderEncoder endEncoding];
        [commandBuffer presentDrawable:view.currentDrawable];
        [commandBuffer commit];
    }
}

@end

BEGIN_NAMESPACE_MW

AppleStimulusDisplay::AppleStimulusDisplay(bool useColorManagement) :
    StimulusDisplay(useColorManagement),
    commandQueue(nil),
    mainView(nil),
    mirrorView(nil),
    mainViewDelegate(nil),
    mirrorViewDelegate(nil),
    framebufferWidth(0),
    framebufferHeight(0),
    framebuffer_id(-1)
{ }

AppleStimulusDisplay::~AppleStimulusDisplay() {
    @autoreleasepool {
        mirrorViewDelegate = nil;
        mainViewDelegate = nil;
        mirrorView = nil;
        mainView = nil;
        commandQueue = nil;
    }
}

void AppleStimulusDisplay::prepareContext(int context_id, bool isMainContext) {
    @autoreleasepool {
        auto contextManager = boost::dynamic_pointer_cast<AppleOpenGLContextManager>(opengl_context_manager);
        MTKView *view = contextManager->getView(context_id);
        view.paused = YES;

        MWKStimulusDisplayViewDelegate *delegate = [[MWKStimulusDisplayViewDelegate alloc] init];
        NSError *error = nil;
        if (![delegate prepareWithMTKView:view useColorManagement:useColorManagement error:&error]) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  "Cannot prepare Metal view delegate",
                                  error.localizedDescription.UTF8String);
        }

        if (isMainContext) {
            view.enableSetNeedsDisplay = NO;
            prepareFramebufferStack(view, contextManager->getContext(context_id));
            commandQueue = [view.device newCommandQueue];
            mainView = view;
            mainViewDelegate = delegate;
            auto ctxLock = opengl_context_manager->setCurrent(context_id);
            framebuffer_id = createFramebuffer();
        } else {
            view.enableSetNeedsDisplay = YES;
            mirrorView = view;
            mirrorViewDelegate = delegate;
        }

        delegate.commandQueue = commandQueue;
        delegate.texture = getMetalFramebufferTexture(framebuffer_id);
        view.delegate = delegate;
    }
}

void AppleStimulusDisplay::renderDisplay(const std::vector<boost::shared_ptr<Stimulus>> &stimsToDraw) {
    @autoreleasepool {
        if (needDraw) {
            auto ctxLock = opengl_context_manager->setCurrent(main_context_id);
            pushFramebuffer(framebuffer_id);

#if !MWORKS_OPENGL_ES
            // This has no effect on non-sRGB framebuffers, so we can enable it unconditionally
            gl::Enabled<GL_FRAMEBUFFER_SRGB> framebufferSRGBEnabled;
#endif

            glDisable(GL_BLEND);
            glDisable(GL_DITHER);

            glClearColor(backgroundRed, backgroundGreen, backgroundBlue, backgroundAlpha);
            glClear(GL_COLOR_BUFFER_BIT);

            auto sharedThis = shared_from_this();
            for (auto &stim : stimsToDraw) {
                stim->draw(sharedThis);
            }

            glFlush();  // Commit pending OpenGL commands
            popFramebuffer();

            if (mirrorView) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    mirrorView.needsDisplay = YES;
                });
            }
        }

        [mainView draw];
    }
}

void AppleStimulusDisplay::prepareFramebufferStack(MTKView *view, MWKOpenGLContext *context) {
    framebufferWidth = view.drawableSize.width;
    framebufferHeight = view.drawableSize.height;

    {
        NSDictionary *pixelBufferAttributes = @{
            (NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_64RGBAHalf),
            (NSString *)kCVPixelBufferWidthKey: @(framebufferWidth),
            (NSString *)kCVPixelBufferHeightKey: @(framebufferHeight),
            (NSString *)kCVPixelBufferMetalCompatibilityKey: @(YES),
#if TARGET_OS_OSX
            (NSString *)kCVPixelBufferOpenGLCompatibilityKey: @(YES),
#else
            (NSString *)kCVPixelBufferOpenGLESCompatibilityKey: @(YES),
#endif
        };
        CVPixelBufferPoolRef _cvPixelBufferPool = nullptr;
        auto status = CVPixelBufferPoolCreate(kCFAllocatorDefault,
                                              nullptr,
                                              (__bridge CFDictionaryRef)pixelBufferAttributes,
                                              &_cvPixelBufferPool);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create pixel buffer pool (error = %d)") % status);
        }
        cvPixelBufferPool = CVPixelBufferPoolPtr::owned(_cvPixelBufferPool);
    }

    {
        CVMetalTextureCacheRef _cvMetalTextureCache = nullptr;
        auto status = CVMetalTextureCacheCreate(kCFAllocatorDefault,
                                                nil,
                                                view.device,
                                                nil,
                                                &_cvMetalTextureCache);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create Metal texture cache (error = %d)") % status);
        }
        cvMetalTextureCache = CVMetalTextureCachePtr::created(_cvMetalTextureCache);
    }

    {
#if TARGET_OS_OSX
        CVOpenGLTextureCacheRef _cvOpenGLTextureCache = nullptr;
        auto status = CVOpenGLTextureCacheCreate(kCFAllocatorDefault,
                                                 nil,
                                                 context.CGLContextObj,
                                                 context.pixelFormat.CGLPixelFormatObj,
                                                 nil,
                                                 &_cvOpenGLTextureCache);
#else
        CVOpenGLESTextureCacheRef _cvOpenGLTextureCache = nullptr;
        auto status = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault,
                                                   nil,
                                                   context,
                                                   nil,
                                                   &_cvOpenGLTextureCache);
#endif
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create OpenGL texture cache (error = %d)") % status);
        }
        cvOpenGLTextureCache = CVOpenGLTextureCachePtr::created(_cvOpenGLTextureCache);
    }
}

int AppleStimulusDisplay::createFramebuffer() {
    Framebuffer framebuffer;

    {
        CVPixelBufferRef _cvPixelBuffer = nullptr;
        auto status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault,
                                                         cvPixelBufferPool.get(),
                                                         &_cvPixelBuffer);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create pixel buffer (error = %d)") % status);
        }
        framebuffer.cvPixelBuffer = CVPixelBufferPtr::owned(_cvPixelBuffer);
    }

    {
        CVMetalTextureRef _cvMetalTexture = nullptr;
        auto status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                                cvMetalTextureCache.get(),
                                                                framebuffer.cvPixelBuffer.get(),
                                                                nil,
                                                                MTLPixelFormatRGBA16Float,
                                                                framebufferWidth,
                                                                framebufferHeight,
                                                                0,
                                                                &_cvMetalTexture);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create Metal texture (error = %d)") % status);
        }
        framebuffer.cvMetalTexture = CVMetalTexturePtr::created(_cvMetalTexture);
    }

    {
#if TARGET_OS_OSX
        CVOpenGLTextureRef _cvOpenGLTexture = nullptr;
        auto status = CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                                 cvOpenGLTextureCache.get(),
                                                                 framebuffer.cvPixelBuffer.get(),
                                                                 nil,
                                                                 &_cvOpenGLTexture);
#else
        CVOpenGLESTextureRef _cvOpenGLTexture = nullptr;
        auto status = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                                   cvOpenGLTextureCache.get(),
                                                                   framebuffer.cvPixelBuffer.get(),
                                                                   nil,
                                                                   GL_TEXTURE_2D,
                                                                   GL_RGBA16F,
                                                                   framebufferWidth,
                                                                   framebufferHeight,
                                                                   GL_RGBA,
                                                                   GL_HALF_FLOAT,
                                                                   0,
                                                                   &_cvOpenGLTexture);
#endif
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create OpenGL texture (error = %d)") % status);
        }
        framebuffer.cvOpenGLTexture = CVOpenGLTexturePtr::created(_cvOpenGLTexture);
    }

    {
        GLuint _glFramebuffer = 0;
        glGenFramebuffers(1, &_glFramebuffer);
        gl::FramebufferBinding<GL_DRAW_FRAMEBUFFER> framebufferBinding(_glFramebuffer);

        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                               GL_COLOR_ATTACHMENT0,
#if TARGET_OS_OSX
                               CVOpenGLTextureGetTarget(framebuffer.cvOpenGLTexture.get()),
                               CVOpenGLTextureGetName(framebuffer.cvOpenGLTexture.get()),
#else
                               CVOpenGLESTextureGetTarget(framebuffer.cvOpenGLTexture.get()),
                               CVOpenGLESTextureGetName(framebuffer.cvOpenGLTexture.get()),
#endif
                               0);

        if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)) {
            throw SimpleException("OpenGL framebuffer setup failed");
        }

        framebuffer.glFramebuffer = _glFramebuffer;
    }

    int framebuffer_id = 0;
    auto lastIter = framebuffers.rbegin();
    if (lastIter != framebuffers.rend()) {
        framebuffer_id = lastIter->first + 1;
    }
    framebuffers.emplace(framebuffer_id, std::move(framebuffer));
    return framebuffer_id;
}

void AppleStimulusDisplay::pushFramebuffer(int framebuffer_id) {
    auto iter = framebuffers.find(framebuffer_id);
    if (iter == framebuffers.end()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: invalid framebuffer ID: %d", framebuffer_id);
        return;
    }
    framebufferStack.emplace_back(iter->second);
    bindCurrentFramebuffer();
}

void AppleStimulusDisplay::bindCurrentFramebuffer() {
    if (framebufferStack.empty()) {
        // Bind the default framebuffer
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        return;
    }
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferStack.back().glFramebuffer);
    const GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
    glDrawBuffers(1, &drawBuffer);
    glViewport(0, 0, framebufferWidth, framebufferHeight);
}

id<MTLTexture> AppleStimulusDisplay::getMetalFramebufferTexture(int framebuffer_id) const {
    auto iter = framebuffers.find(framebuffer_id);
    if (iter == framebuffers.end()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: invalid framebuffer ID: %d", framebuffer_id);
        return nil;
    }
    return CVMetalTextureGetTexture(iter->second.cvMetalTexture.get());
}

id<MTLTexture> AppleStimulusDisplay::getCurrentMetalFramebufferTexture() const {
    if (framebufferStack.empty()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: no current Metal framebuffer texture");
        return nil;
    }
    return CVMetalTextureGetTexture(framebufferStack.back().cvMetalTexture.get());
}

void AppleStimulusDisplay::popFramebuffer() {
    if (framebufferStack.empty()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: no framebuffer to pop");
        return;
    }
    framebufferStack.pop_back();
    bindCurrentFramebuffer();
}

void AppleStimulusDisplay::releaseFramebuffer(int framebuffer_id) {
    auto iter = framebuffers.find(framebuffer_id);
    if (iter == framebuffers.end()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: invalid framebuffer ID: %d", framebuffer_id);
        return;
    }
    framebuffers.erase(iter);
}

END_NAMESPACE_MW
<commit_msg>Use separate Metal command queues for the main and mirror view, as sharing one queue can cause frame drops and other issues.  Improvements to MWKStimulusDisplayViewDelegate.<commit_after>//
//  AppleStimulusDisplay.cpp
//  MWorksCore
//
//  Created by Christopher Stawarz on 12/14/20.
//

#include "AppleStimulusDisplay.hpp"

#include "OpenGLUtilities.hpp"
#include "Stimulus.h"

@interface MWKStimulusDisplayViewDelegate : NSObject <MTKViewDelegate>

@property(nonatomic, readonly) id<MTLCommandQueue> commandQueue;
@property(nonatomic, strong) id<MTLTexture> texture;

+ (instancetype)delegateWithMTKView:(MTKView *)view
                 useColorManagement:(BOOL)useColorManagement
                              error:(__autoreleasing NSError **)error;

- (instancetype)initWithCommandQueue:(id<MTLCommandQueue>)commandQueue
                       pipelineState:(id<MTLRenderPipelineState>)pipelineState;

@end

@implementation MWKStimulusDisplayViewDelegate {
    id<MTLRenderPipelineState> _pipelineState;
}

+ (instancetype)delegateWithMTKView:(MTKView *)view
                 useColorManagement:(BOOL)useColorManagement
                              error:(__autoreleasing NSError **)error
{
    id<MTLLibrary> library = [view.device newDefaultLibraryWithBundle:[NSBundle bundleForClass:self] error:error];
    if (!library) {
        return nil;
    }

    MTLFunctionConstantValues *functionConstantValues = [[MTLFunctionConstantValues alloc] init];
    const bool convertToSRGB = useColorManagement;
    [functionConstantValues setConstantValue:&convertToSRGB
                                        type:MTLDataTypeBool
                                    withName:@"MWKStimulusDisplayViewDelegate_convertToSRGB"];

    id<MTLFunction> vertexFunction = [library newFunctionWithName:@"MWKStimulusDisplayViewDelegate_vertexShader"];

    id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"MWKStimulusDisplayViewDelegate_fragmentShader"
                                                     constantValues:functionConstantValues
                                                              error:error];
    if (!fragmentFunction) {
        return nil;
    }

    MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
    pipelineStateDescriptor.vertexFunction = vertexFunction;
    pipelineStateDescriptor.fragmentFunction = fragmentFunction;
    pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat;

    id<MTLRenderPipelineState> pipelineState = [view.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
                                                                                error:error];
    if (!pipelineState) {
        return nil;
    }

    return [[self alloc] initWithCommandQueue:[view.device newCommandQueue] pipelineState:pipelineState];
}

- (instancetype)initWithCommandQueue:(id<MTLCommandQueue>)commandQueue
                       pipelineState:(id<MTLRenderPipelineState>)pipelineState
{
    self = [super init];
    if (self) {
        _commandQueue = commandQueue;
        _pipelineState = pipelineState;
    }
    return self;
}

- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
    // Stimulus display views aren't resizeable, so this should never be called
}

- (void)drawInMTKView:(MTKView *)view {
    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    if (renderPassDescriptor) {
        id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
        id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

        [renderEncoder setRenderPipelineState:_pipelineState];
        [renderEncoder setFragmentTexture:self.texture atIndex:0];

        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];

        [renderEncoder endEncoding];
        [commandBuffer presentDrawable:view.currentDrawable];
        [commandBuffer commit];
    }
}

@end

BEGIN_NAMESPACE_MW

AppleStimulusDisplay::AppleStimulusDisplay(bool useColorManagement) :
    StimulusDisplay(useColorManagement),
    commandQueue(nil),
    mainView(nil),
    mirrorView(nil),
    mainViewDelegate(nil),
    mirrorViewDelegate(nil),
    framebufferWidth(0),
    framebufferHeight(0),
    framebuffer_id(-1)
{ }

AppleStimulusDisplay::~AppleStimulusDisplay() {
    @autoreleasepool {
        mirrorViewDelegate = nil;
        mainViewDelegate = nil;
        mirrorView = nil;
        mainView = nil;
        commandQueue = nil;
    }
}

void AppleStimulusDisplay::prepareContext(int context_id, bool isMainContext) {
    @autoreleasepool {
        auto contextManager = boost::dynamic_pointer_cast<AppleOpenGLContextManager>(opengl_context_manager);
        MTKView *view = contextManager->getView(context_id);
        view.paused = YES;

        MWKStimulusDisplayViewDelegate *delegate = nil;
        NSError *error = nil;
        if (!(delegate = [MWKStimulusDisplayViewDelegate delegateWithMTKView:view
                                                          useColorManagement:useColorManagement
                                                                       error:&error]))
        {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  "Cannot create stimulus display view delegate",
                                  error.localizedDescription.UTF8String);
        }

        if (!isMainContext) {
            view.enableSetNeedsDisplay = YES;
            mirrorView = view;
            mirrorViewDelegate = delegate;
        } else {
            view.enableSetNeedsDisplay = NO;
            commandQueue = delegate.commandQueue;
            mainView = view;
            mainViewDelegate = delegate;
            auto ctxLock = contextManager->setCurrent(context_id);
            prepareFramebufferStack(view, contextManager->getContext(context_id));
            framebuffer_id = createFramebuffer();
        }

        delegate.texture = getMetalFramebufferTexture(framebuffer_id);
        view.delegate = delegate;
    }
}

void AppleStimulusDisplay::renderDisplay(const std::vector<boost::shared_ptr<Stimulus>> &stimsToDraw) {
    @autoreleasepool {
        if (needDraw) {
            auto ctxLock = opengl_context_manager->setCurrent(main_context_id);
            pushFramebuffer(framebuffer_id);

#if !MWORKS_OPENGL_ES
            // This has no effect on non-sRGB framebuffers, so we can enable it unconditionally
            gl::Enabled<GL_FRAMEBUFFER_SRGB> framebufferSRGBEnabled;
#endif

            glDisable(GL_BLEND);
            glDisable(GL_DITHER);

            glClearColor(backgroundRed, backgroundGreen, backgroundBlue, backgroundAlpha);
            glClear(GL_COLOR_BUFFER_BIT);

            auto sharedThis = shared_from_this();
            for (auto &stim : stimsToDraw) {
                stim->draw(sharedThis);
            }

            popFramebuffer();
            glFlush();  // Commit pending OpenGL commands

            if (mirrorView) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    mirrorView.needsDisplay = YES;
                });
            }
        }

        [mainView draw];
    }
}

void AppleStimulusDisplay::prepareFramebufferStack(MTKView *view, MWKOpenGLContext *context) {
    framebufferWidth = view.drawableSize.width;
    framebufferHeight = view.drawableSize.height;

    {
        NSDictionary *pixelBufferAttributes = @{
            (NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_64RGBAHalf),
            (NSString *)kCVPixelBufferWidthKey: @(framebufferWidth),
            (NSString *)kCVPixelBufferHeightKey: @(framebufferHeight),
            (NSString *)kCVPixelBufferMetalCompatibilityKey: @(YES),
#if TARGET_OS_OSX
            (NSString *)kCVPixelBufferOpenGLCompatibilityKey: @(YES),
#else
            (NSString *)kCVPixelBufferOpenGLESCompatibilityKey: @(YES),
#endif
        };
        CVPixelBufferPoolRef _cvPixelBufferPool = nullptr;
        auto status = CVPixelBufferPoolCreate(kCFAllocatorDefault,
                                              nullptr,
                                              (__bridge CFDictionaryRef)pixelBufferAttributes,
                                              &_cvPixelBufferPool);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create pixel buffer pool (error = %d)") % status);
        }
        cvPixelBufferPool = CVPixelBufferPoolPtr::owned(_cvPixelBufferPool);
    }

    {
        CVMetalTextureCacheRef _cvMetalTextureCache = nullptr;
        auto status = CVMetalTextureCacheCreate(kCFAllocatorDefault,
                                                nil,
                                                view.device,
                                                nil,
                                                &_cvMetalTextureCache);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create Metal texture cache (error = %d)") % status);
        }
        cvMetalTextureCache = CVMetalTextureCachePtr::created(_cvMetalTextureCache);
    }

    {
#if TARGET_OS_OSX
        CVOpenGLTextureCacheRef _cvOpenGLTextureCache = nullptr;
        auto status = CVOpenGLTextureCacheCreate(kCFAllocatorDefault,
                                                 nil,
                                                 context.CGLContextObj,
                                                 context.pixelFormat.CGLPixelFormatObj,
                                                 nil,
                                                 &_cvOpenGLTextureCache);
#else
        CVOpenGLESTextureCacheRef _cvOpenGLTextureCache = nullptr;
        auto status = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault,
                                                   nil,
                                                   context,
                                                   nil,
                                                   &_cvOpenGLTextureCache);
#endif
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create OpenGL texture cache (error = %d)") % status);
        }
        cvOpenGLTextureCache = CVOpenGLTextureCachePtr::created(_cvOpenGLTextureCache);
    }
}

int AppleStimulusDisplay::createFramebuffer() {
    Framebuffer framebuffer;

    {
        CVPixelBufferRef _cvPixelBuffer = nullptr;
        auto status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault,
                                                         cvPixelBufferPool.get(),
                                                         &_cvPixelBuffer);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create pixel buffer (error = %d)") % status);
        }
        framebuffer.cvPixelBuffer = CVPixelBufferPtr::owned(_cvPixelBuffer);
    }

    {
        CVMetalTextureRef _cvMetalTexture = nullptr;
        auto status = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                                cvMetalTextureCache.get(),
                                                                framebuffer.cvPixelBuffer.get(),
                                                                nil,
                                                                MTLPixelFormatRGBA16Float,
                                                                framebufferWidth,
                                                                framebufferHeight,
                                                                0,
                                                                &_cvMetalTexture);
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create Metal texture (error = %d)") % status);
        }
        framebuffer.cvMetalTexture = CVMetalTexturePtr::created(_cvMetalTexture);
    }

    {
#if TARGET_OS_OSX
        CVOpenGLTextureRef _cvOpenGLTexture = nullptr;
        auto status = CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                                 cvOpenGLTextureCache.get(),
                                                                 framebuffer.cvPixelBuffer.get(),
                                                                 nil,
                                                                 &_cvOpenGLTexture);
#else
        CVOpenGLESTextureRef _cvOpenGLTexture = nullptr;
        auto status = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                                   cvOpenGLTextureCache.get(),
                                                                   framebuffer.cvPixelBuffer.get(),
                                                                   nil,
                                                                   GL_TEXTURE_2D,
                                                                   GL_RGBA16F,
                                                                   framebufferWidth,
                                                                   framebufferHeight,
                                                                   GL_RGBA,
                                                                   GL_HALF_FLOAT,
                                                                   0,
                                                                   &_cvOpenGLTexture);
#endif
        if (status != kCVReturnSuccess) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  boost::format("Cannot create OpenGL texture (error = %d)") % status);
        }
        framebuffer.cvOpenGLTexture = CVOpenGLTexturePtr::created(_cvOpenGLTexture);
    }

    {
        GLuint _glFramebuffer = 0;
        glGenFramebuffers(1, &_glFramebuffer);
        gl::FramebufferBinding<GL_DRAW_FRAMEBUFFER> framebufferBinding(_glFramebuffer);

        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                               GL_COLOR_ATTACHMENT0,
#if TARGET_OS_OSX
                               CVOpenGLTextureGetTarget(framebuffer.cvOpenGLTexture.get()),
                               CVOpenGLTextureGetName(framebuffer.cvOpenGLTexture.get()),
#else
                               CVOpenGLESTextureGetTarget(framebuffer.cvOpenGLTexture.get()),
                               CVOpenGLESTextureGetName(framebuffer.cvOpenGLTexture.get()),
#endif
                               0);

        if (GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)) {
            throw SimpleException("OpenGL framebuffer setup failed");
        }

        framebuffer.glFramebuffer = _glFramebuffer;
    }

    int framebuffer_id = 0;
    auto lastIter = framebuffers.rbegin();
    if (lastIter != framebuffers.rend()) {
        framebuffer_id = lastIter->first + 1;
    }
    framebuffers.emplace(framebuffer_id, std::move(framebuffer));
    return framebuffer_id;
}

void AppleStimulusDisplay::pushFramebuffer(int framebuffer_id) {
    auto iter = framebuffers.find(framebuffer_id);
    if (iter == framebuffers.end()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: invalid framebuffer ID: %d", framebuffer_id);
        return;
    }
    framebufferStack.emplace_back(iter->second);
    bindCurrentFramebuffer();
}

void AppleStimulusDisplay::bindCurrentFramebuffer() {
    if (framebufferStack.empty()) {
        // Bind the default framebuffer
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        return;
    }
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferStack.back().glFramebuffer);
    const GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
    glDrawBuffers(1, &drawBuffer);
    glViewport(0, 0, framebufferWidth, framebufferHeight);
}

id<MTLTexture> AppleStimulusDisplay::getMetalFramebufferTexture(int framebuffer_id) const {
    auto iter = framebuffers.find(framebuffer_id);
    if (iter == framebuffers.end()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: invalid framebuffer ID: %d", framebuffer_id);
        return nil;
    }
    return CVMetalTextureGetTexture(iter->second.cvMetalTexture.get());
}

id<MTLTexture> AppleStimulusDisplay::getCurrentMetalFramebufferTexture() const {
    if (framebufferStack.empty()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: no current Metal framebuffer texture");
        return nil;
    }
    return CVMetalTextureGetTexture(framebufferStack.back().cvMetalTexture.get());
}

void AppleStimulusDisplay::popFramebuffer() {
    if (framebufferStack.empty()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: no framebuffer to pop");
        return;
    }
    framebufferStack.pop_back();
    bindCurrentFramebuffer();
}

void AppleStimulusDisplay::releaseFramebuffer(int framebuffer_id) {
    auto iter = framebuffers.find(framebuffer_id);
    if (iter == framebuffers.end()) {
        merror(M_DISPLAY_MESSAGE_DOMAIN, "Internal error: invalid framebuffer ID: %d", framebuffer_id);
        return;
    }
    framebuffers.erase(iter);
}

END_NAMESPACE_MW
<|endoftext|>