<commit_before>#include "VolumeOSD.h"

#include "..\SoundPlayer.h"

#include <string>

#include "..\HotkeyInfo.h"
#include "..\MeterWnd\Meters\CallbackMeter.h"
#include "..\Monitor.h"
#include "..\Skin.h"
#include "..\SkinManager.h"
#include "..\Slider\VolumeSlider.h"
#include "..\MeterWnd\LayeredWnd.h"

#define MENU_SETTINGS 0
#define MENU_MIXER 1
#define MENU_EXIT 2
#define MENU_DEVICE 0xF000

VolumeOSD::VolumeOSD() :
OSD(L"3RVX-VolumeDispatcher"),
_mWnd(L"3RVX-VolumeOSD", L"3RVX-VolumeOSD"),
_muteWnd(L"3RVX-MuteOSD", L"3RVX-MuteOSD") {

    LoadSkin();
    Settings *settings = Settings::Instance();

    /* Start the volume controller */
    _volumeCtrl = new CoreAudio(_hWnd);
    std::wstring device = settings->AudioDeviceID();
    _volumeCtrl->Init(device);
    _selectedDesc = _volumeCtrl->DeviceDesc();

    /* Set up volume state variables */
    _lastVolume = _volumeCtrl->Volume();
    _muted = _volumeCtrl->Muted();

    if (settings->SoundEffectsEnabled()) {
        _sounds = true;
    }

    /* Create the slider */
    _volumeSlider = new VolumeSlider(*_volumeCtrl);

    /* Set up context menu */
    if (settings->NotifyIconEnabled()) {
        _menu = CreatePopupMenu();
        _deviceMenu = CreatePopupMenu();

        InsertMenu(_menu, -1, MF_ENABLED, MENU_SETTINGS, L"Settings");
        InsertMenu(_menu, -1, MF_POPUP, UINT(_deviceMenu), L"Audio Device");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_MIXER, L"Mixer");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_EXIT, L"Exit");

        _menuFlags = TPM_RIGHTBUTTON;
        if (GetSystemMetrics(SM_MENUDROPALIGNMENT) != 0) {
            _menuFlags |= TPM_RIGHTALIGN;
        } else {
            _menuFlags |= TPM_LEFTALIGN;
        }

        UpdateDeviceMenu();
    }

    _mWnd.AlwaysOnTop(settings->AlwaysOnTop());
    _mWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _mWnd.VisibleDuration(settings->HideDelay());

    _muteWnd.AlwaysOnTop(settings->AlwaysOnTop());
    _muteWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _muteWnd.VisibleDuration(settings->HideDelay());

    UpdateIcon();
    float v = _volumeCtrl->Volume();
    MeterLevels(v);
    _volumeSlider->MeterLevels(v);

    /* TODO: check whether we should show the OSD on startup or not. If so, post
     * a MSG_VOL_CHNG so that the volume level (or mute) is displayed: */
    SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
}

VolumeOSD::~VolumeOSD() {
    DestroyMenu(_deviceMenu);
    DestroyMenu(_menu);
    delete _icon;
    delete _volumeSlider;
    delete _callbackMeter;
    _volumeCtrl->Dispose();
}

void VolumeOSD::UpdateDeviceMenu() {
    if (_menu == NULL || _deviceMenu == NULL) {
        return;
    }

    /* Remove any devices currently in the menu first */
    for (unsigned int i = 0; i < _deviceList.size(); ++i) {
        RemoveMenu(_deviceMenu, 0, MF_BYPOSITION);
    }
    _deviceList.clear();

    std::list<VolumeController::DeviceInfo> devices
        = _volumeCtrl->ListDevices();
    std::wstring currentDeviceId = _volumeCtrl->DeviceId();

    int menuItem = MENU_DEVICE;
    for (VolumeController::DeviceInfo device : devices) {
        unsigned int flags = MF_ENABLED;
        if (currentDeviceId == device.id) {
            flags |= MF_CHECKED;
        }

        InsertMenu(_deviceMenu, -1, flags, menuItem++, device.name.c_str());
        _deviceList.push_back(device);
    }
}

void VolumeOSD::LoadSkin() {
    Settings *settings = Settings::Instance();
    Skin *skin = SkinManager::Instance()->CurrentSkin();

    /* Volume OSD */
    /* TODO: should make sure this isn't NULL! */
    _mWnd.BackgroundImage(skin->volumeBackground);

    if (skin->volumeMask != NULL) {
        _mWnd.EnableGlass(skin->volumeMask);
    }

    for (Meter *m : skin->volumeMeters) {
        _mWnd.AddMeter(m);
    }

    /* Add a callback meter with the default volume increment for sounds */
    _callbackMeter = new CallbackMeter(
        skin->DefaultVolumeUnits(), *this);
    _mWnd.AddMeter(_callbackMeter);

    /* Default volume increment */
    _defaultIncrement = (float) (10000 / skin->DefaultVolumeUnits()) / 10000.0f;
    CLOG(L"Default volume increment: %f", _defaultIncrement);

    _mWnd.Update();

    /* Mute OSD */
    /* TODO: NULL check*/
    _muteWnd.BackgroundImage(skin->muteBackground);

    if (skin->muteMask != NULL) {
        _muteWnd.EnableGlass(skin->muteMask);
    }
    _muteWnd.Update();

    /* Create clones for additional monitors */
    std::vector<Monitor> monitors = ActiveMonitors();
    for (unsigned int i = 1; i < monitors.size(); ++i) {
        _mWnd.Clone();
        _muteWnd.Clone();
    }
    UpdateWindowPositions(monitors);

    /* Set up notification icon */
    if (settings->NotifyIconEnabled()) {
        _iconImages = skin->volumeIconset;
        if (_iconImages.size() > 0) {
            _icon = new NotifyIcon(_hWnd, L"3RVX", _iconImages[0]);
        }
    }

    /* Enable sound effects, if any */
    if (settings->SoundEffectsEnabled()) {
        if (skin->volumeSound) {
            _soundPlayer = skin->volumeSound;
        }
    }
}

void VolumeOSD::MeterLevels(float level) {
    _mWnd.MeterLevels(level);
    _mWnd.Update();
}

void VolumeOSD::MeterChangeCallback(int units) {
    if (_soundPlayer) {
        _soundPlayer->Play();
    }
}

void VolumeOSD::Hide() {
    _mWnd.Hide(false);
    _muteWnd.Hide(false);
}

void VolumeOSD::HideIcon() {
    delete _icon;
}

void VolumeOSD::UpdateIcon() {
    UpdateIconImage();
    UpdateIconTip();
}

void VolumeOSD::UpdateIconImage() {
    if (_icon == NULL) {
        return;
    }

    int icon = 0;
    if (_volumeCtrl->Muted() == false) {
        int vUnits = _iconImages.size() - 1;
        icon = (int) ceil(_volumeCtrl->Volume() * vUnits);
    }

    if (icon != _lastIcon) {
        _icon->UpdateIcon(_iconImages[icon]);
        _lastIcon = icon;
    }
}

void VolumeOSD::UpdateIconTip() {
    if (_icon == NULL) {
        return;
    }

    if (_volumeCtrl->Muted()) {
        _icon->UpdateToolTip(_selectedDesc + L": Muted");
    } else {
        float v = _volumeCtrl->Volume();
        std::wstring perc = std::to_wstring((int) (v * 100.0f));
        std::wstring level = _selectedDesc + L": " + perc + L"%";
        _icon->UpdateToolTip(level);
    }
}

void VolumeOSD::UnMute() {
    if (_volumeCtrl->Muted() == true) {
        _volumeCtrl->Muted(false);
    }
}

void VolumeOSD::ProcessHotkeys(HotkeyInfo &hki) {
    switch (hki.action) {
    case HotkeyInfo::IncreaseVolume:
    case HotkeyInfo::DecreaseVolume:
        UnMute();
        ProcessVolumeHotkeys(hki);
        break;
        }
        _volumeCtrl->Volume(
            (float) (currentUnit + unitIncrement) * _defaultIncrement);
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::Mute:
        _volumeCtrl->ToggleMute();
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::VolumeSlider:
        if (_volumeSlider->Visible()) {
            /* If the slider is already visible, user must want to close it. */
            _volumeSlider->Hide();
        } else {
            SendMessage(_hWnd, MSG_NOTIFYICON, NULL, WM_LBUTTONUP);
        }
        break;
    }
}

void VolumeOSD::ProcessVolumeHotkeys(HotkeyInfo &hki) {
    float currentVol = _volumeCtrl->Volume();
    HotkeyInfo::VolumeKeyArgTypes type = HotkeyInfo::VolumeArgType(hki);

    if (type == HotkeyInfo::VolumeKeyArgTypes::Percentage) {
        /* Deal with percentage-based amounts */
        float amount = (hki.ArgToDouble(0) / 100.0f);
        if (hki.action == HotkeyInfo::HotkeyActions::DecreaseVolume) {
            amount = -amount;
        }
        _volumeCtrl->Volume(currentVol + amount);
    } else {
        /* Unit-based amounts */
        int unitIncrement = 1;
        int currentUnit = _callbackMeter->CalcUnits();
        if (currentVol <= 0.000001f) {
            currentUnit = 0;
        }

        if (hki.action == HotkeyInfo::DecreaseVolume) {
            unitIncrement = -1;
        }

        if (type == HotkeyInfo::VolumeKeyArgTypes::Units) {
            unitIncrement *= hki.ArgToInt(0);
        }

        _volumeCtrl->Volume(
            (float) (currentUnit + unitIncrement) * _defaultIncrement);
    }

    /* Tell 3RVX that we changed the volume */
    SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
}

void VolumeOSD::UpdateWindowPositions(std::vector<Monitor> &monitors) {
    PositionWindow(monitors[0], _mWnd);
    PositionWindow(monitors[0], _muteWnd);

    std::vector<LayeredWnd *> meterClones = _mWnd.Clones();
    std::vector<LayeredWnd *> muteClones = _muteWnd.Clones();
    for (unsigned int i = 1; i < monitors.size(); ++i) {
        PositionWindow(monitors[i], *meterClones[i - 1]);
        PositionWindow(monitors[i], *muteClones[i - 1]);
    }
}

void VolumeOSD::UpdateVolumeState() {
    float v = _volumeCtrl->Volume();
    MeterLevels(v);
    _volumeSlider->MeterLevels(v);
    UpdateIcon();
}

