void CommandHandler::DoDeactivateSkinBang(std::vector<std::wstring>& args, Skin* skin) { if (!args.empty()) { skin = GetRainmeter().GetSkin(args[0]); if (!skin) { LogWarningF(L"!DeactivateConfig: \"%s\" not active", args[0].c_str()); return; } } if (skin) { GetRainmeter().DeactivateSkin(skin, -1); } else { LogError(L"!DeactivateConfig: Invalid parameters"); } }
void CommandHandler::DoSkinMenuBang(std::vector<std::wstring>& args, Skin* skin) { if (!args.empty()) { skin = GetRainmeter().GetSkin(args[0]); if (!skin) { LogWarningF(L"!SkinMenu: \"%s\" not active", args[0].c_str()); return; } } if (skin) { POINT pos = System::GetCursorPosition(); GetRainmeter().ShowContextMenu(pos, skin); } else { LogError(L"!SkinMenu: Invalid parameter"); } }
/* ** Executes a custom bang. ** */ void Measure::Command(const std::wstring& command) { LogWarningF(this, L"!CommandMeasure: Not supported"); }
/* ** Read the options specified in the ini file. ** */ void MeasureDiskSpace::ReadOptions(ConfigParser& parser, const WCHAR* section) { double oldMaxValue = m_MaxValue; Measure::ReadOptions(parser, section); m_Drive = parser.ReadString(section, L"Drive", L"C:\\"); if (m_Drive.empty()) { LogWarningF(this, L"FreeDiskSpace: Drive= empty"); m_Value = 0.0; m_MaxValue = 0.0; m_OldTotalBytes = 0; m_StringValue.clear(); } else { // A trailing backslash is required for GetDiskFreeSpaceEx(). PathUtil::AppendBacklashIfMissing(m_Drive); } m_Type = (1 == parser.ReadInt(section, L"Type", 0)); m_Total = (1 == parser.ReadInt(section, L"Total", 0)); m_Label = (1 == parser.ReadInt(section, L"Label", 0)); m_IgnoreRemovable = (1 == parser.ReadInt(section, L"IgnoreRemovable", 1)); m_DiskQuota = (1 == parser.ReadInt(section, L"DiskQuota", 1)); // Set the m_MaxValue if (!m_Initialized) { BOOL result = FALSE; ULONGLONG i64TotalBytes; if (!m_Drive.empty()) { const WCHAR* drive = m_Drive.c_str(); UINT type = GetDriveType(drive); if (type != DRIVE_NO_ROOT_DIR && type != DRIVE_CDROM && (!m_IgnoreRemovable || type != DRIVE_REMOVABLE)) // Ignore CD-ROMS and removable drives { result = GetDiskFreeSpaceEx(drive, nullptr, (PULARGE_INTEGER)&i64TotalBytes, nullptr); } } if (result) { m_MaxValue = (double)(__int64)i64TotalBytes; m_OldTotalBytes = i64TotalBytes; } else { m_MaxValue = 0.0; m_OldTotalBytes = 0; } } else { if (m_Type) { m_MaxValue = DRIVETYPE_MAX; m_OldTotalBytes = 0; } else { m_MaxValue = oldMaxValue; } } }
/* ** Executes a custom bang. ** */ void Measure::Command(const std::wstring& command) { LogWarningF(this, L"!CommandMeasure: Not supported by [%s]", m_Name.c_str()); }
void CommandHandler::DoWriteKeyValueBang(std::vector<std::wstring>& args, Skin* skin) { if (args.size() == 3 && skin) { // Add the skin file path to the args args.push_back(skin->GetFilePath()); } else if (args.size() < 4) { LogErrorF(skin, L"!WriteKeyValue: Invalid parameters"); return; } std::wstring& strIniFile = args[3]; if (skin) { skin->MakePathAbsolute(strIniFile); } const WCHAR* iniFile = strIniFile.c_str(); if (strIniFile.find(L"..\\") != std::wstring::npos || strIniFile.find(L"../") != std::wstring::npos) { LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile); return; } if (_wcsnicmp(iniFile, GetRainmeter().m_SkinPath.c_str(), GetRainmeter().m_SkinPath.size()) != 0 && _wcsnicmp(iniFile, GetRainmeter().m_SettingsPath.c_str(), GetRainmeter().m_SettingsPath.size()) != 0) { LogErrorF(skin, L"!WriteKeyValue: Illegal path: %s", iniFile); return; } // Verify whether the file exists. if (_waccess(iniFile, 0) == -1) { LogErrorF(skin, L"!WriteKeyValue: File not found: %s", iniFile); return; } // Verify whether the file is read-only. DWORD attr = GetFileAttributes(iniFile); if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY)) { LogWarningF(skin, L"!WriteKeyValue: File is read-only: %s", iniFile); return; } // Avoid "IniFileMapping" System::UpdateIniFileMappingList(); std::wstring strIniWrite = System::GetTemporaryFile(strIniFile); if (strIniWrite.size() == 1 && strIniWrite[0] == L'?') // error occurred { return; } bool temporary = !strIniWrite.empty(); if (temporary) { if (GetRainmeter().GetDebug()) { LogDebugF(skin, L"!WriteKeyValue: Writing to: %s (Temp: %s)", iniFile, strIniWrite.c_str()); } } else { if (GetRainmeter().GetDebug()) { LogDebugF(skin, L"!WriteKeyValue: Writing to: %s", iniFile); } strIniWrite = strIniFile; } const WCHAR* iniWrite = strIniWrite.c_str(); const WCHAR* section = args[0].c_str(); const WCHAR* key = args[1].c_str(); const std::wstring& strValue = args[2]; bool formula = false; BOOL write = 0; if (skin) { double value; formula = skin->GetParser().ParseFormula(strValue, &value); if (formula) { WCHAR buffer[256]; int len = _snwprintf_s(buffer, _TRUNCATE, L"%.5f", value); Measure::RemoveTrailingZero(buffer, len); write = WritePrivateProfileString(section, key, buffer, iniWrite); } } if (!formula) { write = WritePrivateProfileString(section, key, strValue.c_str(), iniWrite); } if (temporary) { if (write != 0) { WritePrivateProfileString(nullptr, nullptr, nullptr, iniWrite); // FLUSH // Copy the file back. if (!System::CopyFiles(strIniWrite, strIniFile)) { LogErrorF(skin, L"!WriteKeyValue: Failed to copy temporary file to original filepath: %s (Temp: %s)", iniFile, iniWrite); } } else // failed { LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s (Temp: %s)", iniFile, iniWrite); } // Remove the temporary file. System::RemoveFile(strIniWrite); } else { if (write == 0) // failed { LogErrorF(skin, L"!WriteKeyValue: Failed to write to: %s", iniFile); } } }
/* ** Read the options specified in the ini file. ** */ void MeasureScript::ReadOptions(ConfigParser& parser, const WCHAR* section) { Measure::ReadOptions(parser, section); std::wstring scriptFile = parser.ReadString(section, L"ScriptFile", L""); if (!scriptFile.empty()) { if (m_Skin) { m_Skin->MakePathAbsolute(scriptFile); } if (!m_Initialized || wcscmp(scriptFile.c_str(), m_LuaScript.GetFile().c_str()) != 0) { UninitializeLuaScript(); if (m_LuaScript.Initialize(scriptFile)) { bool hasInitializeFunction = m_LuaScript.IsFunction(g_InitializeFunctionName); m_HasUpdateFunction = m_LuaScript.IsFunction(g_UpdateFunctionName); auto L = m_LuaScript.GetState(); lua_rawgeti(L, LUA_GLOBALSINDEX, m_LuaScript.GetRef()); *(Skin**)lua_newuserdata(L, sizeof(Skin*)) = m_Skin; lua_getglobal(L, "MeterWindow"); lua_setmetatable(L, -2); lua_setfield(L, -2, "SKIN"); *(Measure**)lua_newuserdata(L, sizeof(Measure*)) = this; lua_getglobal(L, "Measure"); lua_setmetatable(L, -2); lua_setfield(L, -2, "SELF"); if (!m_LuaScript.IsUnicode()) { // For backwards compatibility. m_HasGetStringFunction = m_LuaScript.IsFunction(g_GetStringFunctionName); if (m_HasGetStringFunction) { LogWarningF(this, L"Script: Using deprecated GetStringValue()"); } lua_getfield(L, -1, "PROPERTIES"); if (lua_isnil(L, -1) == 0) { lua_pushnil(L); // Look in the table for values to read from the section while (lua_next(L, -2)) { lua_pop(L, 1); const char* strKey = lua_tostring(L, -1); const std::wstring wstrKey = StringUtil::Widen(strKey); const std::wstring& wstrValue = parser.ReadString(section, wstrKey.c_str(), L""); if (!wstrValue.empty()) { const std::string strStrVal = StringUtil::Narrow(wstrValue); lua_pushstring(L, strStrVal.c_str()); lua_setfield(L, -3, strKey); } } } // Pop PROPERTIES table. lua_pop(L, 1); } // Pop our table. lua_pop(L, 1); if (m_Initialized) { // If the measure is already initialized and the script has changed, we need to // manually call Initialize(). Initialize(); } // Valid script. return; } } else if (m_LuaScript.IsInitialized()) { // Already initialized. return; } } LogErrorF(this, L"Script: File not valid"); UninitializeLuaScript(); }
void MeasureNowPlaying::ReadOptions(ConfigParser& parser, const WCHAR* section) { Measure::ReadOptions(parser, section); // Data is stored in two structs: Measure and ParentMeasure. ParentMeasure is created for measures // with PlayerName=someplayer. Measure is created for all measures and points to ParentMeasure as // referenced in PlayerName=[section]. // Read settings from the ini-file LPCWSTR str = parser.ReadString(section, L"PlayerName", L"", false).c_str(); if (str[0] == L'[') { if (m_Parent) { // Don't let a measure measure change its parent } else { // PlayerName starts with [ so use referenced section ++str; size_t len = wcslen(str); if (len > 0 && str[len - 1] == L']') { --len; std::vector<ParentMeasure*>::iterator iter = g_ParentMeasures.begin(); for ( ; iter != g_ParentMeasures.end(); ++iter) { if (GetSkin() == (*iter)->owner->GetSkin() && _wcsnicmp(str, (*iter)->owner->GetName(), len) == 0) { // Use same ParentMeasure as referenced section m_Parent = (*iter); ++m_Parent->measureCount; break; } } if (!m_Parent) { // The referenced section doesn't exist LogWarningF(this, L"Invalid PlayerName=%s", str - 1); return; } } } } else { // ParentMeasure is created when PlayerName is an actual player (and not a reference) Player* oldPlayer = nullptr; if (m_Parent) { if (m_Parent->owner != this) { // Don't let a measure-only measure become a parent measure return; } oldPlayer = m_Parent->player; } else { m_Parent = new ParentMeasure; g_ParentMeasures.push_back(m_Parent); m_Parent->owner = this; } if (_wcsicmp(L"AIMP", str) == 0) { m_Parent->player = PlayerAIMP::Create(); } else if (_wcsicmp(L"CAD", str) == 0) { m_Parent->player = PlayerCAD::Create(); } else if (_wcsicmp(L"foobar2000", str) == 0) { HWND fooWindow = FindWindow(L"foo_rainmeter_class", nullptr); if (fooWindow) { const WCHAR* error = L"Your foobar2000 plugin is out of date.\n\nDo you want to update the plugin now?"; if (MessageBox(nullptr, error, L"Rainmeter", MB_YESNO | MB_ICONINFORMATION | MB_TOPMOST) == IDYES) { ShellExecute(nullptr, L"open", L"http://github.com/poiru/foo-cad#readme", nullptr, nullptr, SW_SHOWNORMAL); } } m_Parent->player = PlayerCAD::Create(); } else if (_wcsicmp(L"iTunes", str) == 0) { m_Parent->player = PlayerITunes::Create(); } else if (_wcsicmp(L"MediaMonkey", str) == 0) { m_Parent->player = PlayerWinamp::Create(WA_MEDIAMONKEY); } else if (_wcsicmp(L"Spotify", str) == 0) { m_Parent->player = PlayerSpotify::Create(); } else if (_wcsicmp(L"WinAmp", str) == 0) { m_Parent->player = PlayerWinamp::Create(WA_WINAMP); } else if (_wcsicmp(L"WMP", str) == 0) { m_Parent->player = PlayerWMP::Create(); } else { // Default to WLM m_Parent->player = PlayerWLM::Create(); if (_wcsicmp(L"WLM", str) != 0) { LogErrorF(this, L"Invalid PlayerName=%s", str); } } m_Parent->player->AddInstance(); m_Parent->playerPath = parser.ReadString(section, L"PlayerPath", L""); m_Parent->trackChangeAction = parser.ReadString(section, L"TrackChangeAction", L"", false); m_Parent->disableLeadingZero = parser.ReadBool(section, L"DisableLeadingZero", false); if (oldPlayer) { m_Parent->player->SetMeasures(oldPlayer->GetMeasures()); // Remove instance here so that player doesn't have to reinitialize if PlayerName was // not changed. oldPlayer->RemoveInstance(); } } str = parser.ReadString(section, L"PlayerType", L"").c_str(); if (_wcsicmp(L"ARTIST", str) == 0) { m_Type = MEASURE_ARTIST; } else if (_wcsicmp(L"TITLE", str) == 0) { m_Type = MEASURE_TITLE; } else if (_wcsicmp(L"ALBUM", str) == 0) { m_Type = MEASURE_ALBUM; } else if (_wcsicmp(L"COVER", str) == 0) { m_Type = MEASURE_COVER; } else if (_wcsicmp(L"DURATION", str) == 0) { m_Type = MEASURE_DURATION; } else if (_wcsicmp(L"POSITION", str) == 0) { m_Type = MEASURE_POSITION; } else if (_wcsicmp(L"PROGRESS", str) == 0) { m_Type = MEASURE_PROGRESS; m_MaxValue = 100.0; } else if (_wcsicmp(L"RATING", str) == 0) { m_Type = MEASURE_RATING; m_MaxValue = 5.0; } else if (_wcsicmp(L"STATE", str) == 0) { m_Type = MEASURE_STATE; } else if (_wcsicmp(L"STATUS", str) == 0) { m_Type = MEASURE_STATUS; } else if (_wcsicmp(L"VOLUME", str) == 0) { m_Type = MEASURE_VOLUME; m_MaxValue = 100.0; } else if (_wcsicmp(L"SHUFFLE", str) == 0) { m_Type = MEASURE_SHUFFLE; } else if (_wcsicmp(L"REPEAT", str) == 0) { m_Type = MEASURE_REPEAT; } else if (_wcsicmp(L"LYRICS", str) == 0) { LogWarningF(this, L"Using undocumented PlayerType=LYRICS!"); m_Type = MEASURE_LYRICS; } else if (_wcsicmp(L"FILE", str) == 0) { m_Type = MEASURE_FILE; } else if (_wcsicmp(L"NUMBER", str) == 0) { m_Type = MEASURE_NUMBER; } else if (_wcsicmp(L"YEAR", str) == 0) { m_Type = MEASURE_YEAR; } else if (_wcsicmp(L"GENRE", str) == 0) { m_Type = MEASURE_GENRE; } else { LogErrorF(this, L"Invalid PlayerType=%s", str); } m_Parent->player->AddMeasure(m_Type); }
void MeasureNowPlaying::Command(const std::wstring& command) { const WCHAR* args = command.c_str(); if (!m_Parent) return; Player* player = m_Parent->player; if (!player->IsInitialized()) { if (_wcsicmp(args, L"OpenPlayer") == 0 || _wcsicmp(args, L"TogglePlayer") == 0) { player->OpenPlayer(m_Parent->playerPath); } } else if (_wcsicmp(args, L"Pause") == 0) { player->Pause(); } else if (_wcsicmp(args, L"Play") == 0) { player->Play(); } else if (_wcsicmp(args, L"PlayPause") == 0) { (player->GetState() != STATE_PLAYING) ? player->Play() : player->Pause(); } else if (_wcsicmp(args, L"Next") == 0) { player->Next(); } else if (_wcsicmp(args, L"Previous") == 0) { player->Previous(); } else if (_wcsicmp(args, L"Stop") == 0) { player->Stop(); } else if (_wcsicmp(args, L"OpenPlayer") == 0) { player->OpenPlayer(m_Parent->playerPath); } else if (_wcsicmp(args, L"ClosePlayer") == 0 || _wcsicmp(args, L"TogglePlayer") == 0) { player->ClosePlayer(); } else { LPCWSTR arg = wcschr(args, L' '); if (arg) { ++arg; // Skip the space if (_wcsnicmp(args, L"SetPosition", 11) == 0) { int position = (int)(_wtof(arg) * (double)player->GetDuration()) / 100; if (arg[0] == L'+' || arg[0] == L'-') { position += player->GetPosition(); } player->SetPosition(position); } else if (_wcsnicmp(args, L"SetRating", 9) == 0) { int rating = _wtoi(arg); if (rating >= 0 && rating <= 5) { player->SetRating(rating); } } else if (_wcsnicmp(args, L"SetVolume", 9) == 0) { int volume = _wtoi(arg); if (arg[0] == L'+' || arg[0] == L'-') { // Relative to current volume volume += player->GetVolume(); } if (volume < 0) { volume = 0; } else if (volume > 100) { volume = 100; } player->SetVolume(volume);; } else if (_wcsnicmp(args, L"SetShuffle", 9) == 0) { int state = _wtoi(arg); if (state == -1) { player->SetShuffle(!player->GetShuffle()); } else if (state == 0 || state == 1) { player->SetShuffle(state != 0); } } else if (_wcsnicmp(args, L"SetRepeat", 9) == 0) { int state = _wtoi(arg); if (state == -1) { player->SetRepeat(!player->GetRepeat()); } else if (state == 0 || state == 1) { player->SetRepeat(state != 0); } } else { LogWarningF(this, L"Invalid !CommandMeasure"); } } else { LogWarningF(this, L"Invalid !CommandMeasure"); } } }