//*************************************************************************** // WinAMP, Marmot2' mod // + изменено большинство управляющих клавиш (для лучшего использования на Motorola) // + добавлена возможность вкл./откл. окна визуализации и переключения ее в полноэкранный режим при удерживании # // (корректно работает для AVS, с другими модулями визуал. не проверялось) // + возможность переключения профилей визуализации AVS // + соответственно исправлена справка //*************************************************************************** etIgnore = 0; etActivate = 1; etBegin = 2; etEnd = 3; etKeyPress = 4; etKeyRelease = 5; etIntegerInput = 6; etBack = 7; etTimer = 8; etNext = 9; etTextInput = 10; etCustom = 12; ctVolume = 1; ctRewind = 2; ctFastForward = 3; ctRating = 4; stNormal = 0; stHelp = 1; stVolume = 2; stFastForward = 3; stRewind = 4; stExtraMenu = 5; stBrowseAll = 6; stBrowseArtists = 7; stBrowseArtistSongs = 8; stVolumeNoTimeout = 9; stSearch = 10; stSearchError = 11; stSearchList = 12; stFeedback = 13; //-- added stToggleVis = 14; emSearch = 0; emBrowseAll = 1; emBrowseAllSorted = 2; emBrowseArtists = 3; showDialog = false; windowClassName = "Winamp v1.x"; window = Windows.findWindow(windowClassName); timeout = 50; movementStep = 1000; if(ExecuteData.type == etActivate) { showDialog = true; RemoteController.setStore(new Array(3)); RemoteController.store[0] = stNormal; } else if(ExecuteData.type == etBegin) { RemoteController.startTimer(500); } else if(ExecuteData.type == etEnd) { RemoteController.stopTimer(); } else if(ExecuteData.type == etTimer) { showDialog = true; } if(!window) { if(ExecuteData.type == etBack) return; if(ExecuteData.type == etNext) { RemoteController.showProgress("Launching..."); if(!Windows.open(Windows.readRegistryString("HKCU\Software\Winamp\") # "\Winamp.exe")) { RemoteController.showDialog("WinAMP not installed"); RemoteController.stopTimer(); return; } for(i = 0; i < 20; i += 1) { window = Windows.findWindow(windowClassName); if(window) break; Windows.sleep(400); } showDialog = true; } } else if(RemoteController.store[0] == stNormal) { if(ExecuteData.type == etBack) return; if(ExecuteData.type == etNext) { // Play/Pause showDialog = true; state = window.sendMessageTimeout(0x400, 0, 104, timeout, 0); if(state == 0) // Stopped { // Play window.postMessage(0x111, 40045, 0); } else // Playing or paused { // Pause - this toggles it if paused already window.postMessage(0x111, 40046, 0); } } else if(ExecuteData.type == etCustom) { if(ExecuteData.customType == ctVolume) { window.postMessage(0x400, ExecuteData.input * 2.55, 122); } else if(ExecuteData.customType == ctRewind && ExecuteData.input == 1) { // Rewind RemoteController.store[0] = stRewind; RemoteController.store[1] = movementStep; RemoteController.startTimer(100); } else if(ExecuteData.customType == ctFastForward && ExecuteData.input == 1) { // Fast Forward RemoteController.store[0] = stFastForward; RemoteController.store[1] = movementStep; RemoteController.startTimer(100); } else if(ExecuteData.customType == ctRating) { // Rating window.postMessage(0x400, ExecuteData.input, 639); } } else if(ExecuteData.type == etKeyPress) { if(ExecuteData.keyID == "1") { // Rewind RemoteController.store[0] = stRewind; RemoteController.store[1] = movementStep; RemoteController.startTimer(100); } else if(ExecuteData.keyID == "3") { // Fast Forward RemoteController.store[0] = stFastForward; RemoteController.store[1] = movementStep; RemoteController.startTimer(100); } else if(ExecuteData.keyID == "5") { // Play/Pause showDialog = true; state = window.sendMessageTimeout(0x400, 0, 104, timeout, 0); if(state == 0) // Stopped { // Play window.postMessage(0x111, 40045, 0); } else // Playing or paused { // Pause - this toggles it if paused already window.postMessage(0x111, 40046, 0); } } else if(ExecuteData.keyID == "2") { // Stop window.postMessage(0x111, 40047, 0); } //--->Моя вставка! else if(ExecuteData.keyID == "#") { // Visualization RemoteController.store[0] = stToggleVis; RemoteController.startTimer(1000); } else if("s" # ExecuteData.keyID == "s0") //При нажатии софт-меню-кнопок также возвр."0", но с доп. упр.символом. Таким способом можно обнаружить отсутствие упр.символа { // Next visualization profile window.postMessage(0x111, 40382, 0); } //<--- else if(ExecuteData.keyID == "^"||ExecuteData.keyID == "4") { // Previous window.postMessage(0x111, 40044, 0); } else if(ExecuteData.keyID == "v"||ExecuteData.keyID == "6") { // Next window.postMessage(0x111, 40048, 0); } else if(ExecuteData.keyID == "u" || ExecuteData.keyID == "d" || ExecuteData.keyID == "7") { volume = window.sendMessageTimeout(0x400, -666, 122, timeout, -1); if(volume != -1) { RemoteController.showPercentInput("Volume", volume / 2.55); RemoteController.store[0] = stVolume; RemoteController.startTimer(3000); } } else if(ExecuteData.keyID == "f") { // Help! RemoteController.store[0] = stHelp; showDialog = true; } else if(ExecuteData.keyID == "*") { // Menu! RemoteController.store[0] = stExtraMenu; RemoteController.stopTimer(); showDialog = true; } // else if(ExecuteData.keyID == "4") // { // hWinampAl = Windows.findWindow("Winamp AL"); // if(hWinampAl) // { // window.postMessage(0x111, 40047, 0); // hWinampAl.postMessage(0x400, 114, 0); // } // } // else if(ExecuteData.keyID == "6") // { // hWinampAl = Windows.findWindow("Winamp AL"); // if(hWinampAl) // { // window.postMessage(0x111, 40047, 0); // hWinampAl.postMessage(0x400, 115, 0); // } // } else if(ExecuteData.keyID == "8") { shuffle = !window.sendMessageTimeout(0x400, 0, 250, timeout, 0); window.postMessage(0x400, shuffle, 252); if(shuffle) RemoteController.showDialog("Shuffle: Enabled"); else RemoteController.showDialog("Shuffle: Disabled"); RemoteController.store[0] = stFeedback; RemoteController.startTimer(500); } else if(ExecuteData.keyID == "9") { repeat = !window.sendMessageTimeout(0x400, 0, 251, timeout, 0); window.postMessage(0x400, repeat, 253); if(repeat) RemoteController.showDialog("Repeat: Enabled"); else RemoteController.showDialog("Repeat: Disabled"); RemoteController.store[0] = stFeedback; RemoteController.startTimer(500); } } } else if(RemoteController.store[0] == stHelp) { if(ExecuteData.type == etTimer) return; if(ExecuteData.type == etBack || ExecuteData.type == etNext) { showDialog = true; RemoteController.store[0] = stNormal; } } else if(RemoteController.store[0] == stVolume) { if(ExecuteData.type == etTimer || ExecuteData.type == etBack || ExecuteData.type == etNext) { showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } else if(ExecuteData.type == etIntegerInput) { RemoteController.startTimer(3000); window.postMessage(0x400, ExecuteData.input * 2.55, 122); } } else if(RemoteController.store[0] == stVolumeNoTimeout) { if(ExecuteData.type == etBack || ExecuteData.type == etNext) { showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } else if(ExecuteData.type == etIntegerInput) { window.postMessage(0x400, ExecuteData.input * 2.55, 122); } } //--->Моя вставка! else if(RemoteController.store[0] == stToggleVis) { if(ExecuteData.type == etTimer&&RemoteController.store[2]==0) //клавиша нажата >1000мсек -> полноэкр.режим { window.postMessage(0x111,40389,0); RemoteController.store[0] = stNormal; RemoteController.store[2] = 1; } else if (ExecuteData.type == etKeyRelease) //клавиша отжата раньше, чем отработал таймер { if (RemoteController.store[2] == 0) //Перекл. окно визуализации {window.postMessage(0x111,40192,0);} else //Выход из полноэкранного режима { VisWin = Windows.findWindow("avswnd"); VisWin.postMessage(0x0021,window,0x02010000+1); //mouseactivate VisWin.postMessage(0x0201,1,0); //lbuttondown VisWin.postMessage(0x0202,0,0); //lbuttonup RemoteController.store[2] = 0; } RemoteController.store[0] = stNormal; } }//<--- else if(RemoteController.store[0] == stFastForward) { if(ExecuteData.type == etTimer) { time = window.sendMessageTimeout(0x400, 0, 105, timeout, -1); if(time != -1) { window.postMessage(0x400, time+RemoteController.store[1], 106); RemoteController.store[1] += 100; } } else if(ExecuteData.type == etKeyRelease || (ExecuteData.customType == ctFastForward && ExecuteData.input == 0)) { RemoteController.startTimer(500); RemoteController.store[0] = stNormal; } } else if(RemoteController.store[0] == stRewind) { if(ExecuteData.type == etTimer) { time = window.sendMessageTimeout(0x400, 0, 105, timeout, -1); if(time != -1) { time = time - RemoteController.store[1]; if(time < 0) time = 0; window.postMessage(0x400, time, 106); RemoteController.store[1] += 100; } } else if(ExecuteData.type == etKeyRelease || (ExecuteData.customType == ctRewind && ExecuteData.input == 0)) { RemoteController.startTimer(500); RemoteController.store[0] = stNormal; } } else if(RemoteController.store[0] == stExtraMenu) { if(ExecuteData.type == etBack || ExecuteData.type == etNext) { showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } else if(ExecuteData.type == etIntegerInput) { // 0 = Browse all // 1 = Browse all sorted // 2 = Browse by artist if(ExecuteData.input == emBrowseAll) { // Request writing the playlist. if(window.sendMessageTimeout(0x400, 0, 120, timeout, -1) == -1) { // Shit.. problems! showDialog = true; RemoteController.store[0] = stNormal; } m3uName = window.moduleFileName ^ "^(.*)\.exe$/$1.m3u/i"; m3uFile = new Reader(m3uName); songArray = new Array(0); songName = ""; while(m3uFile.isReadable()) { line = m3uFile.readLine(); if(!line) continue; if(line ~ "^#") { if(line ~ "^#EXTINF:\d+,(?:.*? - )?(.*?)$") songName = Windows.convertFromACPToUTF8(regex_captures[1]); } else { if(!songName) songName = Windows.convertFromOEMCPToUTF8(line ^ "^(?:.*\\)(.*)$/$1"); songArray.append(songName); songName = ""; } } RemoteController.showMenu("Songs", songArray); RemoteController.store[0] = stBrowseAll; } else if(ExecuteData.input == emBrowseAllSorted) { // Request writing the playlist. if(window.sendMessageTimeout(0x400, 0, 120, timeout, -1) == -1) { // Shit.. problems! showDialog = true; RemoteController.store[0] = stNormal; } m3uName = window.moduleFileName ^ "^(.*)\.exe$/$1.m3u/i"; m3uFile = new Reader(m3uName); songArray = new Array(0); songName = ""; while(m3uFile.isReadable()) { line = m3uFile.readLine(); if(!line) continue; if(line ~ "^#") { if(line ~ "^#EXTINF:\d+,(?:.*? - )?(.*?)$") songName = Windows.convertFromACPToUTF8(regex_captures[1]); } else { if(!songName) songName = Windows.convertFromOEMCPToUTF8(line ^ "^(?:.*\\)(.*)$/$1"); songArray.append(songName); songName = ""; } } RemoteController.showSortedMenu("Songs", songArray); RemoteController.store[0] = stBrowseAll; } else if(ExecuteData.input == emBrowseArtists) { if(window.sendMessageTimeout(0x400, 0, 120, timeout, -1) == -1) { // Shit.. problems! showDialog = true; RemoteController.store[0] = stNormal; } m3uName = window.moduleFileName ^ "^(.*)\.exe$/$1.m3u/i"; m3uFile = new Reader(m3uName); artistDictionary = new Dictionary; artistName = ""; songName = ""; index = 0; while(m3uFile.isReadable()) { line = m3uFile.readLine(); if(!line) continue; if(line ~ "^#") { if(line ~ "^#EXTINF:\d+,(?:(.*?) - )?(.*?)$") { artistName = Windows.convertFromACPToUTF8(regex_captures[1]); songName = Windows.convertFromACPToUTF8(regex_captures[2]); } } else { if(!artistName) artistName = ""; if(!songName) songName = Windows.convertFromOEMCPToUTF8(line ^ "^(?:.*\\)(.*)$/$1"); if(!artistDictionary.hasKey(artistName)) artistDictionary.insert(artistName, new Array(0)); data = new Array(2); data[0] = songName; data[1] = index; artistDictionary[artistName].append(data); artistName = ""; songName = ""; index += 1; } } // Now build artist array artistArray = new Array(0); artist = artistDictionary.enumerate; while(artist) artistArray.append(artist.nextKey); RemoteController.showMenu("Artists", artistArray); RemoteController.store[0] = stBrowseArtists; RemoteController.store[1] = artistDictionary; } else if(ExecuteData.input == emSearch) { RemoteController.store[0] = stSearch; showDialog = true; } } } else if(RemoteController.store[0] == stBrowseAll) { if(ExecuteData.type == etBack) { showDialog = true; RemoteController.store[0] = stExtraMenu; } else if(ExecuteData.type == etIntegerInput) { // Stop window.sendMessageTimeout(0x111, 40047, 0, timeout, -1); // Set play list pos window.sendMessageTimeout(0x400, ExecuteData.input, 121, timeout, -1); // Start play window.sendMessageTimeout(0x111, 40045, 0, timeout, -1); // Return to info display showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } } else if(RemoteController.store[0] == stBrowseArtists) { if(ExecuteData.type == etBack) { showDialog = true; RemoteController.store[0] = stExtraMenu; } else if(ExecuteData.type == etIntegerInput) { artist = RemoteController.store[1].enumerate; for(i = 0; i < ExecuteData.input; i += 1) artist.nextKey; artistName = artist.nextKey; if(artistName == "") { showDialog = true; RemoteController.store[0] = stExtraMenu; } else { songList = new Array(0); artistData = RemoteController.store[1][artistName]; for(i = 0; i < artistData.size; i += 1) songList.append(artistData[i][0]); RemoteController.showMenu(artistName, songList); RemoteController.store[0] = stBrowseArtistSongs; RemoteController.store[2] = RemoteController.store[1][artistName]; } } } else if(RemoteController.store[0] == stBrowseArtistSongs) { if(ExecuteData.type == etBack) { // Now build artist array artistArray = new Array(0); artist = RemoteController.store[1].enumerate; while(artist) { artistArray.append(artist.nextKey); } RemoteController.showMenu("Artists", artistArray); RemoteController.store[0] = stBrowseArtists; } else if(ExecuteData.type == etIntegerInput) { songIndex = RemoteController.store[2][ExecuteData.input][1]; // Stop window.sendMessageTimeout(0x111, 40047, 0, timeout, -1); // Set play list pos window.sendMessageTimeout(0x400, songIndex, 121, timeout, -1); // Start play window.sendMessageTimeout(0x111, 40045, 0, timeout, -1); // Return to info display showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } } else if(RemoteController.store[0] == stSearch) { if(ExecuteData.type == etBack) { showDialog = true; RemoteController.store[0] = stExtraMenu; } else if(ExecuteData.type == etTextInput) { StringInput = ExecuteData.input; if(String.length(StringInput) < 2) { RemoteController.showDialog("Search must be 2 characters or greater"); RemoteController.store[0] = stSearchError; } else { if(window.sendMessageTimeout(0x400, 0, 120, timeout, -1) == -1) { // Shit.. problems! showDialog = true; RemoteController.store[0] = stNormal; } m3uName = window.moduleFileName ^ "^(.*)\.exe$/$1.m3u/i"; m3uFile = new Reader(m3uName); songArray = new Array(0); match = false; songName = ""; index = 0; SearchString = (StringInput ^ "[^A-Za-z0-9 ]+//g") # "/i"; while(m3uFile.isReadable()) { line = m3uFile.readLine(); if(!line) continue; if(line ~ "^#") { if(line ~ "^#EXTINF:\d+,(?:(.*?) - )?(.*?)$") songName = Windows.convertFromACPToUTF8(regex_captures[2]); if(line ~ SearchString) match = true; } else { if(!songName) songName = Windows.convertFromOEMCPToUTF8(line ^ "^(?:.*\\)(.*)$/$1"); if(line ~ SearchString) match = true; if(match) { data = new Array(2); data[0] = songName; data[1] = index; songArray.append(data); } songName = ""; match = false; index += 1; } } if(songArray.size == 0) { RemoteController.showDialog("No songs found"); RemoteController.store[0] = stSearchError; } else { // Now build artist array menuArray = new Array(0); for(i = 0; i < songArray.size; i += 1) menuArray.append( songArray[i][0] ); RemoteController.showSortedMenu("Search: " # StringInput, menuArray); RemoteController.store[0] = stSearchList; RemoteController.store[1] = songArray; } } } } else if(RemoteController.store[0] == stSearchError) { if(ExecuteData.type == etBack || ExecuteData.type == etNext) { showDialog = true; RemoteController.store[0] = stSearch; } } else if(RemoteController.store[0] == stSearchList) { if(ExecuteData.type == etBack) { showDialog = true; RemoteController.store[0] = stSearch; } else if(ExecuteData.type == etIntegerInput) { songIndex = RemoteController.store[1][ExecuteData.input][1]; // Stop window.sendMessageTimeout(0x111, 40047, 0, timeout, -1); // Set play list pos window.sendMessageTimeout(0x400, songIndex, 121, timeout, -1); // Start play window.sendMessageTimeout(0x111, 40045, 0, timeout, -1); // Return to info display showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } } else if(RemoteController.store[0] == stFeedback) { if(ExecuteData.type == etTimer || ExecuteData.type == etBack || ExecuteData.type == etNext) { showDialog = true; RemoteController.store[0] = stNormal; RemoteController.startTimer(500); } } if(showDialog) { if(!window) { RemoteController.showDialog("Press OK to launch WinAMP"); } else if(RemoteController.store[0] == stNormal || RemoteController.store[0] == stFastForward || RemoteController.store[0] == stRewind) { title = ""; artist = ""; album = ""; // Version check /* if(window.sendMessageTimeout(0x400, 0, 0, timeout, 0) >= 0x2090) { album = Helpers.GetWinampMetaInfo(window, "Album"); artist = Helpers.GetWinampMetaInfo(window, "Artist"); title = Helpers.GetWinampMetaInfo(window, "Title"); } */ if(!title) { if(window.name ~ "\d+\.\s+(.+?)(?: - (.+?))?\s*- Winamp(?:\s*?\[(.+)\])?") { if(regex_captures[2]) { title = regex_captures[2]; artist = regex_captures[1]; } else { title = regex_captures[1]; } } else { title = window.name; } } time = window.sendMessageTimeout(0x400, 0, 105, timeout, -1); totalTime = -1; if(time >= 0) { time = time / 1000; totalTime = window.sendMessageTimeout(0x400, 1, 105, timeout, -1); if(totalTime < time) totalTime = -1; } if(RemoteController.canShowMediaPlayer) { volume = window.sendMessageTimeout(0x400, -666, 122, timeout, 128); flags = 3; // Another version check if(window.sendMessageTimeout(0x400, 0, 0, timeout, 0) >= 0x5004 && window.sendMessageTimeout(0x400, 0, 124, timeout, 0) > 0) { flags = 7; rating = window.sendMessageTimeout(0x400, 0, 640, 200, 0); } else rating = 0; if(time < 0) time = 0; if(totalTime < 0) totalTime = 0; RemoteController.showMediaPlayer(flags, title, artist, album, time, totalTime, volume/2.55, rating); } else { text = title; if(artist != "") text #= crlf # artist; if(time >= 0) { text #= crlf # asInteger(time/60) # ":" # asBaseNString(time%60, 10, 2); if(totalTime > 0) text #= "/" # asInteger(totalTime/60) # ":" # asBaseNString(totalTime%60, 10, 2); } text #= crlf # "([fire] for help)"; RemoteController.showDialog(text); } } else if(RemoteController.store[0] == stHelp) { if(RemoteController.canShowMediaPlayer) { Text = "OK: Change mode" # crlf # "5: Play/Pause" # crlf # "1,3: Rewind/Forward" # crlf # "2: Stop" # crlf # "^ or 4,v or 6: Previous/Next Track" # crlf # "7: Enter Volume" # crlf # "8: Toggle Shuffle" # crlf # "9: Toggle Repeat" # crlf # "0: Next Visualization Preset" # crlf # "*: Extras" # crlf # "#: Toggle Visualization, keep it 1sec - go to Fullscreen mode" # crlf # "<,>: Change Volume"; } else { Text = "OK: Play/Pause" # crlf # "Menu: Extras" # crlf # "c: Stop" # crlf # "+,-: Volume Up/Down" # crlf # "Left,Right: Rewind/Fast Forward" # crlf # "Up,Down: Previous/Next Track" # crlf # "1: Change Volume" # crlf # "8: Toggle Shuffle" # crlf # "9: Toggle Repeat"; } // if(Windows.findWindow("Winamp AL")) Text #= crlf # "4,6: Previous/Next Album"; RemoteController.showText("WinAMP", Text); } else if(RemoteController.store[0] == stVolume) { // Nothing.. Already done. } else if(RemoteController.store[0] == stVolumeNoTimeout) { // Nothing.. Already done. } else if(RemoteController.store[0] == stExtraMenu) { MenuItems = new Array(0); MenuItems.append("Search..."); MenuItems.append("Browse all"); MenuItems.append("Browse all sorted"); MenuItems.append("Browse by artist"); RemoteController.showMenu("WinAMP", MenuItems); } else if(RemoteController.store[0] == stBrowseAll) { // Nothing.. already done } else if(RemoteController.store[0] == stBrowseArtists) { // Nothing.. already done } else if(RemoteController.store[0] == stBrowseArtistSongs) { // Nothing.. already done } else if(RemoteController.store[0] == stSearch) { RemoteController.showTextInput("Search..."); } else if(RemoteController.store[0] == stSearchError) { // Nothing.. already done } else if(RemoteController.store[0] == stFeedback) { // Nothing.. already done } else { RemoteController.showDialog("Internal error - unknown state"); } } //***************************************************************************