LRESULT
VolumeOSD::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == MSG_VOL_CHNG) {
        float v = _volumeCtrl->Volume();
        bool muteState = _volumeCtrl->Muted();

        _volumeSlider->MeterLevels(v);
        UpdateIcon();

        if (wParam > 0) {
            /* We manually post a MSG_VOL_CHNG when modifying the volume with
             * hotkeys, so this CoreAudio-generated event can be ignored
             * by the OSD. */
            CLOG(L"Ignoring volume change notification generated by 3RVX");
            return DefWindowProc(hWnd, message, wParam, lParam);
        }

        CLOG(L"Volume change notification:\nNew level: %f\nPrevious: %f",
            v, _lastVolume);
        if (lParam == 0 && (muteState == _muted)) {
            if (abs(v - _lastVolume) < 0.0001f) {
                CLOG(L"No change in volume detected; ignoring event.");
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        _lastVolume = v;
        _muted = muteState;

        if (_volumeSlider->Visible() == false) {
            if (_volumeCtrl->Muted() || v == 0.0f) {
                _muteWnd.Show();
                _mWnd.Hide(false);
            } else {
                MeterLevels(v);
                _mWnd.Show();
                _muteWnd.Hide(false);
            }
            HideOthers(Volume);
        }

    } else if (message == MSG_VOL_DEVCHNG) {
        CLOG(L"Volume device change detected.");
        if (_selectedDevice == L"") {
            _volumeCtrl->SelectDefaultDevice();
        } else {
            HRESULT hr = _volumeCtrl->SelectDevice(_selectedDevice);
            if (FAILED(hr)) {
                _volumeCtrl->SelectDefaultDevice();
            }
        }
        _selectedDesc = _volumeCtrl->DeviceDesc();
        UpdateDeviceMenu();
        UpdateVolumeState();

    } else if (message == MSG_NOTIFYICON) {
        if (lParam == WM_LBUTTONUP) {
            _volumeSlider->MeterLevels(_volumeCtrl->Volume());
            _volumeSlider->Show();
        } else if (lParam == WM_RBUTTONUP) {
            POINT p;
            GetCursorPos(&p);
            SetForegroundWindow(hWnd);
            TrackPopupMenuEx(_menu, _menuFlags, p.x, p.y, _hWnd, NULL);
            PostMessage(hWnd, WM_NULL, 0, 0);
        }

    } else if (message == WM_COMMAND) {
        int menuItem = LOWORD(wParam);
        switch (menuItem) {
        case MENU_SETTINGS:
            Settings::LaunchSettingsApp();
            break;

        case MENU_MIXER: {
            CLOG(L"Menu: Mixer");
            HINSTANCE code = ShellExecute(NULL, L"open", L"sndvol",
                NULL, NULL, SW_SHOWNORMAL);
            break;
        }

        case MENU_EXIT:
            CLOG(L"Menu: Exit: %d", (int) _masterWnd);
            SendMessage(_masterWnd, WM_CLOSE, NULL, NULL);
            break;
        }

        /* Device menu items */
        if ((menuItem & MENU_DEVICE) > 0) {
            int device = menuItem & 0x0FFF;
            VolumeController::DeviceInfo selectedDev = _deviceList[device];
            if (selectedDev.id != _volumeCtrl->DeviceId()) {
                /* A different device has been selected */
                CLOG(L"Changing to volume device: %s",
                    selectedDev.name.c_str());
                _volumeCtrl->SelectDevice(selectedDev.id);
                UpdateDeviceMenu();
                UpdateVolumeState();
            }
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}<commit_msg>Implement SetVolume hotkey<commit_after>#include "VolumeOSD.h"

#include "..\SoundPlayer.h"

#include <string>

#include "..\HotkeyInfo.h"
#include "..\MeterWnd\Meters\CallbackMeter.h"
#include "..\Monitor.h"
#include "..\Skin.h"
#include "..\SkinManager.h"
#include "..\Slider\VolumeSlider.h"
#include "..\MeterWnd\LayeredWnd.h"

#define MENU_SETTINGS 0
#define MENU_MIXER 1
#define MENU_EXIT 2
#define MENU_DEVICE 0xF000

VolumeOSD::VolumeOSD() :
OSD(L"3RVX-VolumeDispatcher"),
_mWnd(L"3RVX-VolumeOSD", L"3RVX-VolumeOSD"),
_muteWnd(L"3RVX-MuteOSD", L"3RVX-MuteOSD") {

    LoadSkin();
    Settings *settings = Settings::Instance();

    /* Start the volume controller */
    _volumeCtrl = new CoreAudio(_hWnd);
    std::wstring device = settings->AudioDeviceID();
    _volumeCtrl->Init(device);
    _selectedDesc = _volumeCtrl->DeviceDesc();

    /* Set up volume state variables */
    _lastVolume = _volumeCtrl->Volume();
    _muted = _volumeCtrl->Muted();

    if (settings->SoundEffectsEnabled()) {
        _sounds = true;
    }

    /* Create the slider */
    _volumeSlider = new VolumeSlider(*_volumeCtrl);

    /* Set up context menu */
    if (settings->NotifyIconEnabled()) {
        _menu = CreatePopupMenu();
        _deviceMenu = CreatePopupMenu();

        InsertMenu(_menu, -1, MF_ENABLED, MENU_SETTINGS, L"Settings");
        InsertMenu(_menu, -1, MF_POPUP, UINT(_deviceMenu), L"Audio Device");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_MIXER, L"Mixer");
        InsertMenu(_menu, -1, MF_ENABLED, MENU_EXIT, L"Exit");

        _menuFlags = TPM_RIGHTBUTTON;
        if (GetSystemMetrics(SM_MENUDROPALIGNMENT) != 0) {
            _menuFlags |= TPM_RIGHTALIGN;
        } else {
            _menuFlags |= TPM_LEFTALIGN;
        }

        UpdateDeviceMenu();
    }

    _mWnd.AlwaysOnTop(settings->AlwaysOnTop());
    _mWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _mWnd.VisibleDuration(settings->HideDelay());

    _muteWnd.AlwaysOnTop(settings->AlwaysOnTop());
    _muteWnd.HideAnimation(settings->HideAnim(), settings->HideSpeed());
    _muteWnd.VisibleDuration(settings->HideDelay());

    UpdateIcon();
    float v = _volumeCtrl->Volume();
    MeterLevels(v);
    _volumeSlider->MeterLevels(v);

    /* TODO: check whether we should show the OSD on startup or not. If so, post
     * a MSG_VOL_CHNG so that the volume level (or mute) is displayed: */
    SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
}

VolumeOSD::~VolumeOSD() {
    DestroyMenu(_deviceMenu);
    DestroyMenu(_menu);
    delete _icon;
    delete _volumeSlider;
    delete _callbackMeter;
    _volumeCtrl->Dispose();
}

void VolumeOSD::UpdateDeviceMenu() {
    if (_menu == NULL || _deviceMenu == NULL) {
        return;
    }

    /* Remove any devices currently in the menu first */
    for (unsigned int i = 0; i < _deviceList.size(); ++i) {
        RemoveMenu(_deviceMenu, 0, MF_BYPOSITION);
    }
    _deviceList.clear();

    std::list<VolumeController::DeviceInfo> devices
        = _volumeCtrl->ListDevices();
    std::wstring currentDeviceId = _volumeCtrl->DeviceId();

    int menuItem = MENU_DEVICE;
    for (VolumeController::DeviceInfo device : devices) {
        unsigned int flags = MF_ENABLED;
        if (currentDeviceId == device.id) {
            flags |= MF_CHECKED;
        }

        InsertMenu(_deviceMenu, -1, flags, menuItem++, device.name.c_str());
        _deviceList.push_back(device);
    }
}

void VolumeOSD::LoadSkin() {
    Settings *settings = Settings::Instance();
    Skin *skin = SkinManager::Instance()->CurrentSkin();

    /* Volume OSD */
    /* TODO: should make sure this isn't NULL! */
    _mWnd.BackgroundImage(skin->volumeBackground);

    if (skin->volumeMask != NULL) {
        _mWnd.EnableGlass(skin->volumeMask);
    }

    for (Meter *m : skin->volumeMeters) {
        _mWnd.AddMeter(m);
    }

    /* Add a callback meter with the default volume increment for sounds */
    _callbackMeter = new CallbackMeter(
        skin->DefaultVolumeUnits(), *this);
    _mWnd.AddMeter(_callbackMeter);

    /* Default volume increment */
    _defaultIncrement = (float) (10000 / skin->DefaultVolumeUnits()) / 10000.0f;
    CLOG(L"Default volume increment: %f", _defaultIncrement);

    _mWnd.Update();

    /* Mute OSD */
    /* TODO: NULL check*/
    _muteWnd.BackgroundImage(skin->muteBackground);

    if (skin->muteMask != NULL) {
        _muteWnd.EnableGlass(skin->muteMask);
    }
    _muteWnd.Update();

    /* Create clones for additional monitors */
    std::vector<Monitor> monitors = ActiveMonitors();
    for (unsigned int i = 1; i < monitors.size(); ++i) {
        _mWnd.Clone();
        _muteWnd.Clone();
    }
    UpdateWindowPositions(monitors);

    /* Set up notification icon */
    if (settings->NotifyIconEnabled()) {
        _iconImages = skin->volumeIconset;
        if (_iconImages.size() > 0) {
            _icon = new NotifyIcon(_hWnd, L"3RVX", _iconImages[0]);
        }
    }

    /* Enable sound effects, if any */
    if (settings->SoundEffectsEnabled()) {
        if (skin->volumeSound) {
            _soundPlayer = skin->volumeSound;
        }
    }
}

void VolumeOSD::MeterLevels(float level) {
    _mWnd.MeterLevels(level);
    _mWnd.Update();
}

void VolumeOSD::MeterChangeCallback(int units) {
    if (_soundPlayer) {
        _soundPlayer->Play();
    }
}

void VolumeOSD::Hide() {
    _mWnd.Hide(false);
    _muteWnd.Hide(false);
}

void VolumeOSD::HideIcon() {
    delete _icon;
}

void VolumeOSD::UpdateIcon() {
    UpdateIconImage();
    UpdateIconTip();
}

void VolumeOSD::UpdateIconImage() {
    if (_icon == NULL) {
        return;
    }

    int icon = 0;
    if (_volumeCtrl->Muted() == false) {
        int vUnits = _iconImages.size() - 1;
        icon = (int) ceil(_volumeCtrl->Volume() * vUnits);
    }

    if (icon != _lastIcon) {
        _icon->UpdateIcon(_iconImages[icon]);
        _lastIcon = icon;
    }
}

void VolumeOSD::UpdateIconTip() {
    if (_icon == NULL) {
        return;
    }

    if (_volumeCtrl->Muted()) {
        _icon->UpdateToolTip(_selectedDesc + L": Muted");
    } else {
        float v = _volumeCtrl->Volume();
        std::wstring perc = std::to_wstring((int) (v * 100.0f));
        std::wstring level = _selectedDesc + L": " + perc + L"%";
        _icon->UpdateToolTip(level);
    }
}

void VolumeOSD::UnMute() {
    if (_volumeCtrl->Muted() == true) {
        _volumeCtrl->Muted(false);
    }
}

void VolumeOSD::ProcessHotkeys(HotkeyInfo &hki) {
    switch (hki.action) {
    case HotkeyInfo::IncreaseVolume:
    case HotkeyInfo::DecreaseVolume:
        UnMute();
        ProcessVolumeHotkeys(hki);
        break;

    case HotkeyInfo::SetVolume: {
        HotkeyInfo::VolumeKeyArgTypes type = HotkeyInfo::VolumeArgType(hki);
        if (type == HotkeyInfo::VolumeKeyArgTypes::NoArgs) {
            return;
        } else if (type == HotkeyInfo::VolumeKeyArgTypes::Units) {
            int numUnits = hki.ArgToInt(0);
            _volumeCtrl->Volume(numUnits * _defaultIncrement);
        } else if (type == HotkeyInfo::VolumeKeyArgTypes::Percentage) {
            double perc = hki.ArgToDouble(0);
            _volumeCtrl->Volume((float) perc);
        }
    }

        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::Mute:
        _volumeCtrl->ToggleMute();
        SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
        break;

    case HotkeyInfo::VolumeSlider:
        if (_volumeSlider->Visible()) {
            /* If the slider is already visible, user must want to close it. */
            _volumeSlider->Hide();
        } else {
            SendMessage(_hWnd, MSG_NOTIFYICON, NULL, WM_LBUTTONUP);
        }
        break;
    }
}

void VolumeOSD::ProcessVolumeHotkeys(HotkeyInfo &hki) {
    float currentVol = _volumeCtrl->Volume();
    HotkeyInfo::VolumeKeyArgTypes type = HotkeyInfo::VolumeArgType(hki);

    if (type == HotkeyInfo::VolumeKeyArgTypes::Percentage) {
        /* Deal with percentage-based amounts */
        float amount = (hki.ArgToDouble(0) / 100.0f);
        if (hki.action == HotkeyInfo::HotkeyActions::DecreaseVolume) {
            amount = -amount;
        }
        _volumeCtrl->Volume(currentVol + amount);
    } else {
        /* Unit-based amounts */
        int unitIncrement = 1;
        int currentUnit = _callbackMeter->CalcUnits();
        if (currentVol <= 0.000001f) {
            currentUnit = 0;
        }

        if (hki.action == HotkeyInfo::DecreaseVolume) {
            unitIncrement = -1;
        }

        if (type == HotkeyInfo::VolumeKeyArgTypes::Units) {
            unitIncrement *= hki.ArgToInt(0);
        }

        _volumeCtrl->Volume(
            (float) (currentUnit + unitIncrement) * _defaultIncrement);
    }

    /* Tell 3RVX that we changed the volume */
    SendMessage(_hWnd, MSG_VOL_CHNG, NULL, (LPARAM) 1);
}

void VolumeOSD::UpdateWindowPositions(std::vector<Monitor> &monitors) {
    PositionWindow(monitors[0], _mWnd);
    PositionWindow(monitors[0], _muteWnd);

    std::vector<LayeredWnd *> meterClones = _mWnd.Clones();
    std::vector<LayeredWnd *> muteClones = _muteWnd.Clones();
    for (unsigned int i = 1; i < monitors.size(); ++i) {
        PositionWindow(monitors[i], *meterClones[i - 1]);
        PositionWindow(monitors[i], *muteClones[i - 1]);
    }
}

void VolumeOSD::UpdateVolumeState() {
    float v = _volumeCtrl->Volume();
    MeterLevels(v);
    _volumeSlider->MeterLevels(v);
    UpdateIcon();
}

LRESULT
VolumeOSD::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == MSG_VOL_CHNG) {
        float v = _volumeCtrl->Volume();
        bool muteState = _volumeCtrl->Muted();

        _volumeSlider->MeterLevels(v);
        UpdateIcon();

        if (wParam > 0) {
            /* We manually post a MSG_VOL_CHNG when modifying the volume with
             * hotkeys, so this CoreAudio-generated event can be ignored
             * by the OSD. */
            CLOG(L"Ignoring volume change notification generated by 3RVX");
            return DefWindowProc(hWnd, message, wParam, lParam);
        }

        CLOG(L"Volume change notification:\nNew level: %f\nPrevious: %f",
            v, _lastVolume);
        if (lParam == 0 && (muteState == _muted)) {
            if (abs(v - _lastVolume) < 0.0001f) {
                CLOG(L"No change in volume detected; ignoring event.");
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        _lastVolume = v;
        _muted = muteState;

        if (_volumeSlider->Visible() == false) {
            if (_volumeCtrl->Muted() || v == 0.0f) {
                _muteWnd.Show();
                _mWnd.Hide(false);
            } else {
                MeterLevels(v);
                _mWnd.Show();
                _muteWnd.Hide(false);
            }
            HideOthers(Volume);
        }

    } else if (message == MSG_VOL_DEVCHNG) {
        CLOG(L"Volume device change detected.");
        if (_selectedDevice == L"") {
            _volumeCtrl->SelectDefaultDevice();
        } else {
            HRESULT hr = _volumeCtrl->SelectDevice(_selectedDevice);
            if (FAILED(hr)) {
                _volumeCtrl->SelectDefaultDevice();
            }
        }
        _selectedDesc = _volumeCtrl->DeviceDesc();
        UpdateDeviceMenu();
        UpdateVolumeState();

    } else if (message == MSG_NOTIFYICON) {
        if (lParam == WM_LBUTTONUP) {
            _volumeSlider->MeterLevels(_volumeCtrl->Volume());
            _volumeSlider->Show();
        } else if (lParam == WM_RBUTTONUP) {
            POINT p;
            GetCursorPos(&p);
            SetForegroundWindow(hWnd);
            TrackPopupMenuEx(_menu, _menuFlags, p.x, p.y, _hWnd, NULL);
            PostMessage(hWnd, WM_NULL, 0, 0);
        }

    } else if (message == WM_COMMAND) {
        int menuItem = LOWORD(wParam);
        switch (menuItem) {
        case MENU_SETTINGS:
            Settings::LaunchSettingsApp();
            break;

        case MENU_MIXER: {
            CLOG(L"Menu: Mixer");
            HINSTANCE code = ShellExecute(NULL, L"open", L"sndvol",
                NULL, NULL, SW_SHOWNORMAL);
            break;
        }

        case MENU_EXIT:
            CLOG(L"Menu: Exit: %d", (int) _masterWnd);
            SendMessage(_masterWnd, WM_CLOSE, NULL, NULL);
            break;
        }

        /* Device menu items */
        if ((menuItem & MENU_DEVICE) > 0) {
            int device = menuItem & 0x0FFF;
            VolumeController::DeviceInfo selectedDev = _deviceList[device];
            if (selectedDev.id != _volumeCtrl->DeviceId()) {
                /* A different device has been selected */
                CLOG(L"Changing to volume device: %s",
                    selectedDev.name.c_str());
                _volumeCtrl->SelectDevice(selectedDev.id);
                UpdateDeviceMenu();
                UpdateVolumeState();
            }
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ExampleDiffusion.h"

// If we use a material pointer we need to include the
// material class
#include "Material.h"

/**
 * This function defines the valid parameters for
 * this Kernel and their default values
 */
template<>
InputParameters validParams<ExampleDiffusion>()
{
  InputParameters params = validParams<Diffusion>();
  return params;
}

ExampleDiffusion::ExampleDiffusion(const std::string & name,
                                   InputParameters parameters)
  :Diffusion(name,parameters),
   _diffusivity(getMaterialProperty<Real>("diffusivity"))
{}

Real
ExampleDiffusion::computeQpResidual()
{
  // We're dereferencing the _diffusivity pointer to get to the
  // material properties vector... which gives us one property
  // value per quadrature point.

  // Also... we're reusing the Diffusion Kernel's residual
  // so that we don't have to recode that.
  return _diffusivity[_qp]*Diffusion::computeQpResidual();
}

Real
ExampleDiffusion::computeQpJacobian()
{
  // We're dereferencing the _diffusivity pointer to get to the
  // material properties vector... which gives us one property
  // value per quadrature point.

  // Also... we're reusing the Diffusion Kernel's residual
  // so that we don't have to recode that.
  return _diffusivity[_qp]*Diffusion::computeQpJacobian();
}
<commit_msg>No longer need to #include "Material.h" in this file.<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ExampleDiffusion.h"

/**
 * This function defines the valid parameters for
 * this Kernel and their default values
 */
template<>
InputParameters validParams<ExampleDiffusion>()
{
  InputParameters params = validParams<Diffusion>();
  return params;
}

ExampleDiffusion::ExampleDiffusion(const std::string & name,
                                   InputParameters parameters)
  :Diffusion(name,parameters),
   _diffusivity(getMaterialProperty<Real>("diffusivity"))
{}

Real
ExampleDiffusion::computeQpResidual()
{
  // We're dereferencing the _diffusivity pointer to get to the
  // material properties vector... which gives us one property
  // value per quadrature point.

  // Also... we're reusing the Diffusion Kernel's residual
  // so that we don't have to recode that.
  return _diffusivity[_qp]*Diffusion::computeQpResidual();
}

Real
ExampleDiffusion::computeQpJacobian()
{
  // We're dereferencing the _diffusivity pointer to get to the
  // material properties vector... which gives us one property
  // value per quadrature point.

  // Also... we're reusing the Diffusion Kernel's residual
  // so that we don't have to recode that.
  return _diffusivity[_qp]*Diffusion::computeQpJacobian();
}
<|endoftext|>


<commit_before>/*  -*-c++-*-
 *  Copyright (C) 2009 Cedric Pinson <cedric.pinson@plopbyte.net>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <iostream>
#include <osgDB/ReadFile>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osg/Drawable>
#include <osg/MatrixTransform>

#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/RigTransformHardware>
#include <osgAnimation/MorphGeometry>
#include <osgAnimation/MorphTransformHardware>
#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/BoneMapVisitor>

#include <sstream>

static unsigned int getRandomValueinRange(unsigned int v)
{
    return static_cast<unsigned int>((rand() * 1.0 * v)/(RAND_MAX-1));
}

//osg::ref_ptr<osg::Program> program;
// show how to override the default RigTransformHardware for customized usage
struct MyRigTransformHardware : public osgAnimation::RigTransformHardware
{

    virtual bool init(osgAnimation::RigGeometry& rig)
    {
        if(!rig.getSkeleton() && !rig.getParents().empty())
        {
            osgAnimation::RigGeometry::FindNearestParentSkeleton finder;
            if(rig.getParents().size() > 1)
                osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << rig.getName() << " )" << std::endl;
            rig.getParents()[0]->accept(finder);

            if(!finder._root.valid())
            {
                osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << rig.getName() << " )" << std::endl;
                return false;
            }
            rig.setSkeleton(finder._root.get());
        }
        osgAnimation::BoneMapVisitor mapVisitor;
        rig.getSkeleton()->accept(mapVisitor);
        osgAnimation::BoneMap boneMap = mapVisitor.getBoneMap();

        if (!buildPalette(boneMap,rig) )
            return false;

        osg::Geometry& source = *rig.getSourceGeometry();
        osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
        if (!positionSrc)
        {
            OSG_WARN << "RigTransformHardware no vertex array in the geometry " << rig.getName() << std::endl;
            return false;
        }

        // copy shallow from source geometry to rig
        rig.copyFrom(source);

        osg::ref_ptr<osg::Program> program ;
        osg::ref_ptr<osg::Shader> vertexshader;
        osg::ref_ptr<osg::StateSet> stateset = rig.getOrCreateStateSet();

        //grab geom source program and vertex shader if _shader is not setted
        if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM)))
        {
            for(unsigned int i=0; i<program->getNumShaders(); ++i)
                if(program->getShader(i)->getType()==osg::Shader::VERTEX)
                {
                    vertexshader=program->getShader(i);
                    program->removeShader(vertexshader);

                }
        }
        else
        {
            program = new osg::Program;
            program->setName("HardwareSkinning");
        }
        //set default source if _shader is not user setted
        if (!vertexshader.valid())
        {
            if (!_shader.valid())
                vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"shaders/skinning.vert");
            else vertexshader=_shader;
        }

        if (!vertexshader.valid())
        {
            OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl;
            return false;
        }

        // replace max matrix by the value from uniform
        {
            std::string str = vertexshader->getShaderSource();
            std::string toreplace = std::string("MAX_MATRIX");
            std::size_t start = str.find(toreplace);
            if (std::string::npos != start)
            {
                std::stringstream ss;
                ss << getMatrixPaletteUniform()->getNumElements();
                str.replace(start, toreplace.size(), ss.str());
                vertexshader->setShaderSource(str);
            }
            else
            {
                OSG_INFO<< "MAX_MATRIX not found in Shader! " << str << std::endl;
            }
            OSG_INFO << "Shader " << str << std::endl;
        }

        unsigned int attribIndex = 11;
        unsigned int nbAttribs = getNumVertexAttrib();
        if(nbAttribs==0)
            OSG_WARN << "nbAttribs== " << nbAttribs << std::endl;
        for (unsigned int i = 0; i < nbAttribs; i++)
        {
            std::stringstream ss;
            ss << "boneWeight" << i;
            program->addBindAttribLocation(ss.str(), attribIndex + i);

            if(getVertexAttrib(i)->getNumElements()!=_nbVertices)
                OSG_WARN << "getVertexAttrib== " << getVertexAttrib(i)->getNumElements() << std::endl;
            rig.setVertexAttribArray(attribIndex + i, getVertexAttrib(i));
            OSG_INFO << "set vertex attrib " << ss.str() << std::endl;
        }

        program->addShader(vertexshader.get());
        stateset->removeUniform("nbBonesPerVertex");
        stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex));
        stateset->removeUniform("matrixPalette");
        stateset->addUniform(getMatrixPaletteUniform());

        stateset->removeAttribute(osg::StateAttribute::PROGRAM);
        if(!stateset->getAttribute(osg::StateAttribute::PROGRAM))
            stateset->setAttributeAndModes(program.get());

        _needInit = false;
        return true;
    }

};

struct SetupRigGeometry : public osg::NodeVisitor
{
    bool _hardware;
    SetupRigGeometry( bool hardware = true) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _hardware(hardware) {}

    void apply(osg::Geode& geode)
    {
        for (unsigned int i = 0; i < geode.getNumDrawables(); i++)
            apply(*geode.getDrawable(i));
    }
    void apply(osg::Drawable& geom)
    {
        if (_hardware)
        {
            osgAnimation::RigGeometry* rig = dynamic_cast<osgAnimation::RigGeometry*>(&geom);
            if (rig){
                rig->setRigTransformImplementation(new MyRigTransformHardware);
                osgAnimation::MorphGeometry *morph=dynamic_cast<osgAnimation::MorphGeometry*>(rig->getSourceGeometry());
                if(morph)morph->setMorphTransformImplementation(new osgAnimation::MorphTransformHardware);
            }
        }

#if 0
        if (geom.getName() != std::string("BoundingBox")) // we disable compute of bounding box for all geometry except our bounding box
            geom.setComputeBoundingBoxCallback(new osg::Drawable::ComputeBoundingBoxCallback);
//            geom.setInitialBound(new osg::Drawable::ComputeBoundingBoxCallback);
#endif
    }
};

osg::Group* createCharacterInstance(osg::Group* character, bool hardware)
{
    osg::ref_ptr<osg::Group> c ;
    if (hardware)
        c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL & ~osg::CopyOp::DEEP_COPY_PRIMITIVES & ~osg::CopyOp::DEEP_COPY_ARRAYS);
    else
        c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL);

    osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(c->getUpdateCallback());

    osgAnimation::BasicAnimationManager* anim = dynamic_cast<osgAnimation::BasicAnimationManager*>(animationManager);
    const osgAnimation::AnimationList& list = animationManager->getAnimationList();
    int v = getRandomValueinRange(list.size());
    if (list[v]->getName() == std::string("MatIpo_ipo"))
    {
        anim->playAnimation(list[v].get());
        v = (v + 1)%list.size();
    }

    anim->playAnimation(list[v].get());

    SetupRigGeometry switcher(hardware);
    c->accept(switcher);

    return c.release();
}

int main (int argc, char* argv[])
{
    std::cerr << "This example works better with nathan.osg" << std::endl;

    osg::ArgumentParser psr(&argc, argv);

    osgViewer::Viewer viewer(psr);

    bool hardware = true;
    int maxChar = 10;
    while (psr.read("--software"))
    {
        hardware = false;
    }
    while (psr.read("--number", maxChar)) {}

    osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFiles(psr);
    osg::ref_ptr<osg::Group> root = dynamic_cast<osg::Group*>(node.get());
    if (!root)
    {
        std::cout << psr.getApplicationName() <<": No data loaded" << std::endl;
        return 1;
    }

    {
        osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(root->getUpdateCallback());
        if(!animationManager)
        {
            osg::notify(osg::FATAL) << "no AnimationManagerBase found, updateCallback need to animate elements" << std::endl;
            return 1;
        }
    }

    osg::ref_ptr<osg::Group> scene = new osg::Group;

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the thread model handler
    viewer.addEventHandler(new osgViewer::ThreadingHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new osgViewer::HelpHandler(psr.getApplicationUsage()));

    // add the LOD Scale handler
    viewer.addEventHandler(new osgViewer::LODScaleHandler);

    // add the screen capture handler
    viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);

    viewer.setSceneData(scene.get());

    viewer.realize();

    double xChar = maxChar;
    double yChar = xChar * 9.0/16;
    for (double  i = 0.0; i < xChar; i++)
    {
        for (double  j = 0.0; j < yChar; j++)
        {

            osg::ref_ptr<osg::Group> c = createCharacterInstance(root.get(), hardware);
            osg::MatrixTransform* tr = new osg::MatrixTransform;
            tr->setMatrix(osg::Matrix::translate( 2.0 * (i - xChar * .5),
                                                  0.0,
                                                  2.0 * (j - yChar * .5)));
            tr->addChild(c.get());
            scene->addChild(tr);
        }
    }
    std::cout << "created " << xChar * yChar << " instance"  << std::endl;

    return viewer.run();
}

<commit_msg>update example to use a common program<commit_after>/*  -*-c++-*-
 *  Copyright (C) 2009 Cedric Pinson <cedric.pinson@plopbyte.net>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <iostream>
#include <osgDB/ReadFile>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osg/Drawable>
#include <osg/MatrixTransform>

#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/RigTransformHardware>
#include <osgAnimation/MorphGeometry>
#include <osgAnimation/MorphTransformHardware>
#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/BoneMapVisitor>

#include <sstream>

static unsigned int getRandomValueinRange(unsigned int v)
{
    return static_cast<unsigned int>((rand() * 1.0 * v)/(RAND_MAX-1));
}

osg::ref_ptr<osg::Program> CommonProgram;
// show how to override the default RigTransformHardware for customized usage
struct MyRigTransformHardware : public osgAnimation::RigTransformHardware
{
    int _maxmatrix;
    MyRigTransformHardware() : _maxmatrix(99){}
    virtual bool init(osgAnimation::RigGeometry& rig)
    {
        if(_perVertexInfluences.empty())
        {
            prepareData(rig);
            return false;
        }
        if(!rig.getSkeleton())
            return false;

        osgAnimation::BoneMapVisitor mapVisitor;
        rig.getSkeleton()->accept(mapVisitor);
        osgAnimation::BoneMap boneMap = mapVisitor.getBoneMap();

        if (!buildPalette(boneMap,rig) )
            return false;

        osg::Geometry& source = *rig.getSourceGeometry();
        osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());

        if (!positionSrc)
        {
            OSG_WARN << "RigTransformHardware no vertex array in the geometry " << rig.getName() << std::endl;
            return false;
        }

        // copy shallow from source geometry to rig
        rig.copyFrom(source);

        osg::ref_ptr<osg::Shader> vertexshader;
        osg::ref_ptr<osg::StateSet> stateset = rig.getOrCreateStateSet();
        if(!CommonProgram.valid()){
            CommonProgram   = new osg::Program;
            CommonProgram->setName("HardwareSkinning");

            //set default source if _shader is not user setted
            if (!vertexshader.valid())
            {
                    vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert");
            }

            if (!vertexshader.valid())
            {
                OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl;
                return false;
            }

            // replace max matrix by the value from uniform
            {
                std::string str = vertexshader->getShaderSource();
                std::string toreplace = std::string("MAX_MATRIX");
                std::size_t start = str.find(toreplace);
                if (std::string::npos != start)
                {
                    std::stringstream ss;
                    ss << _maxmatrix;//getMatrixPaletteUniform()->getNumElements();
                    str.replace(start, toreplace.size(), ss.str());
                    vertexshader->setShaderSource(str);
                }
                else
                {
                    OSG_WARN<< "MAX_MATRIX not found in Shader! " << str << std::endl;
                }
                OSG_INFO << "Shader " << str << std::endl;
            }
            CommonProgram->addShader(vertexshader.get());
        }
        unsigned int nbAttribs = getNumVertexAttrib();
        for (unsigned int i = 0; i < nbAttribs; i++)
        {
            std::stringstream ss;
            ss << "boneWeight" << i;
            CommonProgram->addBindAttribLocation(ss.str(), _minAttribIndex + i);
            rig.setVertexAttribArray(_minAttribIndex + i, getVertexAttrib(i));
            OSG_INFO << "set vertex attrib " << ss.str() << std::endl;
        }

        stateset->removeUniform("nbBonesPerVertex");
        stateset->addUniform(new osg::Uniform("nbBonesPerVertex",_bonesPerVertex));

        stateset->removeUniform("matrixPalette");
        stateset->addUniform(_uniformMatrixPalette);

        stateset->setAttribute(CommonProgram.get());

        _needInit = false;
        return true;
    }

};

struct SetupRigGeometry : public osg::NodeVisitor
{
    bool _hardware;
    SetupRigGeometry( bool hardware = true) : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _hardware(hardware) {}

    void apply(osg::Geode& geode)
    {
        for (unsigned int i = 0; i < geode.getNumDrawables(); i++)
            apply(*geode.getDrawable(i));
    }
    void apply(osg::Drawable& geom)
    {
        if (_hardware)
        {
            osgAnimation::RigGeometry* rig = dynamic_cast<osgAnimation::RigGeometry*>(&geom);
            if (rig){
                rig->setRigTransformImplementation(new MyRigTransformHardware);
                osgAnimation::MorphGeometry *morph=dynamic_cast<osgAnimation::MorphGeometry*>(rig->getSourceGeometry());
                if(morph)morph->setMorphTransformImplementation(new osgAnimation::MorphTransformHardware);
            }
        }

#if 0
        if (geom.getName() != std::string("BoundingBox")) // we disable compute of bounding box for all geometry except our bounding box
            geom.setComputeBoundingBoxCallback(new osg::Drawable::ComputeBoundingBoxCallback);
//            geom.setInitialBound(new osg::Drawable::ComputeBoundingBoxCallback);
#endif
    }
};

osg::Group* createCharacterInstance(osg::Group* character, bool hardware)
{
    osg::ref_ptr<osg::Group> c ;
    if (hardware)
        c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL & ~osg::CopyOp::DEEP_COPY_PRIMITIVES & ~osg::CopyOp::DEEP_COPY_ARRAYS);
    else
        c = osg::clone(character, osg::CopyOp::DEEP_COPY_ALL);

    osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(c->getUpdateCallback());

    osgAnimation::BasicAnimationManager* anim = dynamic_cast<osgAnimation::BasicAnimationManager*>(animationManager);
    const osgAnimation::AnimationList& list = animationManager->getAnimationList();
    int v = getRandomValueinRange(list.size());
    if (list[v]->getName() == std::string("MatIpo_ipo"))
    {
        anim->playAnimation(list[v].get());
        v = (v + 1)%list.size();
    }

    anim->playAnimation(list[v].get());

    SetupRigGeometry switcher(hardware);
    c->accept(switcher);

    return c.release();
}

int main (int argc, char* argv[])
{
    std::cerr << "This example works better with nathan.osg" << std::endl;

    osg::ArgumentParser psr(&argc, argv);

    osgViewer::Viewer viewer(psr);

    bool hardware = true;
    int maxChar = 10;
    while (psr.read("--software"))
    {
        hardware = false;
    }
    while (psr.read("--number", maxChar)) {}

    osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFiles(psr);
    osg::ref_ptr<osg::Group> root = dynamic_cast<osg::Group*>(node.get());
    if (!root)
    {
        std::cout << psr.getApplicationName() <<": No data loaded" << std::endl;
        return 1;
    }

    {
        osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(root->getUpdateCallback());
        if(!animationManager)
        {
            osg::notify(osg::FATAL) << "no AnimationManagerBase found, updateCallback need to animate elements" << std::endl;
            return 1;
        }
    }

    osg::ref_ptr<osg::Group> scene = new osg::Group;

    // add the state manipulator
    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the thread model handler
    viewer.addEventHandler(new osgViewer::ThreadingHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new osgViewer::HelpHandler(psr.getApplicationUsage()));

    // add the LOD Scale handler
    viewer.addEventHandler(new osgViewer::LODScaleHandler);

    // add the screen capture handler
    viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);

    viewer.setSceneData(scene.get());

    viewer.realize();

    double xChar = maxChar;
    double yChar = xChar * 9.0/16;
    for (double  i = 0.0; i < xChar; i++)
    {
        for (double  j = 0.0; j < yChar; j++)
        {

            osg::ref_ptr<osg::Group> c = createCharacterInstance(root.get(), hardware);
            osg::MatrixTransform* tr = new osg::MatrixTransform;
            tr->setMatrix(osg::Matrix::translate( 2.0 * (i - xChar * .5),
                                                  0.0,
                                                  2.0 * (j - yChar * .5)));
            tr->addChild(c.get());
            scene->addChild(tr);
        }
    }
    std::cout << "created " << xChar * yChar << " instance"  << std::endl;

    return viewer.run();
}

<|endoftext|>


<commit_before>/*

 MIT License

 Copyright (c) 2017 Leonid Keselman

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 https://github.com/leonidk/imshow/blob/master/LICENSE

 */

#include "imshow/imshow.h"
#include <GLFW/glfw3.h>
#include <mutex>
#include <unordered_map>
#include <string>
#include <stdint.h>
#include <memory>
#include <iostream>
#include <vector>

#pragma comment( lib, "opengl32" )

namespace glfw
{
char g_key;
bool g_key_update = false;
bool g_close = true;

std::mutex g_mutex;
struct winState
{
    GLFWwindow* win;
    GLuint tex;
    Image image;
    int x, y; // screen position
};
std::unordered_map<std::string, winState> g_windows;

static winState * getWindowState(GLFWwindow *window)
{
    for (auto & win : g_windows)
    {
        if (win.second.win == window)
        {
            return &win.second;
        }
    }
    return nullptr;
}

static void render_callback(GLFWwindow * window)
{
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushMatrix();

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_ALPHA);

    glClearColor(0, 0, 0, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    {
        const auto win = getWindowState(window);
        glBindTexture(GL_TEXTURE_2D, win->tex);

        glBegin(GL_QUADS);
        glTexCoord2f(0, 1);
        glVertex2f(-1, -1);
        glTexCoord2f(1, 1);
        glVertex2f(1, -1);
        glTexCoord2f(1, 0);
        glVertex2f(1, 1);
        glTexCoord2f(0, 0);
        glVertex2f(-1, 1);
        glEnd();

        glBindTexture(GL_TEXTURE_2D, 0);
    }

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_ALPHA);

    glPopMatrix();
    glPopAttrib();
}

static void position_callback(GLFWwindow *window, int x, int y)
{
    if(auto win = getWindowState(window))
    {
        win->x = x;
        win->y = y;
    }
}

static void focus_callback(GLFWwindow *window, int focus)
{
    if(focus)
    {
        glfwMakeContextCurrent(window);
        render_callback(window);
        glfwSwapBuffers(window);
    }
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS)
    {
        g_key = tolower(key);
        g_key_update = true;
    }
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    const auto win = getWindowState(window);
    const float wScale = ((float)width) / ((float)win->image.width);
    const float hScale = ((float)height) / ((float)win->image.height);
    const float minScale = (wScale < hScale) ? wScale : hScale;
    const int wShift = (int)nearbyint((width - minScale*win->image.width) / 2.0f);
    const int hShift = (int)nearbyint((height - minScale*win->image.height) / 2.0f);

    glfwMakeContextCurrent(window);
    glViewport(wShift, hShift, (int)nearbyint(win->image.width*minScale), (int)nearbyint(win->image.height*minScale));
    render_callback(window);
    glfwSwapBuffers(window);
}

static void refresh_callback(GLFWwindow *window)
{
    glfwMakeContextCurrent(window);
    render_callback(window);
    glfwSwapBuffers(window);
}

static void window_close_callback(GLFWwindow *window)
{
    // For a key update for the main loop
    g_close = true;
    glfwMakeContextCurrent(window);
    glfwSetWindowShouldClose(window, GLFW_TRUE);
    glfwPostEmptyEvent();
}

static void eraseWindow(std::unordered_map<std::string, winState>::const_iterator iter)
{
    // Always invalidate window with existing name
    glfwMakeContextCurrent(iter->second.win);
    glfwDestroyWindow(iter->second.win);
    glDeleteTextures(1,&iter->second.tex);
    g_windows.erase(iter);
}

static void eraseWindow(const char *name)
{
    auto iter = g_windows.find(name);
    if(iter != g_windows.end())
    {
        eraseWindow(iter);
    }
}

void imshow(const char * name, const Image & img)
{
    std::unique_lock<std::mutex> lock(g_mutex);

    if(g_windows.empty())
    {
        glfwInit();
    }

    std::string s_name(name);

    bool hasWindow = false;
    int x, y;

    auto iter = g_windows.find(s_name);
    if(iter != g_windows.end())
    {
        hasWindow = true;
        x = iter->second.x;
        y = iter->second.y;

        eraseWindow(iter);
        iter = g_windows.end();
    }

    if (iter == g_windows.end())
    {
        // OS X:
        // * must create window prior to glGenTextures on OS X
        // * glfw complains w/ the following error on >= 10.12
        auto window = glfwCreateWindow(img.width, img.height, s_name.c_str(), NULL, NULL);

        glfwMakeContextCurrent(window);

        glfwSetKeyCallback(window, key_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwSetWindowRefreshCallback(window, render_callback);
        glfwSetWindowFocusCallback(window, focus_callback);
        glfwSetWindowPosCallback(window, position_callback);
        glfwSetWindowRefreshCallback(window, refresh_callback);
        glfwSetWindowCloseCallback(window, window_close_callback);

        GLuint tex;
        glGenTextures(1, &tex);

        if(hasWindow)
        {
            glfwSetWindowPos(window, x, y);
        }
        else
        {
            glfwGetWindowPos(window, &x, &y);
        }
        g_windows[s_name] = {window, tex, img, x, y};
    }

    GLuint format, type;
    switch (img.type)
    {
        case IM_8U:
            type = GL_UNSIGNED_BYTE;
            break;
        case IM_8I:
            type = GL_BYTE;
            break;
        case IM_16U:
            type = GL_UNSIGNED_SHORT;
            break;
        case IM_16I:
            type = GL_SHORT;
            break;
        case IM_32U:
            type = GL_UNSIGNED_INT;
            break;
        case IM_32I:
            type = GL_INT;
            break;
        case IM_32F:
            type = GL_FLOAT;
            break;
        case IM_64F:
            type = GL_DOUBLE;
            break;
        default:
            return;
    }
    switch (img.channels)
    {
        case 0:
        case 1:
            format = GL_LUMINANCE;
            break;
        case 2:
            format = GL_LUMINANCE_ALPHA;
            break;
        case 3:
            format = GL_BGR;
            break;
        case 4:
            format = GL_BGRA;
            break;
    }

    auto window = g_windows[s_name];
    glfwMakeContextCurrent(window.win);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glBindTexture(GL_TEXTURE_2D, window.tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.width, img.height, 0, format, type, img.data);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glBindTexture(GL_TEXTURE_2D, 0);

    render_callback(window.win);
    glfwSwapBuffers(window.win);
}

char getKey(bool wait)
{
    std::unique_lock<std::mutex> lock(g_mutex);
    g_close = false;

    std::vector<std::string> toDelete;
    for (const auto & win : g_windows)
    {
        if (glfwWindowShouldClose(win.second.win))
        {
            g_close = true;
            toDelete.push_back(win.first);
        }
        else
        {
            glfwMakeContextCurrent(win.second.win);
            glfwSwapBuffers(win.second.win);
            lock.unlock();
            if (wait && !g_close)
            {
                do
                {
                    glfwWaitEvents();
                    if(glfwWindowShouldClose(win.second.win))
                    {
                        g_close = true;
                        toDelete.push_back(win.first);
                    }
                }
                while (!g_key_update && !g_close);
            }
            else
            {
                glfwPollEvents();
            }
            lock.lock();

            if (!g_key_update)
            {
                g_key = '\0';
            }
        }
    }

    g_key_update = false;
    for (const auto & name : toDelete)
    {
        eraseWindow(name.c_str());
    }
    return g_key;
}
}
<commit_msg>fix startup aspect ratio<commit_after>/*

 MIT License

 Copyright (c) 2017 Leonid Keselman

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.

 https://github.com/leonidk/imshow/blob/master/LICENSE

 */

#include "imshow/imshow.h"
#include <GLFW/glfw3.h>
#include <mutex>
#include <unordered_map>
#include <string>
#include <stdint.h>
#include <memory>
#include <iostream>
#include <vector>

#pragma comment( lib, "opengl32" )

namespace glfw
{
char g_key;
bool g_key_update = false;
bool g_close = true;

std::mutex g_mutex;
struct winState
{
    GLFWwindow* win;
    GLuint tex;
    Image image;
    int x, y; // screen position
};
std::unordered_map<std::string, winState> g_windows;

static winState * getWindowState(GLFWwindow *window)
{
    for (auto & win : g_windows)
    {
        if (win.second.win == window)
        {
            return &win.second;
        }
    }
    return nullptr;
}

static void render_callback(GLFWwindow * window)
{
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushMatrix();

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_ALPHA);

    glClearColor(0, 0, 0, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    {
        const auto win = getWindowState(window);
        glBindTexture(GL_TEXTURE_2D, win->tex);

        glBegin(GL_QUADS);
        glTexCoord2f(0, 1);
        glVertex2f(-1, -1);
        glTexCoord2f(1, 1);
        glVertex2f(1, -1);
        glTexCoord2f(1, 0);
        glVertex2f(1, 1);
        glTexCoord2f(0, 0);
        glVertex2f(-1, 1);
        glEnd();

        glBindTexture(GL_TEXTURE_2D, 0);
    }

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_ALPHA);

    glPopMatrix();
    glPopAttrib();
}

static void position_callback(GLFWwindow *window, int x, int y)
{
    if(auto win = getWindowState(window))
    {
        win->x = x;
        win->y = y;
    }
}

static void focus_callback(GLFWwindow *window, int focus)
{
    if(focus)
    {
        glfwMakeContextCurrent(window);
        render_callback(window);
        glfwSwapBuffers(window);
    }
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (action == GLFW_PRESS)
    {
        g_key = tolower(key);
        g_key_update = true;
    }
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    const auto win = getWindowState(window);
    const float wScale = ((float)width) / ((float)win->image.width);
    const float hScale = ((float)height) / ((float)win->image.height);
    const float minScale = (wScale < hScale) ? wScale : hScale;
    const int wShift = (int)nearbyint((width - minScale*win->image.width) / 2.0f);
    const int hShift = (int)nearbyint((height - minScale*win->image.height) / 2.0f);

    glfwMakeContextCurrent(window);
    glViewport(wShift, hShift, (int)nearbyint(win->image.width*minScale), (int)nearbyint(win->image.height*minScale));
    render_callback(window);
    glfwSwapBuffers(window);
}

static void refresh_callback(GLFWwindow *window)
{
    glfwMakeContextCurrent(window);
    render_callback(window);
    glfwSwapBuffers(window);
}

static void window_close_callback(GLFWwindow *window)
{
    // For a key update for the main loop
    g_close = true;
    glfwMakeContextCurrent(window);
    glfwSetWindowShouldClose(window, GLFW_TRUE);
    glfwPostEmptyEvent();
}

static void eraseWindow(std::unordered_map<std::string, winState>::const_iterator iter)
{
    // Always invalidate window with existing name
    glfwMakeContextCurrent(iter->second.win);
    glfwDestroyWindow(iter->second.win);
    glDeleteTextures(1,&iter->second.tex);
    g_windows.erase(iter);
}

static void eraseWindow(const char *name)
{
    auto iter = g_windows.find(name);
    if(iter != g_windows.end())
    {
        eraseWindow(iter);
    }
}

void imshow(const char * name, const Image & img)
{
    std::unique_lock<std::mutex> lock(g_mutex);

    if(g_windows.empty())
    {
        glfwInit();
    }

    std::string s_name(name);

    bool hasWindow = false;
    int x, y;

    auto iter = g_windows.find(s_name);
    if(iter != g_windows.end())
    {
        hasWindow = true;
        x = iter->second.x;
        y = iter->second.y;

        eraseWindow(iter);
        iter = g_windows.end();
    }

    if (iter == g_windows.end())
    {
        // OS X:
        // * must create window prior to glGenTextures on OS X
        // * glfw complains w/ the following error on >= 10.12
        auto window = glfwCreateWindow(img.width, img.height, s_name.c_str(), NULL, NULL);

        glfwMakeContextCurrent(window);

        glfwSetKeyCallback(window, key_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        glfwSetWindowRefreshCallback(window, render_callback);
        glfwSetWindowFocusCallback(window, focus_callback);
        glfwSetWindowPosCallback(window, position_callback);
        glfwSetWindowRefreshCallback(window, refresh_callback);
        glfwSetWindowCloseCallback(window, window_close_callback);

        GLuint tex;
        glGenTextures(1, &tex);

        if(hasWindow)
        {
            glfwSetWindowPos(window, x, y);
        }
        else
        {
            glfwGetWindowPos(window, &x, &y);
        }
        g_windows[s_name] = {window, tex, img, x, y};
    }

    GLuint format, type;
    switch (img.type)
    {
        case IM_8U:
            type = GL_UNSIGNED_BYTE;
            break;
        case IM_8I:
            type = GL_BYTE;
            break;
        case IM_16U:
            type = GL_UNSIGNED_SHORT;
            break;
        case IM_16I:
            type = GL_SHORT;
            break;
        case IM_32U:
            type = GL_UNSIGNED_INT;
            break;
        case IM_32I:
            type = GL_INT;
            break;
        case IM_32F:
            type = GL_FLOAT;
            break;
        case IM_64F:
            type = GL_DOUBLE;
            break;
        default:
            return;
    }
    switch (img.channels)
    {
        case 0:
        case 1:
            format = GL_LUMINANCE;
            break;
        case 2:
            format = GL_LUMINANCE_ALPHA;
            break;
        case 3:
            format = GL_BGR;
            break;
        case 4:
            format = GL_BGRA;
            break;
    }

    auto window = g_windows[s_name];
    glfwMakeContextCurrent(window.win);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glBindTexture(GL_TEXTURE_2D, window.tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.width, img.height, 0, format, type, img.data);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glBindTexture(GL_TEXTURE_2D, 0);

    // Retrieve actual size of allocated window framebuffer:
    int width, height;
    glfwGetFramebufferSize(window.win, &width, &height);
    framebuffer_size_callback(window.win, width, height);
}

char getKey(bool wait)
{
    std::unique_lock<std::mutex> lock(g_mutex);
    g_close = false;

    std::vector<std::string> toDelete;
    for (const auto & win : g_windows)
    {
        if (glfwWindowShouldClose(win.second.win))
        {
            g_close = true;
            toDelete.push_back(win.first);
        }
        else
        {
            glfwMakeContextCurrent(win.second.win);
            glfwSwapBuffers(win.second.win);
            lock.unlock();
            if (wait && !g_close)
            {
                do
                {
                    glfwWaitEvents();
                    if(glfwWindowShouldClose(win.second.win))
                    {
                        g_close = true;
                        toDelete.push_back(win.first);
                    }
                }
                while (!g_key_update && !g_close);
            }
            else
            {
                glfwPollEvents();
            }
            lock.lock();

            if (!g_key_update)
            {
                g_key = '\0';
            }
        }
    }

    g_key_update = false;
    for (const auto & name : toDelete)
    {
        eraseWindow(name.c_str());
    }
    return g_key;
}
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Michal Uricar
 * Copyright (C) 2012 Michal Uricar
 */

#include <shogun/classifier/svm/LibLinear.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/io/SGIO.h>
#include <shogun/labels/MulticlassLabels.h>
#include <shogun/labels/StructuredLabels.h>
#include <shogun/lib/common.h>
#include <shogun/loss/HingeLoss.h>
#include <shogun/machine/LinearMulticlassMachine.h>
#include <shogun/mathematics/Math.h>
#include <shogun/multiclass/MulticlassOneVsRestStrategy.h>
#include <shogun/structure/MulticlassSOLabels.h>
#include <shogun/structure/MulticlassModel.h>
#include <shogun/structure/DualLibQPBMSOSVM.h>
#include <shogun/io/streaming/StreamingAsciiFile.h>
#include <shogun/features/streaming/StreamingSparseFeatures.h>

using namespace shogun;

/** Reads multiclass trainig data stored in svmlight format (i.e. label nz_idx_1:value1 nz_idx_2:value2 ... nz_idx_N:valueN )
 *
 * @param fname    path to file with training data
 * @param DIM      dimension of features
 * @param N        number of feature vectors
 * @param labs     vector with labels
 * @param feats    matrix with features
 */
void read_data(const char fname[], uint32_t DIM, uint32_t N, SGVector< float64_t > *labs, SGMatrix< float64_t > *feats)
{
	CStreamingAsciiFile* file=new CStreamingAsciiFile(fname);
	SG_REF(file);

	CStreamingSparseFeatures< float64_t >* stream_features=
		new CStreamingSparseFeatures< float64_t >(file, true, 1024);
	SG_REF(stream_features);

	SGVector<float64_t > vec(DIM);

	stream_features->start_parser();

	uint32_t num_vectors=0;

	while( stream_features->get_next_example() )
	{
		vec.zero();
		stream_features->add_to_dense_vec(1.0, vec, DIM);

		(*labs)[num_vectors]=stream_features->get_label();

		for(uint32_t i=0; i<DIM; ++i)
		{
			(*feats)[num_vectors*DIM+i]=vec[i];
		}

		num_vectors++;
		stream_features->release_example();
	}

	stream_features->end_parser();

	SG_UNREF(stream_features);
}

int main(int argc, char * argv[])
{
	// initialization
	//-------------------------------------------------------------------------

	float64_t lambda=0.01, eps=0.01;
	bool icp=1;
	uint32_t cp_models=1;
	ESolver solver=BMRM;
	uint32_t feat_dim, num_feat;

	init_shogun_with_defaults();

	if (argc < 8)
	{
		SG_SERROR("Usage: so_multiclass_BMRM <data.in> <feat_dim> <num_feat> <lambda> <icp> <epsilon> <solver> [<cp_models>]\n");
		return -1;
	}

	SG_SPRINT("arg[1] = %s\n", argv[1]);

	feat_dim=::atoi(argv[2]);
	num_feat=::atoi(argv[3]);
	lambda=::atof(argv[4]);
	icp=::atoi(argv[5]);
	eps=::atof(argv[6]);

	if (strcmp("BMRM", argv[7])==0)
		solver=BMRM;

	if (strcmp("PPBMRM", argv[7])==0)
		solver=PPBMRM;

	if (strcmp("P3BMRM", argv[7])==0)
		solver=P3BMRM;

	if (argc > 8)
	{
		cp_models=::atoi(argv[8]);
	}

	SGVector< float64_t >* labs=
		new SGVector< float64_t >(num_feat);

	SGMatrix< float64_t >* feats=
		new SGMatrix< float64_t >(feat_dim, num_feat);

	// read data
	read_data(argv[1], feat_dim, num_feat, labs, feats);

	// Create train labels
	CMulticlassSOLabels* labels = new CMulticlassSOLabels(*labs);

	// Create train features
	CDenseFeatures< float64_t >* features =
		new CDenseFeatures< float64_t >(*feats);

	// Create structured model
	CMulticlassModel* model = new CMulticlassModel(features, labels);

	// Create loss function
	CHingeLoss* loss = new CHingeLoss();

	// Create SO-SVM
	CDualLibQPBMSOSVM* sosvm =
		new CDualLibQPBMSOSVM(
				model,
				loss,
				labels,
				lambda);
	SG_REF(sosvm);

	sosvm->set_cleanAfter(10);
	sosvm->set_cleanICP(icp);
	sosvm->set_TolRel(eps);
	sosvm->set_cp_models(cp_models);
	sosvm->set_solver(solver);

	// Train
	//-------------------------------------------------------------------------

	SG_SPRINT("Train using lambda = %lf ICP removal = %d \n",
			sosvm->get_lambda(), sosvm->get_cleanICP());

	sosvm->train();

	bmrm_return_value_T res = sosvm->get_result();

	SG_SPRINT("result = { Fp=%lf, Fd=%lf, nIter=%d, nCP=%d, nzA=%d, exitflag=%d }\n",
			res.Fp, res.Fd, res.nIter, res.nCP, res.nzA, res.exitflag);

	CStructuredLabels* out =
		CStructuredLabels::obtain_from_generic(sosvm->apply());
	SG_REF(out);

	SG_SPRINT("\n");

	// Compute error
	//-------------------------------------------------------------------------
	float64_t error=0.0;

	for (uint32_t i=0; i<num_feat; ++i)
	{
		error+=(( (CRealNumber*) out->get_label(i) )->value==labs->get_element(i)) ? 0.0 : 1.0;
	}

	SG_SPRINT("Error = %lf %% \n", error/num_feat*100);

	// Free memory
	SG_UNREF(sosvm);
	SG_UNREF(out);

	exit_shogun();

	return 0;
}
<commit_msg>BMRM libshogun example fix (runnable without cmd arguments)<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Michal Uricar
 * Copyright (C) 2012 Michal Uricar
 */

#include <shogun/classifier/svm/LibLinear.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/io/SGIO.h>
#include <shogun/labels/MulticlassLabels.h>
#include <shogun/labels/StructuredLabels.h>
#include <shogun/lib/common.h>
#include <shogun/loss/HingeLoss.h>
#include <shogun/machine/LinearMulticlassMachine.h>
#include <shogun/mathematics/Math.h>
#include <shogun/multiclass/MulticlassOneVsRestStrategy.h>
#include <shogun/structure/MulticlassSOLabels.h>
#include <shogun/structure/MulticlassModel.h>
#include <shogun/structure/DualLibQPBMSOSVM.h>
#include <shogun/io/streaming/StreamingAsciiFile.h>
#include <shogun/features/streaming/StreamingSparseFeatures.h>

using namespace shogun;

#define	DIMS		2
#define EPSILON  	10e-5
#define	NUM_SAMPLES	100
#define NUM_CLASSES	10

char FNAME[] = "data.svmlight";

/** Reads multiclass trainig data stored in svmlight format (i.e. label nz_idx_1:value1 nz_idx_2:value2 ... nz_idx_N:valueN )
 *
 * @param fname    path to file with training data
 * @param DIM      dimension of features
 * @param N        number of feature vectors
 * @param labs     vector with labels
 * @param feats    matrix with features
 */
void read_data(const char fname[], uint32_t DIM, uint32_t N, SGVector< float64_t > *labs, SGMatrix< float64_t > *feats)
{
	CStreamingAsciiFile* file=new CStreamingAsciiFile(fname);
	SG_REF(file);

	CStreamingSparseFeatures< float64_t >* stream_features=
		new CStreamingSparseFeatures< float64_t >(file, true, 1024);
	SG_REF(stream_features);

	SGVector<float64_t > vec(DIM);

	stream_features->start_parser();

	uint32_t num_vectors=0;

	while( stream_features->get_next_example() )
	{
		vec.zero();
		stream_features->add_to_dense_vec(1.0, vec, DIM);

		(*labs)[num_vectors]=stream_features->get_label();

		for(uint32_t i=0; i<DIM; ++i)
		{
			(*feats)[num_vectors*DIM+i]=vec[i];
		}

		num_vectors++;
		stream_features->release_example();
	}

	stream_features->end_parser();

	SG_UNREF(stream_features);
}

/** Generates random multiclass training data and stores them in svmlight format
 *
 * @param labs      returned vector with labels
 * @param feats     returned matrix with features
 */
void gen_rand_data(SGVector< float64_t > labs, SGMatrix< float64_t > feats)
{
	float64_t means[DIMS];
	float64_t  stds[DIMS];

	FILE* pfile = fopen(FNAME, "w");

	for ( int32_t c = 0 ; c < NUM_CLASSES ; ++c )
	{
		for ( int32_t j = 0 ; j < DIMS ; ++j )
		{
			means[j] = CMath::random(-100, 100);
			stds[j] = CMath::random(   1,   5);
		}

		for ( int32_t i = 0 ; i < NUM_SAMPLES ; ++i )
		{
			labs[c*NUM_SAMPLES+i] = c;

			fprintf(pfile, "%d", c);

			for ( int32_t j = 0 ; j < DIMS ; ++j )
			{
				feats[(c*NUM_SAMPLES+i)*DIMS + j] =
					CMath::normal_random(means[j], stds[j]);

				fprintf(pfile, " %d:%f", j+1, feats[(c*NUM_SAMPLES+i)*DIMS + j]);
			}

			fprintf(pfile, "\n");
		}
	}

	fclose(pfile);
}

int main(int argc, char * argv[])
{
	// initialization
	//-------------------------------------------------------------------------

	float64_t lambda=0.01, eps=0.01;
	bool icp=1;
	uint32_t cp_models=1;
	ESolver solver=BMRM;
	uint32_t feat_dim, num_feat;

	init_shogun_with_defaults();

	if (argc > 1 && argc < 8)
	{
		SG_SERROR("Usage: so_multiclass_BMRM <data.in> <feat_dim> <num_feat> <lambda> <icp> <epsilon> <solver> [<cp_models>]\n");
		return -1;
	}

	if (argc > 1)
	{
		// parse command line arguments for parameters setting

		SG_SPRINT("arg[1] = %s\n", argv[1]);

		feat_dim=::atoi(argv[2]);
		num_feat=::atoi(argv[3]);
		lambda=::atof(argv[4]);
		icp=::atoi(argv[5]);
		eps=::atof(argv[6]);

		if (strcmp("BMRM", argv[7])==0)
			solver=BMRM;

		if (strcmp("PPBMRM", argv[7])==0)
			solver=PPBMRM;

		if (strcmp("P3BMRM", argv[7])==0)
			solver=P3BMRM;

		if (argc > 8)
		{
			cp_models=::atoi(argv[8]);
		}
	}
	else
	{
		// default parameters

		feat_dim=DIMS;
		num_feat=NUM_SAMPLES*NUM_CLASSES;
		lambda=1e3;
		icp=1;
		eps=0.01;
		solver=BMRM;
	}

	SGVector< float64_t >* labs=
		new SGVector< float64_t >(num_feat);

	SGMatrix< float64_t >* feats=
		new SGMatrix< float64_t >(feat_dim, num_feat);

	if (argc==1)
	{
		gen_rand_data(*labs, *feats);
	}
	else
	{
		// read data
		read_data(argv[1], feat_dim, num_feat, labs, feats);
	}

	// Create train labels
	CMulticlassSOLabels* labels = new CMulticlassSOLabels(*labs);

	// Create train features
	CDenseFeatures< float64_t >* features =
		new CDenseFeatures< float64_t >(*feats);

	// Create structured model
	CMulticlassModel* model = new CMulticlassModel(features, labels);

	// Create loss function
	CHingeLoss* loss = new CHingeLoss();

	// Create SO-SVM
	CDualLibQPBMSOSVM* sosvm =
		new CDualLibQPBMSOSVM(
				model,
				loss,
				labels,
				lambda);
	SG_REF(sosvm);

	sosvm->set_cleanAfter(10);
	sosvm->set_cleanICP(icp);
	sosvm->set_TolRel(eps);
	sosvm->set_cp_models(cp_models);
	sosvm->set_solver(solver);

	// Train
	//-------------------------------------------------------------------------

	SG_SPRINT("Train using lambda = %lf ICP removal = %d \n",
			sosvm->get_lambda(), sosvm->get_cleanICP());

	sosvm->train();

	bmrm_return_value_T res = sosvm->get_result();

	SG_SPRINT("result = { Fp=%lf, Fd=%lf, nIter=%d, nCP=%d, nzA=%d, exitflag=%d }\n",
			res.Fp, res.Fd, res.nIter, res.nCP, res.nzA, res.exitflag);

	CStructuredLabels* out =
		CStructuredLabels::obtain_from_generic(sosvm->apply());
	SG_REF(out);

	SG_SPRINT("\n");

	// Compute error
	//-------------------------------------------------------------------------
	float64_t error=0.0;

	for (uint32_t i=0; i<num_feat; ++i)
	{
		error+=(( (CRealNumber*) out->get_label(i) )->value==labs->get_element(i)) ? 0.0 : 1.0;
	}

	SG_SPRINT("Error = %lf %% \n", error/num_feat*100);

	// Free memory
	SG_UNREF(sosvm);
	SG_UNREF(out);

	exit_shogun();

	return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2018-2020, University of Edinburgh, University of Oxford
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  * Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of  nor the names of its contributors may be used to
//    endorse or promote products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#include <exotica_core_task_maps/eff_position.h>

REGISTER_TASKMAP_TYPE("EffPosition", exotica::EffPosition);

namespace exotica
{
void EffPosition::Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi)
{
    if (phi.rows() != kinematics[0].Phi.rows() * 3) ThrowNamed("Wrong size of Phi!");
    for (int i = 0; i < kinematics[0].Phi.rows(); ++i)
    {
        phi(i * 3) = kinematics[0].Phi(i).p[0];
        phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
        phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
    }
}

void EffPosition::Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian)
{
    if (phi.rows() != kinematics[0].Phi.rows() * 3) ThrowNamed("Wrong size of Phi!");
    if (jacobian.rows() != kinematics[0].jacobian.rows() * 3 || jacobian.cols() != kinematics[0].jacobian(0).data.cols()) ThrowNamed("Wrong size of jacobian! " << kinematics[0].jacobian(0).data.cols());
    for (int i = 0; i < kinematics[0].Phi.rows(); ++i)
    {
        phi(i * 3) = kinematics[0].Phi(i).p[0];
        phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
        phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
        jacobian.middleRows(i * 3, 3) = kinematics[0].jacobian[i].data.topRows(3);
    }
}

void EffPosition::Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian, HessianRef hessian)
{
    if (phi.rows() != kinematics[0].Phi.rows() * 3) ThrowNamed("Wrong size of Phi!");
    if (jacobian.rows() != kinematics[0].jacobian.rows() * 3 || jacobian.cols() != kinematics[0].jacobian(0).data.cols()) ThrowNamed("Wrong size of jacobian! " << kinematics[0].jacobian(0).data.cols());
    for (int i = 0; i < kinematics[0].Phi.rows(); ++i)
    {
        phi(i * 3) = kinematics[0].Phi(i).p[0];
        phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
        phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
        jacobian.middleRows(i * 3, 3) = kinematics[0].jacobian[i].data.topRows(3);

        for (int j = 0; j < 3; ++j)
        {
            hessian(j).block(i * 3, 0, jacobian.cols(), jacobian.cols()) = kinematics[0].hessian[i](j);
        }
    }
}

int EffPosition::TaskSpaceDim()
{
    return kinematics[0].Phi.rows() * 3;
}
}  // namespace exotica
<commit_msg>[exotica_core_task_maps] EffPosition: Fix Hessian indexing<commit_after>//
// Copyright (c) 2018-2020, University of Edinburgh, University of Oxford
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  * Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of  nor the names of its contributors may be used to
//    endorse or promote products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#include <exotica_core_task_maps/eff_position.h>

REGISTER_TASKMAP_TYPE("EffPosition", exotica::EffPosition);

namespace exotica
{
void EffPosition::Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi)
{
    if (phi.rows() != kinematics[0].Phi.rows() * 3) ThrowNamed("Wrong size of Phi!");
    for (int i = 0; i < kinematics[0].Phi.rows(); ++i)
    {
        phi(i * 3) = kinematics[0].Phi(i).p[0];
        phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
        phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
    }
}

void EffPosition::Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian)
{
    if (phi.rows() != kinematics[0].Phi.rows() * 3) ThrowNamed("Wrong size of Phi!");
    if (jacobian.rows() != kinematics[0].jacobian.rows() * 3 || jacobian.cols() != kinematics[0].jacobian(0).data.cols()) ThrowNamed("Wrong size of jacobian! " << kinematics[0].jacobian(0).data.cols());
    for (int i = 0; i < kinematics[0].Phi.rows(); ++i)
    {
        phi(i * 3) = kinematics[0].Phi(i).p[0];
        phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
        phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
        jacobian.middleRows(i * 3, 3) = kinematics[0].jacobian[i].data.topRows(3);
    }
}

void EffPosition::Update(Eigen::VectorXdRefConst x, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian, HessianRef hessian)
{
    if (phi.rows() != kinematics[0].Phi.rows() * 3) ThrowNamed("Wrong size of Phi!");
    if (jacobian.rows() != kinematics[0].jacobian.rows() * 3 || jacobian.cols() != kinematics[0].jacobian(0).data.cols()) ThrowNamed("Wrong size of jacobian! " << kinematics[0].jacobian(0).data.cols());
    for (int i = 0; i < kinematics[0].Phi.rows(); ++i)
    {
        phi(i * 3) = kinematics[0].Phi(i).p[0];
        phi(i * 3 + 1) = kinematics[0].Phi(i).p[1];
        phi(i * 3 + 2) = kinematics[0].Phi(i).p[2];
        jacobian.middleRows(i * 3, 3) = kinematics[0].jacobian[i].data.topRows(3);

        for (int j = 0; j < 3; ++j)
        {
            hessian(i * 3 + j).block(0, 0, jacobian.cols(), jacobian.cols()) = kinematics[0].hessian[i](j);
        }
    }
}

int EffPosition::TaskSpaceDim()
{
    return kinematics[0].Phi.rows() * 3;
}
}  // namespace exotica
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <iostream>
#include <Eigen/Core>
#include <chrono>

#include "eigen_spatial_convolutions.h"
#include "eigen_cuboid_convolution.h"

int main()
{
  std::cout << "Hello World!\n";

  const int input_depth = 3;
  const int input_rows = 227;
  const int input_cols = 227;
  const int num_batches = 1;
  const int output_depth = 96;
  const int patch_rows = 11;
  const int patch_cols = 11;
  const int output_rows = input_rows - patch_rows + 1;
  const int output_cols = input_cols - patch_cols + 1;

  using namespace Eigen;

  Tensor<float, 4, RowMajor> input(num_batches, input_cols, input_rows, input_depth);
  Tensor<float, 4, RowMajor> kernel(patch_cols, patch_rows, input_depth, output_depth);
  Tensor<float, 4, RowMajor> result(num_batches, output_cols, output_rows, output_depth);

  input = input.constant(11.0f) + input.random();
  kernel = kernel.constant(2.0f) + kernel.random();

  using namespace std::chrono;
  milliseconds t0 = duration_cast< milliseconds >(system_clock::now().time_since_epoch());
  result = SpatialConvolution(input, kernel, 4, 4, PADDING_SAME);
  milliseconds t1 = duration_cast< milliseconds >(system_clock::now().time_since_epoch());
  auto difference = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count();
  std::cout << difference << " ms" << std::endl;

  return 0;
}
<commit_msg>exp ..<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <iostream>
#include <Eigen/Core>
#include <chrono>

#include "eigen_spatial_convolutions.h"
#include "eigen_cuboid_convolution.h"

void test_conv2d () {
  const int input_depth = 3;
  const int input_rows = 227;
  const int input_cols = 227;
  const int num_batches = 1;
  const int output_depth = 96;
  const int patch_rows = 11;
  const int patch_cols = 11;
  const int output_rows = input_rows - patch_rows + 1;
  const int output_cols = input_cols - patch_cols + 1;

  using namespace Eigen;

  Tensor<float, 4, RowMajor> input(num_batches, input_cols, input_rows, input_depth);
  Tensor<float, 4, RowMajor> kernel(patch_cols, patch_rows, input_depth, output_depth);
  Tensor<float, 4, RowMajor> result(num_batches, output_cols, output_rows, output_depth);

  input = input.constant(11.0f) + input.random();
  kernel = kernel.constant(2.0f) + kernel.random();

  using namespace std::chrono;
  milliseconds t0 = duration_cast< milliseconds >(system_clock::now().time_since_epoch());
  result = SpatialConvolution(input, kernel, 4, 4, PADDING_SAME);
  milliseconds t1 = duration_cast< milliseconds >(system_clock::now().time_since_epoch());
  int difference = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count();
  std::cout << difference << " ms" << std::endl;
}

void test_conv2d_back_input () {

}

int main()
{
  std::cout << "Hello World!\n";

  test_conv2d ();

  return 0;
}
<|endoftext|>