diff --git a/build_scripts/qt/resources.pri b/build_scripts/qt/resources.pri index 6bf55e6..5b03921 100644 --- a/build_scripts/qt/resources.pri +++ b/build_scripts/qt/resources.pri @@ -14,6 +14,7 @@ DISTFILES += \ src/res/img/audio/microphone/ptt_notification.svg \ src/res/img/battery/* \ src/res/img/icons/* \ + src/res/img/alarm/* \ src/res/img/video/* \ src/res/img/chaperone/* \ src/res/qml/qmldir \ diff --git a/build_scripts/qt/sources.pri b/build_scripts/qt/sources.pri index 28658c7..a2e35e6 100644 --- a/build_scripts/qt/sources.pri +++ b/build_scripts/qt/sources.pri @@ -22,6 +22,7 @@ SOURCES += src/main.cpp\ src/keyboard_input/input_parser.cpp \ src/settings/settings.cpp \ src/settings/settings_object.cpp \ + src/alarm_clock/vr_alarm.cpp \ @@ -61,7 +62,8 @@ HEADERS += src/overlaycontroller.h \ src/settings/internal/settings_controller.h \ src/settings/internal/specific_setting_value.h \ src/settings/settings_object.h \ - src/settings/internal/settings_object_data.h + src/settings/internal/settings_object_data.h \ + src/alarm_clock/vr_alarm.h \ win32 { diff --git a/docs/screenshots/UtilitiesPage.png b/docs/screenshots/UtilitiesPage.png index e8ef725..f521c98 100644 Binary files a/docs/screenshots/UtilitiesPage.png and b/docs/screenshots/UtilitiesPage.png differ diff --git a/src/alarm_clock/vr_alarm.cpp b/src/alarm_clock/vr_alarm.cpp new file mode 100644 index 0000000..852650c --- /dev/null +++ b/src/alarm_clock/vr_alarm.cpp @@ -0,0 +1,187 @@ +#include +#include "../tabcontrollers/UtilitiesTabController.h" +#include "vr_alarm.h" +#include "../openvr/ovr_overlay_wrapper.h" + +namespace alarm_clock +{ +using ::settings::BoolSetting; +using ::settings::getSetting; +using ::settings::IntSetting; + +VrAlarm::VrAlarm() + : m_alarm( getSetting( IntSetting::UTILITY_alarmHour ), + getSetting( IntSetting::UTILITY_alarmMinute ), + getSetting( IntSetting::UTILITY_alarmSecond ) ) +{ + ovr_overlay_wrapper::createOverlay( + "OVR-AlarmOverlay", "OVR-AlarmOverlay", &m_alarmOverlayHandle ); + + ovr_overlay_wrapper::hideOverlay( m_alarmOverlayHandle ); + + const auto filename = "/res/img/alarm/alarm_activated.png"; + ovr_overlay_wrapper::setOverlayFromFile( m_alarmOverlayHandle, filename ); + + ovr_overlay_wrapper::setOverlayWidthInMeters( m_alarmOverlayHandle, 0.3f ); + + vr::HmdMatrix34_t overlayTransform = { { { 1.0f, 0.0f, 0.0f, 0.12f }, + { 0.0f, 1.0f, 0.0f, 0.08f }, + { 0.0f, 0.0f, 1.0f, -0.3f } } }; + + vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative( + m_alarmOverlayHandle, + vr::k_unTrackedDeviceIndex_Hmd, + &overlayTransform ); +} + +void VrAlarm::eventLoopTick() +{ + if ( alarmEnabled() && m_alarm.isValid() ) + { + checkAlarmStatus(); + } +} + +void VrAlarm::showAlarmNotification() +{ + ovr_overlay_wrapper::showOverlay( m_alarmOverlayHandle ); +} + +bool VrAlarm::alarmEnabled() +{ + return getSetting( BoolSetting::UTILITY_alarmEnabled ); +} + +void VrAlarm::setAlarmEnabled( const bool enabled ) +{ + setSetting( BoolSetting::UTILITY_alarmEnabled, enabled ); + emit alarmEnabledChanged(); +} + +void VrAlarm::checkAlarmStatus() +{ + const auto timeToAlarmActivation = QTime::currentTime().secsTo( m_alarm ); + // Allow times to be set across the 24:00 hour line. + // Setting a timer at 0100 when it's 2359 should not trigger + // alarm immediately. + const auto secondsOfGracePeriod = 2; + const auto activateAlarm = timeToAlarmActivation < secondsOfGracePeriod + && timeToAlarmActivation > 0; + if ( activateAlarm ) + { + LOG( INFO ) << "Alarm fired at " << m_alarm.hour() << ":" + << m_alarm.minute() << ":" << m_alarm.second() << "."; + showAlarmNotification(); + setAlarmEnabled( false ); + + std::thread t( + []( vr::VROverlayHandle_t overlayHandle ) { + // This will freeze the overlay for 3 seconds + std::this_thread::sleep_for( std::chrono::seconds( 3 ) ); + ovr_overlay_wrapper::hideOverlay( overlayHandle ); + }, + m_alarmOverlayHandle ); + t.detach(); + } +} + +void VrAlarm::setAlarmTimeToCurrentTime() +{ + auto now = QTime::currentTime(); + setAlarmTime( now.hour(), now.minute(), now.second() ); +} + +void VrAlarm::setAlarmTime( const int hour, const int minute, const int second ) +{ + if ( !QTime::isValid( hour, minute, second ) ) + { + LOG( ERROR ) << "setAlarmTime passed invalid time values: '" << hour + << "' hours, '" << minute << "' minutes, '" << second + << "' seconds."; + } + + setSetting( IntSetting::UTILITY_alarmHour, hour ); + setSetting( IntSetting::UTILITY_alarmMinute, minute ); + setSetting( IntSetting::UTILITY_alarmSecond, second ); + + m_alarm.setHMS( hour, minute, second ); + emit alarmTimeChanged(); +} + +void VrAlarm::modAlarmTime( const int hour, const int minute, const int second ) +{ + if ( hour > 22 || hour < -22 ) + { + LOG( ERROR ) << "modAlarmTime called with incorrect hour value: '" + << hour << "'. Values not applied."; + return; + } + if ( minute > 58 || minute < -58 ) + { + LOG( ERROR ) << "modAlarmTime called with incorrect minute value: '" + << minute << "'. Values not applied."; + return; + } + if ( second > 58 || minute < -58 ) + { + LOG( ERROR ) << "modAlarmTime called with incorrect second value: '" + << second << "'. Values not applied."; + return; + } + + auto resultingHour = getSetting( IntSetting::UTILITY_alarmHour ) + hour; + auto resultingMinute + = getSetting( IntSetting::UTILITY_alarmMinute ) + minute; + auto resultingSecond + = getSetting( IntSetting::UTILITY_alarmSecond ) + second; + + if ( resultingSecond > 59 ) + { + resultingSecond -= 60; + resultingMinute += 1; + } + else if ( resultingSecond < 0 ) + { + resultingSecond += 60; + resultingMinute -= 1; + } + + if ( resultingMinute > 59 ) + { + resultingMinute -= 60; + resultingHour += 1; + } + else if ( resultingMinute < 0 ) + { + resultingMinute += 60; + resultingHour -= 1; + } + + if ( resultingHour > 23 ) + { + resultingHour = resultingHour - 24; + } + else if ( resultingHour < 0 ) + { + resultingHour = resultingHour + 24; + } + + setAlarmTime( resultingHour, resultingMinute, resultingSecond ); +} + +int VrAlarm::getAlarmHour() +{ + return getSetting( IntSetting::UTILITY_alarmHour ); +} + +int VrAlarm::getAlarmMinute() +{ + return getSetting( IntSetting::UTILITY_alarmMinute ); +} + +int VrAlarm::getAlarmSecond() +{ + return getSetting( IntSetting::UTILITY_alarmSecond ); +} + +} // namespace alarm_clock diff --git a/src/alarm_clock/vr_alarm.h b/src/alarm_clock/vr_alarm.h new file mode 100644 index 0000000..6bc0b85 --- /dev/null +++ b/src/alarm_clock/vr_alarm.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include +#include +#include +#include "../settings/settings.h" +#include "../openvr/ovr_overlay_wrapper.h" + +namespace alarm_clock +{ +class VrAlarm : public QObject +{ + Q_OBJECT + + Q_PROPERTY( bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled NOTIFY + alarmEnabledChanged ) + +public: + VrAlarm(); + + void eventLoopTick(); + + void showAlarmNotification(); + + bool alarmEnabled(); + void setAlarmEnabled( const bool enabled ); + void checkAlarmStatus(); + + Q_INVOKABLE void setAlarmTimeToCurrentTime(); + Q_INVOKABLE void + setAlarmTime( const int hour, const int minute, const int second ); + Q_INVOKABLE + void modAlarmTime( const int hour, const int minute, const int second ); + Q_INVOKABLE int getAlarmHour(); + Q_INVOKABLE int getAlarmMinute(); + Q_INVOKABLE int getAlarmSecond(); + + /* + Stopwatch + isEnabled + enable + Start + Pause + Stop + Restart + + Timer + isEnabled + enable + Start + Pause + Stop + Restart + */ +signals: + void alarmEnabledChanged(); + void alarmTimeChanged(); + void alarmFired(); + +private: + QTime m_alarm; + vr::VROverlayHandle_t m_alarmOverlayHandle = 0; +}; + +} // namespace alarm_clock diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index 901e603..a634f79 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -46,7 +46,7 @@ OverlayController::OverlayController( bool desktopMode, : QObject(), m_desktopMode( desktopMode ), m_noSound( noSound ), m_verifiedCustomTickRateMs( verifyCustomTickRate( settings::getSetting( settings::IntSetting::APPLICATION_customTickRateMs ) ) ), - m_actions() + m_actions(), m_alarm() { // Arbitrarily chosen Max Length of Directory path, should be sufficient for // Any set-up @@ -292,6 +292,12 @@ OverlayController::OverlayController( bool desktopMode, QQmlEngine::setObjectOwnership( obj, QQmlEngine::CppOwnership ); return obj; } ); + qmlRegisterSingletonType( + qmlSingletonImportName, 1, 0, "VrAlarm", []( QQmlEngine*, QJSEngine* ) { + QObject* obj = &( objectAddress->m_alarm ); + QQmlEngine::setObjectOwnership( obj, QQmlEngine::CppOwnership ); + return obj; + } ); // Grab local version number QStringList verNumericalString @@ -1185,6 +1191,8 @@ void OverlayController::mainEventLoop() m_audioTabController.eventLoopTick(); m_rotationTabController.eventLoopTick( devicePoses ); + m_alarm.eventLoopTick(); + if ( vr::VROverlay()->IsDashboardVisible() ) { m_settingsTabController.dashboardLoopTick(); diff --git a/src/overlaycontroller.h b/src/overlaycontroller.h index 46f8957..cb2bc20 100644 --- a/src/overlaycontroller.h +++ b/src/overlaycontroller.h @@ -1,4 +1,3 @@ - #pragma once #include @@ -43,6 +42,8 @@ #include "openvr/ivrinput.h" +#include "alarm_clock/vr_alarm.h" + namespace application_strings { constexpr auto applicationOrganizationName = "AdvancedSettings-Team"; @@ -152,6 +153,8 @@ private: input::SteamIVRInput m_actions; + alarm_clock::VrAlarm m_alarm; + QNetworkAccessManager* netManager = new QNetworkAccessManager( this ); QJsonDocument m_remoteVersionJsonDocument = QJsonDocument(); QJsonObject m_remoteVersionJsonObject; diff --git a/src/res/img/alarm/alarm_activated.png b/src/res/img/alarm/alarm_activated.png new file mode 100644 index 0000000..58bcc95 Binary files /dev/null and b/src/res/img/alarm/alarm_activated.png differ diff --git a/src/res/qml/common/HourComboBox.qml b/src/res/qml/common/HourComboBox.qml new file mode 100644 index 0000000..21ba543 --- /dev/null +++ b/src/res/qml/common/HourComboBox.qml @@ -0,0 +1,50 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 + +MyComboBox { + textRole: "text" + valueRole: "value" + model: [ + { value: 0, text: "00" }, + { value: 1, text: "01" }, + { value: 2, text: "02" }, + { value: 3, text: "03" }, + { value: 4, text: "04" }, + { value: 5, text: "05" }, + { value: 6, text: "06" }, + { value: 7, text: "07" }, + { value: 8, text: "08" }, + { value: 9, text: "09" }, + { value: 10, text: "10" }, + { value: 11, text: "11" }, + { value: 12, text: "12" }, + { value: 13, text: "13" }, + { value: 14, text: "14" }, + { value: 15, text: "15" }, + { value: 16, text: "16" }, + { value: 17, text: "17" }, + { value: 18, text: "18" }, + { value: 19, text: "19" }, + { value: 20, text: "20" }, + { value: 21, text: "21" }, + { value: 22, text: "22" }, + { value: 23, text: "23" }, + ] + + delegate: ItemDelegate { + width: parent.width + text: modelData.text + hoverEnabled: true + contentItem: MyText { + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + text: parent.text + color: parent.enabled ? "#ffffff" : "#909090" + } + background: Rectangle { + color: parent.pressed ? "#406288" : (parent.hovered ? "#365473" : "#2c435d") + } + } +} diff --git a/src/res/qml/common/MinuteSecondComboBox.qml b/src/res/qml/common/MinuteSecondComboBox.qml new file mode 100644 index 0000000..d66cf0a --- /dev/null +++ b/src/res/qml/common/MinuteSecondComboBox.qml @@ -0,0 +1,86 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 + +MyComboBox { + textRole: "text" + valueRole: "value" + model: [ + { value: 0, text: "00" }, + { value: 1, text: "01" }, + { value: 2, text: "02" }, + { value: 3, text: "03" }, + { value: 4, text: "04" }, + { value: 5, text: "05" }, + { value: 6, text: "06" }, + { value: 7, text: "07" }, + { value: 8, text: "08" }, + { value: 9, text: "09" }, + { value: 10, text: "10" }, + { value: 11, text: "11" }, + { value: 12, text: "12" }, + { value: 13, text: "13" }, + { value: 14, text: "14" }, + { value: 15, text: "15" }, + { value: 16, text: "16" }, + { value: 17, text: "17" }, + { value: 18, text: "18" }, + { value: 19, text: "19" }, + { value: 20, text: "20" }, + { value: 21, text: "21" }, + { value: 22, text: "22" }, + { value: 23, text: "23" }, + { value: 24, text: "24" }, + { value: 25, text: "25" }, + { value: 26, text: "26" }, + { value: 27, text: "27" }, + { value: 28, text: "28" }, + { value: 29, text: "29" }, + { value: 30, text: "30" }, + { value: 31, text: "31" }, + { value: 32, text: "32" }, + { value: 33, text: "33" }, + { value: 34, text: "34" }, + { value: 35, text: "35" }, + { value: 36, text: "36" }, + { value: 37, text: "37" }, + { value: 38, text: "38" }, + { value: 39, text: "39" }, + { value: 40, text: "40" }, + { value: 41, text: "41" }, + { value: 42, text: "42" }, + { value: 43, text: "43" }, + { value: 44, text: "44" }, + { value: 45, text: "45" }, + { value: 46, text: "46" }, + { value: 47, text: "47" }, + { value: 48, text: "48" }, + { value: 49, text: "49" }, + { value: 50, text: "50" }, + { value: 51, text: "51" }, + { value: 52, text: "52" }, + { value: 53, text: "53" }, + { value: 54, text: "54" }, + { value: 55, text: "55" }, + { value: 56, text: "56" }, + { value: 57, text: "57" }, + { value: 58, text: "58" }, + { value: 59, text: "59" } + ] + + delegate: ItemDelegate { + width: parent.width + text: modelData.text + hoverEnabled: true + contentItem: MyText { + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + text: parent.text + color: parent.enabled ? "#ffffff" : "#909090" + } + background: Rectangle { + color: parent.pressed ? "#406288" : (parent.hovered ? "#365473" : "#2c435d") + } + } +} diff --git a/src/res/qml/common/TimeAssembly.qml b/src/res/qml/common/TimeAssembly.qml new file mode 100644 index 0000000..9574ade --- /dev/null +++ b/src/res/qml/common/TimeAssembly.qml @@ -0,0 +1,49 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 + +RowLayout { + signal timeChanged(int hour, int minute, int second) + + HourComboBox { + id: hourBox + onActivated: { + parent.timeChanged(hourBox.currentIndex, + minuteBox.currentIndex, + secondBox.currentIndex) + } + } + MyText { + text: "h" + } + + MinuteSecondComboBox { + id: minuteBox + onActivated: { + parent.timeChanged(hourBox.currentIndex, + minuteBox.currentIndex, + secondBox.currentIndex) + } + } + MyText { + text: "m" + } + + MinuteSecondComboBox { + id: secondBox + onActivated: { + parent.timeChanged(hourBox.currentIndex, + minuteBox.currentIndex, + secondBox.currentIndex) + } + } + MyText { + text: "s" + } + function changeTimer(hour, minute, second) { + hourBox.currentIndex = hour + minuteBox.currentIndex = minute + secondBox.currentIndex = second + } +} diff --git a/src/res/qml/utilities_page/alarm_clock/AlarmGroupBox.qml b/src/res/qml/utilities_page/alarm_clock/AlarmGroupBox.qml index e0e25dd..7342b52 100644 --- a/src/res/qml/utilities_page/alarm_clock/AlarmGroupBox.qml +++ b/src/res/qml/utilities_page/alarm_clock/AlarmGroupBox.qml @@ -10,7 +10,7 @@ GroupBox { label: MyText { leftPadding: 10 - text: "Alarm Clock" + text: "Clock" bottomPadding: -10 } background: Rectangle { @@ -19,164 +19,97 @@ GroupBox { radius: 8 } ColumnLayout { - anchors.fill: parent - - Rectangle { - color: "#ffffff" - height: 1 - Layout.fillWidth: true - Layout.bottomMargin: 5 - } - - RowLayout { - MyToggleButton { - id: alarmClockToggle - text: "" - onCheckedChanged: { - UtilitiesTabController.setAlarmEnabled(checked, false) - } + property int activationButtonWidth: 170; + property int startStopPauseResetButtonWidth: 220 + + ColumnLayout { + + LineSeparator { } - - Item { - Layout.fillWidth: true - } - - MyTextField { - id: alarmClockHourText - text: "00" - keyBoardUID: 602 - Layout.preferredWidth: 50 - horizontalAlignment: Text.AlignHCenter - function onInputEvent(input) { - var val = parseInt(input) - if (!isNaN(val)) { - if (val < 0) { - val = 0 - } else if (val > 23) { - val = 23 - } - UtilitiesTabController.setAlarmTimeHour(val, false) + + RowLayout { + MyToggleButton { + id: alarmClockToggle + text: "Alarm" + + Layout.preferredWidth: parent.parent.parent.activationButtonWidth + onCheckedChanged: { + VrAlarm.alarmEnabled = checked } - parent.parent.parent.setAlarmHourText(UtilitiesTabController.alarmTimeHour) } - } - - MyText { - text: ":" - } - - MyTextField { - id: alarmClockMinuteText - text: "00" - keyBoardUID: 603 - Layout.preferredWidth: 50 - horizontalAlignment: Text.AlignHCenter - function onInputEvent(input) { - var val = parseInt(input) - if (!isNaN(val)) { - if (val < 0) { - val = 0 - } else if (val > 59) { - val = 59 - } - UtilitiesTabController.setAlarmTimeMinute(val, false) + + TimeAssembly { + id: alarmClockTimeAssembly + onTimeChanged: { + VrAlarm.setAlarmTime(hour, minute, second) } - parent.parent.parent.setAlarmMinuteText(UtilitiesTabController.alarmTimeMinute) } - } - - Item { - Layout.fillWidth: true - } - - MyPushButton2 { - Layout.preferredWidth: 200 - text: "Current Time" - onClicked: { - UtilitiesTabController.setAlarmTimeToCurrentTime() + + Item { + Layout.fillWidth: true } - } - - MyPushButton2 { - Layout.leftMargin: 50 - Layout.preferredWidth: 120 - text: "+1 Hour" - onClicked: { - UtilitiesTabController.modAlarmTimeHour(1) + + MyPushButton2 { + Layout.preferredWidth: 170 + text: "Current Time" + onClicked: { + VrAlarm.setAlarmTimeToCurrentTime() + alarmClockTimeAssembly.changeTimer(VrAlarm.getAlarmHour(), + VrAlarm.getAlarmMinute(), + VrAlarm.getAlarmSecond()) + } } - } - - MyPushButton2 { - Layout.preferredWidth: 120 - text: "-1 Hour" - onClicked: { - UtilitiesTabController.modAlarmTimeHour(-1) + + MyPushButton2 { + Layout.preferredWidth: 120 + text: "+1 Hour" + onClicked: { + VrAlarm.modAlarmTime(1, 0, 0) + } } - } - - MyPushButton2 { - text: "+5 Min" - Layout.leftMargin: 50 - Layout.preferredWidth: 120 - onClicked: { - UtilitiesTabController.modAlarmTimeMinute(5) + + MyPushButton2 { + Layout.preferredWidth: 120 + text: "-1 Hour" + onClicked: { + VrAlarm.modAlarmTime(-1, 0, 0) + } } - } - - MyPushButton2 { - Layout.preferredWidth: 120 - text: "-5 Min" - onClicked: { - UtilitiesTabController.modAlarmTimeMinute(-5) + + MyPushButton2 { + text: "+5 Min" + Layout.preferredWidth: 120 + onClicked: { + VrAlarm.modAlarmTime(0, 5, 0) + } } - } - } - - RowLayout { - MyToggleButton { - id: alarmDontAnnoyToggle - text: "Don't Annoy me" - onCheckedChanged: { - UtilitiesTabController.setAlarmIsModal(!checked, false) + + MyPushButton2 { + Layout.preferredWidth: 120 + text: "-5 Min" + onClicked: { + VrAlarm.modAlarmTime(0, -5, 0) + } } } } } Component.onCompleted: { - alarmClockToggle.checked = UtilitiesTabController.alarmEnabled - alarmDontAnnoyToggle.checked = !UtilitiesTabController.alarmIsModal - setAlarmHourText(UtilitiesTabController.alarmTimeHour) - setAlarmMinuteText(UtilitiesTabController.alarmTimeMinute) - alarmGroupBox.visible = !OverlayController.desktopMode + alarmClockToggle.checked = VrAlarm.alarmEnabled + alarmClockTimeAssembly.changeTimer(VrAlarm.getAlarmHour(), + VrAlarm.getAlarmMinute(), + VrAlarm.getAlarmSecond()) } Connections { - target: UtilitiesTabController + target: VrAlarm onAlarmEnabledChanged: { - alarmClockToggle.checked = UtilitiesTabController.alarmEnabled + alarmClockToggle.checked = VrAlarm.alarmEnabled } - onAlarmIsModalChanged: { - alarmDontAnnoyToggle.checked = !UtilitiesTabController.alarmIsModal - } - onAlarmTimeHourChanged: { - setAlarmHourText(UtilitiesTabController.alarmTimeHour) - } - onAlarmTimeMinuteChanged: { - setAlarmMinuteText(UtilitiesTabController.alarmTimeMinute) - } - } - function setAlarmHourText(value) { - if (value < 9) { - alarmClockHourText.text = "0" + value - } else { - alarmClockHourText.text = value - } - } - function setAlarmMinuteText(value) { - if (value < 9) { - alarmClockMinuteText.text = "0" + value - } else { - alarmClockMinuteText.text = value + onAlarmTimeChanged: { + alarmClockTimeAssembly.changeTimer(VrAlarm.getAlarmHour(), + VrAlarm.getAlarmMinute(), + VrAlarm.getAlarmSecond()) } } } diff --git a/src/settings/internal/settings_controller.h b/src/settings/internal/settings_controller.h index 80dc50e..40d29dd 100644 --- a/src/settings/internal/settings_controller.h +++ b/src/settings/internal/settings_controller.h @@ -546,6 +546,10 @@ private: SettingCategory::Utility, QtInfo{ "alarmMinute" }, 0 }, + IntSettingValue{ IntSetting::UTILITY_alarmSecond, + SettingCategory::Utility, + QtInfo{ "alarmSecond" }, + 0 }, IntSettingValue{ IntSetting::ROTATION_autoturnLinearTurnSpeed, SettingCategory::Rotation, QtInfo{ "autoturnLinearTurnSpeed" }, diff --git a/src/settings/settings.h b/src/settings/settings.h index 9368ddd..7e9cc4f 100644 --- a/src/settings/settings.h +++ b/src/settings/settings.h @@ -109,6 +109,7 @@ enum class IntSetting UTILITY_alarmHour, UTILITY_alarmMinute, + UTILITY_alarmSecond, ROTATION_autoturnLinearTurnSpeed, // LAST_ENUMERATOR must always be set to the last value diff --git a/src/tabcontrollers/UtilitiesTabController.cpp b/src/tabcontrollers/UtilitiesTabController.cpp index 91fa32f..393dc7e 100644 --- a/src/tabcontrollers/UtilitiesTabController.cpp +++ b/src/tabcontrollers/UtilitiesTabController.cpp @@ -12,13 +12,6 @@ namespace advsettings { void UtilitiesTabController::initStage1() { - auto qAlarmHour - = settings::getSetting( settings::IntSetting::UTILITY_alarmHour ); - auto qAlarmMinute - = settings::getSetting( settings::IntSetting::UTILITY_alarmMinute ); - - m_alarmTime = QTime( qAlarmHour, qAlarmMinute ); - m_utilitiesSettingsUpdateCounter = utils::adjustUpdateRate( k_utilitiesSettingsUpdateCounter ); } @@ -202,53 +195,11 @@ void UtilitiesTabController::sendKeyboardThree() sendStringAsInput( commands ); } -bool UtilitiesTabController::alarmEnabled() const -{ - return settings::getSetting( settings::BoolSetting::UTILITY_alarmEnabled ); -} - -bool UtilitiesTabController::alarmIsModal() const -{ - return settings::getSetting( settings::BoolSetting::UTILITY_alarmIsModal ); -} - bool UtilitiesTabController::vrcDebug() const { return settings::getSetting( settings::BoolSetting::UTILITY_vrcDebug ); } -int UtilitiesTabController::alarmTimeHour() const -{ - return m_alarmTime.hour(); -} - -int UtilitiesTabController::alarmTimeMinute() const -{ - return m_alarmTime.minute(); -} - -void UtilitiesTabController::setAlarmEnabled( bool enabled, bool notify ) -{ - settings::setSetting( settings::BoolSetting::UTILITY_alarmEnabled, - enabled ); - - m_alarmLastCheckTime = QTime(); - - if ( notify ) - { - emit alarmEnabledChanged( enabled ); - } -} - -void UtilitiesTabController::setAlarmIsModal( bool modal, bool notify ) -{ - settings::setSetting( settings::BoolSetting::UTILITY_alarmIsModal, modal ); - if ( notify ) - { - emit alarmIsModalChanged( modal ); - } -} - void UtilitiesTabController::setVrcDebug( bool value, bool notify ) { settings::setSetting( settings::BoolSetting::UTILITY_vrcDebug, value ); @@ -258,116 +209,6 @@ void UtilitiesTabController::setVrcDebug( bool value, bool notify ) } } -void UtilitiesTabController::setAlarmTimeHour( int hour, bool notify ) -{ - if ( m_alarmTime.hour() == hour ) - { - return; - } - - if ( m_alarmTime.isValid() ) - { - m_alarmTime = QTime( hour, m_alarmTime.minute() ); - } - else - { - m_alarmTime = QTime( hour, 0 ); - } - - settings::setSetting( settings::IntSetting::UTILITY_alarmHour, - m_alarmTime.hour() ); - settings::setSetting( settings::IntSetting::UTILITY_alarmMinute, - m_alarmTime.minute() ); - - m_alarmLastCheckTime = QTime(); - - if ( notify ) - { - emit alarmTimeHourChanged( hour ); - } -} - -void UtilitiesTabController::setAlarmTimeMinute( int min, bool notify ) -{ - if ( m_alarmTime.minute() != min ) - { - if ( m_alarmTime.isValid() ) - { - m_alarmTime = QTime( m_alarmTime.hour(), min ); - } - else - { - m_alarmTime = QTime( 0, min ); - } - - settings::setSetting( settings::IntSetting::UTILITY_alarmHour, - m_alarmTime.hour() ); - settings::setSetting( settings::IntSetting::UTILITY_alarmMinute, - m_alarmTime.minute() ); - - m_alarmLastCheckTime = QTime(); - if ( notify ) - { - emit alarmTimeMinuteChanged( min ); - } - } -} - -void UtilitiesTabController::setAlarmTimeToCurrentTime() -{ - auto now = QTime::currentTime(); - setAlarmTimeHour( now.hour() ); - setAlarmTimeMinute( now.minute() ); -} - -void UtilitiesTabController::modAlarmTimeHour( int value, bool notify ) -{ - auto h = m_alarmTime.hour(); - m_alarmTime = m_alarmTime.addSecs( value * 60 * 60 ); - - settings::setSetting( settings::IntSetting::UTILITY_alarmHour, - m_alarmTime.hour() ); - settings::setSetting( settings::IntSetting::UTILITY_alarmMinute, - m_alarmTime.minute() ); - - if ( h != m_alarmTime.hour() ) - { - m_alarmLastCheckTime = QTime(); - if ( notify ) - { - emit alarmTimeHourChanged( m_alarmTime.hour() ); - } - } -} - -void UtilitiesTabController::modAlarmTimeMinute( int value, bool notify ) -{ - auto h = m_alarmTime.hour(); - auto m = m_alarmTime.minute(); - m_alarmTime = m_alarmTime.addSecs( value * 60 ); - - settings::setSetting( settings::IntSetting::UTILITY_alarmHour, - m_alarmTime.hour() ); - settings::setSetting( settings::IntSetting::UTILITY_alarmMinute, - m_alarmTime.minute() ); - - if ( m != m_alarmTime.minute() || h != m_alarmTime.hour() ) - { - m_alarmLastCheckTime = QTime(); - if ( notify ) - { - if ( h != m_alarmTime.hour() ) - { - emit alarmTimeHourChanged( m_alarmTime.hour() ); - } - if ( m != m_alarmTime.minute() ) - { - emit alarmTimeMinuteChanged( m_alarmTime.minute() ); - } - } - } -} - QString getBatteryIconPath( int batteryState ) { constexpr auto batteryPrefix = "/res/img/battery/battery_"; @@ -431,136 +272,6 @@ void UtilitiesTabController::eventLoopTick() { if ( settingsUpdateCounter >= m_utilitiesSettingsUpdateCounter ) { - if ( alarmEnabled() && m_alarmTime.isValid() ) - { - auto now = QTime::currentTime(); - if ( m_alarmLastCheckTime.isValid() - && m_alarmLastCheckTime <= m_alarmTime && m_alarmTime <= now ) - { - setAlarmEnabled( false ); - char alarmMessageBuffer[1024]; - std::snprintf( alarmMessageBuffer, - 1024, - "The alarm at %02i:%02i went off.", - alarmTimeHour(), - alarmTimeMinute() ); - if ( alarmIsModal() ) - { - std::thread messageThread( - []( UtilitiesTabController* parent, - std::string message ) { - auto res = vr::VROverlay()->ShowMessageOverlay( - message.c_str(), - "Alarm Clock", - "Ok", - "+15 min" ); - if ( res - == vr::VRMessageOverlayResponse_ButtonPress_1 ) - { - parent->setAlarmTimeToCurrentTime(); - parent->modAlarmTimeMinute( 15 ); - parent->setAlarmEnabled( true ); - } - else if ( - res >= vr:: - VRMessageOverlayResponse_CouldntFindSystemOverlay ) - { - static const char* errorMessages[] - = { "CouldntFindSystemOverlay", - "CouldntFindOrCreateClientOverlay", - "ApplicationQuit" }; - int errorCode - = res - - vr:: - VRMessageOverlayResponse_CouldntFindSystemOverlay; - if ( res < 3 ) - { - LOG( ERROR ) - << "Could not create Alarm Overlay: " - << errorMessages[errorCode]; - } - else - { - LOG( ERROR ) << "Could not create Alarm " - "Overlay: Unknown Error"; - } - } - }, - this, - std::string( alarmMessageBuffer ) ); - messageThread.detach(); - } - else - { - vr::VRNotificationId notificationId; - vr::EVRInitError eError; - vr::IVRNotifications* vrnotification - = static_cast( - vr::VR_GetGenericInterface( - vr::IVRNotifications_Version, &eError ) ); - if ( eError != vr::VRInitError_None ) - { - LOG( ERROR ) - << "Error while getting IVRNotifications interface" - << vr::VR_GetVRInitErrorAsEnglishDescription( - eError ); - vrnotification = nullptr; - } - else - { - vr::NotificationBitmap_t* messageIconPtr = nullptr; - /* - // Can i even create this object on the stack, who takes - ownership? vr::NotificationBitmap_t messageIcon; - - // First get image width and height - vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(), - nullptr, 0, (uint32_t*)&messageIcon.m_nWidth, - (uint32_t*)&messageIcon.m_nHeight); - - messageIcon.m_nBytesPerPixel = 4; - unsigned bufferSize = - messageIcon.m_nWidth*messageIcon.m_nHeight*messageIcon.m_nBytesPerPixel; - - // Can I delete this buffer after this section? Who - takes ownership? std::unique_ptr imageBuffer; - imageBuffer.reset(new char[bufferSize]); - messageIcon.m_pImageData = imageBuffer.get(); - - // Get image data - auto iconError = - vr::VROverlay()->GetOverlayImageData(parent->overlayThumbnailHandle(), - messageIcon.m_pImageData, bufferSize, - (uint32_t*)&messageIcon.m_nWidth, - (uint32_t*)&messageIcon.m_nHeight); if (iconError != - vr::VROverlayError_None) { LOG(ERROR) << "Error while - getting message overlay icon: " << - vr::VROverlay()->GetOverlayErrorNameFromEnum(iconError); - } else { - messageIconPtr = &messageIcon; - } - */ - auto nError = vrnotification->CreateNotification( - m_parent->overlayHandle(), - 666, - vr::EVRNotificationType_Transient, - alarmMessageBuffer, - vr::EVRNotificationStyle_Application, - messageIconPtr, - ¬ificationId ); - if ( nError != vr::VRNotificationError_OK ) - { - LOG( ERROR ) - << "Error while creating notification: " - << nError; - vrnotification = nullptr; - } - } - } - } - m_alarmLastCheckTime = now; - } - // attach battery overlay to all tracked devices that aren't a // controller or hmd for ( vr::TrackedDeviceIndex_t i = 0; i < vr::k_unMaxTrackedDeviceCount; diff --git a/src/tabcontrollers/UtilitiesTabController.h b/src/tabcontrollers/UtilitiesTabController.h index 5106173..4b0affd 100644 --- a/src/tabcontrollers/UtilitiesTabController.h +++ b/src/tabcontrollers/UtilitiesTabController.h @@ -19,25 +19,14 @@ class OverlayController; class UtilitiesTabController : public QObject { Q_OBJECT - Q_PROPERTY( bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled NOTIFY - alarmEnabledChanged ) - Q_PROPERTY( bool alarmIsModal READ alarmIsModal WRITE setAlarmIsModal NOTIFY - alarmIsModalChanged ) Q_PROPERTY( bool vrcDebug READ vrcDebug WRITE setVrcDebug NOTIFY vrcDebugChanged ) - Q_PROPERTY( int alarmTimeHour READ alarmTimeHour WRITE setAlarmTimeHour - NOTIFY alarmTimeHourChanged ) - Q_PROPERTY( int alarmTimeMinute READ alarmTimeMinute WRITE - setAlarmTimeMinute NOTIFY alarmTimeMinuteChanged ) private: OverlayController* m_parent; unsigned settingsUpdateCounter = 0; - QTime m_alarmTime; - QTime m_alarmLastCheckTime; - vr::VROverlayHandle_t m_batteryOverlayHandles[vr::k_unMaxTrackedDeviceCount] = { 0 }; int m_batteryState[vr::k_unMaxTrackedDeviceCount]; @@ -51,11 +40,7 @@ public: void eventLoopTick(); - bool alarmEnabled() const; - bool alarmIsModal() const; bool vrcDebug() const; - int alarmTimeHour() const; - int alarmTimeMinute() const; public slots: void sendKeyboardInput( QString input ); @@ -93,21 +78,10 @@ public slots: Q_INVOKABLE void sendKeyboardTwo(); Q_INVOKABLE void sendKeyboardThree(); - void setAlarmEnabled( bool enabled, bool notify = true ); - void setAlarmIsModal( bool modal, bool notify = true ); void setVrcDebug( bool value, bool notify = true ); - void setAlarmTimeHour( int hour, bool notify = true ); - void setAlarmTimeMinute( int min, bool notify = true ); - void setAlarmTimeToCurrentTime(); - void modAlarmTimeHour( int value, bool notify = true ); - void modAlarmTimeMinute( int value, bool notify = true ); signals: - void alarmEnabledChanged( bool enabled ); - void alarmIsModalChanged( bool modal ); void vrcDebugChanged( bool value ); - void alarmTimeHourChanged( int hour ); - void alarmTimeMinuteChanged( int min ); }; } // namespace advsettings