#include "master.h" #include #include #include #include "mediadet.h" #include #include #include #include "menu.h" #include "misc.h" #include "systray.h" #include "stream.h" #include "flags.h" #include "comfunct/comfunct.h" #include "metaparse.h" #include "gui.h" #include "operations.h" void Cleanup(HWND hwnd, short sOptions) { if(sOptions & IS_TRAYED) { DeleteTrayIcon(hwnd); } if(sOptions & MEDIA_HOOK) { SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_TOOLS_MEDIAHOOK, 0), 0); } ToggleHotKeys(hwnd, false); MSNCheckAndUpdate(hwnd, true); return; } void ShutdownPrivilege() { HANDLE hToken; TOKEN_PRIVILEGES tp = {0}; HMENU hParentMenu = GetMenu(GetAPWindow()), hControlMenu = NULL; OpenProcessToken(GetCurrentProcess(), TOKEN_WRITE | TOKEN_QUERY, &hToken); LookupPrivilegeValue(TEXT(""), TEXT("SeShutdownPrivilege"), &tp.Privileges[0].Luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(AdjustTokenPrivileges(hToken, false, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0) != 0 && GetLastError() != ERROR_SUCCESS) { hControlMenu = GetSubMenu(hParentMenu, CONTROL_MENU); EnableMenuItem(hControlMenu, IDI_HELP_LOGOFF, MF_BYCOMMAND | MF_DISABLED); EnableMenuItem(hControlMenu, IDI_HELP_REBOOT, MF_BYCOMMAND | MF_DISABLED); EnableMenuItem(hControlMenu, IDI_HELP_SHUTDOWN, MF_BYCOMMAND | MF_DISABLED); } CloseHandle(hToken); return; } bool IsMPEGAudio(LPTSTR szUrlName) { LPCTSTR szUrlExt = PathFindExtension(szUrlName); #ifdef UNICODE /* Windows 2000/XP support LOCALE_INVARIANT */ if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp3"), -1) == CSTR_EQUAL) { return true; } else if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp2"), -1) == CSTR_EQUAL) { return true; } else if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpa"), -1) == CSTR_EQUAL) { return true; } else if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpga"), -1) == CSTR_EQUAL) { return true; } else return false; #else /* Windows 98 doesn't */ if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp3"), -1) == CSTR_EQUAL) { return true; } else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp2"), -1) == CSTR_EQUAL) { return true; } else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpa"), -1) == CSTR_EQUAL) { return true; } else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpga"), -1) == CSTR_EQUAL) { return true; } else return false; #endif } void GetSavePath(HWND hwnd) { OPENFILENAME ofn = {0}; TCHAR szSaveFileName[MAX_PATH] = TEXT(".mp3"); TCHAR szMyMusic[MAX_PATH] = TEXT(""); GetMyMusicDir(hwnd, szMyMusic); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.lpstrFilter = GetLocalText(28); ofn.lpstrFile = szSaveFileName; ofn.nFilterIndex = 1; ofn.lpstrTitle = GetLocalText(29); ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_NONETWORKBUTTON; ofn.lpstrDefExt = TEXT("mp3"); ofn.lpstrInitialDir = szMyMusic; if(GetSaveFileName(&ofn)) { SaveAudioStream(NULL, szSaveFileName); return; } else if(CommDlgExtendedError()== 0) { return; } } void UnmapMemory() { extern LPTSTR lpSharedMem; extern HANDLE hMemMap; UnmapViewOfFile(lpSharedMem); lpSharedMem = NULL; CloseHandle(hMemMap); return; } bool IsFileAudio(LPCTSTR szFileName) { BSTR wideszFileName = 0; const GUID AudioGUID = MEDIATYPE_Audio; GUID GUIDStreamType = {0}; long lNumStreams = 0; WCHAR* wszTempName = NULL; HRESULT hr = 0; IMediaDet *pDetect = NULL; #ifdef UNICODE wideszFileName = SysAllocString(szFileName); #else wszTempName = UnicodeConversion(szFileName); wideszFileName = SysAllocString(wszTempName); FreePointer(wszTempName); #endif hr = CoCreateInstance(&CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaDet, (void**)&pDetect); if(FAILED(hr)) { HRErrorInfo(hr); SysFreeString(wideszFileName); SAFE_RELEASE(pDetect); return false; } hr = pDetect->lpVtbl->put_Filename(pDetect, wideszFileName); SysFreeString(wideszFileName); if(FAILED(hr)) { HRErrorInfo(hr); SAFE_RELEASE(pDetect); return false; } pDetect->lpVtbl->get_OutputStreams(pDetect, &lNumStreams); if(lNumStreams == 0L) { SAFE_RELEASE(pDetect); return false; } pDetect->lpVtbl->put_CurrentStream(pDetect, 1L); hr = pDetect->lpVtbl->get_StreamType(pDetect, &GUIDStreamType); if(FAILED(hr)) { HRErrorInfo(hr); SAFE_RELEASE(pDetect); return false; } if(!IsEqualGUID(&AudioGUID, &GUIDStreamType)) { SAFE_RELEASE(pDetect); DShowRelease(); return false; } else { SAFE_RELEASE(pDetect); return true; } } void ToggleDesktopLink() { IShellLink* iShlink = NULL; TCHAR szAudioPlayerPath[MAX_PATH] = TEXT(""); GetModuleFileName(NULL, szAudioPlayerPath, MAX_PATH); if(SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void**)&iShlink))) { LPCTSTR szDesc = GetLocalText(30); IPersistFile* iPFile = NULL; iShlink->lpVtbl->SetPath(iShlink, szAudioPlayerPath); iShlink->lpVtbl->SetDescription(iShlink, szDesc); iShlink->lpVtbl->SetIconLocation(iShlink, szAudioPlayerPath, 0); if(SUCCEEDED(iShlink->lpVtbl->QueryInterface(iShlink, &IID_IPersistFile, (void**)&iPFile))) { TCHAR szDesktopLinkPath[MAX_PATH] = TEXT(""); WCHAR* wideszDesktopPath = NULL; if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, szDesktopLinkPath))) { PathAppend(szDesktopLinkPath, TEXT("AudioPlayer.lnk")); } if(PathFileExists(szDesktopLinkPath)) { DeleteFile(szDesktopLinkPath); MessageBox(NULL, GetLocalText(31), TEXT("AudioPlayer"), MB_OK | MB_ICONINFORMATION); SAFE_RELEASE(iShlink); SAFE_RELEASE(iPFile); return; } #ifndef UNICODE wideszDesktopPath = UnicodeConversion(szDesktopLinkPath); iPFile->lpVtbl->Save(iPFile, wideszDesktopPath, TRUE); FreePointer(wideszDesktopPath); #else iPFile->lpVtbl->Save(iPFile, szDesktopLinkPath, TRUE); #endif MessageBox(NULL, GetLocalText(32), TEXT("AudioPlayer"), MB_OK | MB_ICONINFORMATION); SAFE_RELEASE(iPFile); } SAFE_RELEASE(iShlink); } return; } bool ParseCommandLine(LPTSTR szParams, size_t s_tParamsLength, HWND hwnd) { bool bHideWindow = false; extern bool bCmdLine; size_t s_tParamsPosition = 0; TCHAR* cTokenPos = NULL; TCHAR* szParamsCopy = malloc(sizeof(TCHAR) * (_tcslen(szParams) + 2)); szParamsCopy[0] = TEXT(' '); _tcscpy(szParamsCopy + 1, szParams); cTokenPos = _tcstok(szParamsCopy + 1, TEXT("-")); while(cTokenPos != NULL) { if(*(cTokenPos - 2) == TEXT(' ')) /* Filter out paths that have '-' is them, not perfect but it'll do for now */ { switch(cTokenPos[0]) { case 'h': /* Hide the main window */ { if(tolower(cTokenPos[1]) == 'a') /* Hide all instances if -ha is specified */ { DWORD dwTarget = BSM_APPLICATIONS; BroadcastApMessage(&dwTarget, AP_HIDE); } else if(tolower(cTokenPos[1]) == 'c') /* Hide all instances but close this one */ { DWORD dwTarget = BSM_APPLICATIONS; BroadcastApMessage(&dwTarget, AP_HIDE); SendMessage(hwnd, WM_CLOSE, 0, 0); } else { bHideWindow = true; ToggleHotKeys(hwnd, true); } } break; case 'c': /* Close all other instances including this one */ { DWORD dwTarget = BSM_APPLICATIONS; BroadcastApMessage(&dwTarget, AP_CLOSE); } break; case 's': /* Show other instances and close this one */ { DWORD dwTarget = BSM_APPLICATIONS; BroadcastApMessage(&dwTarget, AP_SHOW); SendMessage(hwnd, WM_CLOSE, 0, 0); } break; case 'l': { SendMessage(hwnd, WM_NULL, AP_LOOP, 0); } break; case 'r': { SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_PLAYLIST_SHUFFLE, 0), 0); } break; case 'x': { SendMessage(hwnd, WM_CLOSE, 0, 0); } break; case 't': { SendMessage(hwnd, WM_NULL, AP_TRAY, 0); MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, true); ShowWindow(hwnd, SW_MINIMIZE); bHideWindow = true; } break; case 'e': { SendMessage(hwnd, WM_NULL, AP_CLOSEONFINISH, 0); } break; case 'o': { size_t s_tPathLength = 0; LPTSTR szFileNameStart = cTokenPos + 2; /* Get a pointer to the beginning of the path string after the "-o " */ TCHAR szFullFilePath[MAX_PATH] = TEXT(""); if(szFileNameStart[0] != TEXT('"')) // The path isn't surrounded by quotes { TCHAR szFilePath[MAX_PATH] = TEXT(""); _stscanf(szFileNameStart, TEXT("%s"), szFilePath); if(PathFileExists(szFilePath) == FALSE) { ErrorMessage(GetLocalText(33)); break; } GetFullPathName(szFilePath, MAX_PATH, szFullFilePath, NULL); // essentially concatenates the path we read onto the current directory } else { TCHAR* szClosingQuote = (_tcschr(szFileNameStart + 1, TEXT('"')) + 1); // Get a pointer to the element after the closing quotation mark size_t s_tNoChars = szClosingQuote - szFileNameStart; // Find how long the string is _tcsncpy(szFullFilePath, szFileNameStart, s_tNoChars); // copy that many characters from the starting quote into the szFullFilePath buffer } CommandLineOpen(szFullFilePath, hwnd); } break; } } cTokenPos = _tcstok(NULL, TEXT("-")); // Find the next - in the parameter list and start again } bCmdLine = true; free(szParamsCopy); return bHideWindow; } void BroadcastApMessage(LPDWORD dwTarget, int AP_MSG) { BroadcastSystemMessage(BSF_FORCEIFHUNG, dwTarget, WM_NULL, AP_MSG, 0); /* Since the message specified here will be sent to all windows, WM_NULL has been chosen * to minimize conflicts with other applications */ } void MSNCheckAndUpdate(HWND hwnd, bool bClear) { WCHAR wszMSNString[300] = L""; COPYDATASTRUCT cds = {0}; HWND hMSNWindow = NULL; MENUITEMINFO mii = {0}; HMENU hMenu = GetMenu(hwnd), hToolsMenu = GetSubMenu(hMenu, TOOLS_MENU); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_STATE; GetMenuItemInfo(hToolsMenu, IDI_TOOLS_MSN, FALSE, &mii); if((mii.fState != MFS_CHECKED) && bClear == false) /* If the menu option isn't checked and we're not clearing the text, don't do anything */ { return; } if(bClear == true) { _snwprintf(wszMSNString, 300, L"\\0Music\\00\\0{0} - {1}\\0\\0\\0\\0\\0"); } else { // If we have the Artist and title of the playing file, it has already been found // and is displaying in the middle part of the status bar, so we just get that // instead of querying the file again, if not all we can do is display the file title TCHAR* szDetails = GetStatusText(hwnd, 1); #ifndef UNICODE WCHAR* wszDetails = UnicodeConversion(szDetails); _snwprintf(wszMSNString, 300, L"\\0Music\\01\\0{0}\\0%s\\0\\0\\0", wszDetails); FreePointer(wszDetails); #else _snwprintf(wszMSNString, 300, L"\\0Music\\01\\0{0}\\0%s\\0\\0\\0", szDetails); #endif free(szDetails); } cds.dwData = 0x547; cds.cbData = (DWORD)((wcslen(wszMSNString) + 1) * sizeof(WCHAR)); cds.lpData = wszMSNString; while((hMSNWindow = FindWindowEx(NULL, hMSNWindow, TEXT("MsnMsgrUIManager"), NULL)) != NULL) { SendMessage(hMSNWindow, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds); } return; } bool CheckForUpdates(HWND hwnd, HMODULE* hUpdateModule) { UPDATEPROC UpdateDialog = NULL; STOPPROC UpdateClean = NULL; *hUpdateModule = LoadLibrary(TEXT("update.dll")); if(*hUpdateModule == NULL) { ErrorMessage(GetLocalText(34)); return false; } UpdateDialog = (UPDATEPROC)GetProcAddress(*hUpdateModule, "UpdateDialog"); UpdateClean = (STOPPROC)GetProcAddress(*hUpdateModule, "UpdateClean"); if(UpdateDialog == NULL || UpdateClean == NULL) { ErrorMessage(GetLocalText(35)); return false; } if(UpdateDialog(hwnd, AUDIOPLAYER_VERSION) == NULL) { UpdateClean(); return false; } return true; } void ToggleHotKeys(HWND hwnd, bool bOn) { int i = 0; const short iKeyIdents[] = {0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, 0x09FF}; const char iKeyCodes[] = {0x40, 0x50, 0x55, 0x53, 0x59, 0x4D, VK_F4, 0x56, 0x4C, 0x4E}; /* KeyCodes are: o - Open File(s), p - Play, u - Pause, s - Stop, y - Open / Change playlist, m - Toggle Mute, F4 - Close the App, v - View(Show) Window, l - Toggle Looping, n - Next playlist track */ if(bOn == true) { for(; i < (sizeof(iKeyIdents) / sizeof(short)); i++) { RegisterHotKey(hwnd, iKeyIdents[i], MOD_ALT | MOD_SHIFT, iKeyCodes[i]); } } else { for(; i < (sizeof(iKeyIdents) / sizeof(short)); i++) { UnregisterHotKey(hwnd, iKeyIdents[i]); } } return; } bool CheckForOtherInstances(AP_DATACOPY* pAdc) { HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("AudioPlayer")); if(GetLastError() != ERROR_ALREADY_EXISTS) { ReleaseMutex(hMutex); CloseHandle(hMutex); return false; } else { EnumWindows(APWindowCheckProc, (LPARAM)pAdc); return true; } } BOOL CALLBACK APWindowCheckProc(HWND hWindow, LPARAM lParam) { AP_DATACOPY* pAdc = (AP_DATACOPY*)lParam; TCHAR szWindowTitle[12] = TEXT(""); GetWindowText(hWindow, szWindowTitle, 12); if(_tcscmp(szWindowTitle, TEXT("AudioPlayer")) == 0) { if(hWindow != pAdc->hwnd) /* We found the other instance */ { COPYDATASTRUCT cds = {0}; size_t s_tNameLen = _tcslen(pAdc->szFileName) + 1; TCHAR* szFileToPlay = malloc(s_tNameLen * sizeof(TCHAR)); _tcsncpy(szFileToPlay, pAdc->szFileName, s_tNameLen); cds.cbData = s_tNameLen * sizeof(TCHAR); cds.lpData = szFileToPlay; SendMessage(hWindow, WM_COPYDATA, (WPARAM)pAdc->hwnd, (LPARAM)&cds); free(szFileToPlay); SendMessage(pAdc->hwnd, WM_CLOSE, 0, 0); PostQuitMessage(0); return FALSE; } } return TRUE; } void ReadOptionsAndConfigure(HWND hwnd, short* sOptions) { FILE* fOptions = NULL; TCHAR szAudioPlayerConfig[MAX_PATH] = TEXT(""); GetModuleFileName(NULL, szAudioPlayerConfig, MAX_PATH); PathRemoveFileSpec(szAudioPlayerConfig); _tcscat(szAudioPlayerConfig, TEXT("\\config.txt")); fOptions = _tfopen(szAudioPlayerConfig, TEXT("r")); if(fOptions == NULL) { return; } _ftscanf(fOptions, TEXT("%x"), sOptions); fclose(fOptions); if(*sOptions & TRAY_MINIMIZE) { MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, true); } if(*sOptions & HOTKEYS_ON) { MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_HOTKEYS, true); ToggleHotKeys(hwnd, true); } if(*sOptions & SHOW_LYRICS) { *sOptions &= (~(SHOW_LYRICS)); PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_DISPLAY_LYRICS, 0), 1); } if(*sOptions & INSTANCE_MUTEX) { *sOptions &= (~(INSTANCE_MUTEX)); PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_MUTEX, 0), 1); } #ifdef UNICODE if(*sOptions & MEDIA_HOOK) { *sOptions &= (~(MEDIA_HOOK)); ToggleHook(hwnd, sOptions); } #endif return; } void SaveOptions(short sOptions) { TCHAR szAudioPlayerConfig[MAX_PATH] = TEXT(""); FILE* fOptions = NULL; sOptions &= (~(CLOSE_WHEN_FINISHED)); sOptions &= (~(TIMER_ON)); sOptions &= (~(SHOW_PLAYLIST)); sOptions &= (~(IS_TRAYED)); if(sOptions == 0) { return; /* No point saving if no options are set */ } GetModuleFileName(NULL, szAudioPlayerConfig, MAX_PATH); PathRemoveFileSpec(szAudioPlayerConfig); _tcscat(szAudioPlayerConfig, TEXT("\\config.txt")); fOptions = _tfopen(szAudioPlayerConfig, TEXT("w")); if(fOptions == NULL) { ErrorMessage(GetLocalText(36)); return; } _ftprintf(fOptions, TEXT("%x"), sOptions); fclose(fOptions); return; } void CopyData(HWND hwnd, TCHAR* szText) { HANDLE hMem = NULL; TCHAR* szClipboard = NULL; OpenClipboard(hwnd); EmptyClipboard(); hMem = GlobalAlloc(GHND, (_tcslen(szText) + 1) * sizeof(TCHAR)); szClipboard = GlobalLock(hMem); memcpy(szClipboard, szText, GlobalSize(hMem)); GlobalUnlock(hMem); #ifdef UNICODE SetClipboardData(CF_UNICODETEXT, hMem); #else SetClipboardData(CF_TEXT, hMem); #endif CloseClipboard(); return; } void GetMyMusicDir(HWND hwnd, TCHAR* szMyMusicDir) { #ifndef UNICODE if(SUCCEEDED(SHGetFolderPath(hwnd, CSIDL_PERSONAL, NULL, 0, szMyMusicDir))) { PathAppend(szMyMusicDir, GetLocalText(27)); } #else SHGetFolderPath(hwnd, CSIDL_MYMUSIC, NULL, 0, szMyMusicDir); #endif return; }