/* Copyright (C) 2001-2002 A Nourai 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 2 of the License, or (at your option) any later version. This program 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 included (GNU.txt) GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" #include "mp3_player.h" #include "utils.h" #include "keys.h" #include "modules.h" #if defined(_WIN32) || defined(__XMMS__) int COM_FileOpenRead (char *path, FILE **hndl); char *COM_FileExtension(char *); cvar_t mp3_scrolltitle = {"mp3_scrolltitle", "1"}; cvar_t mp3_showtime = {"mp3_showtime", "1"}; qboolean OnChange_mp3_volume(cvar_t *var, char *s); cvar_t mp3_volume = {"mp3_volume", "1", 0, OnChange_mp3_volume}; cvar_t mp3_grabvolume = {"mp3_grabvolume", "2"}; static char *mp3_notrunning_msg = MP3_PLAYERNAME_LEADINGCAP " is not running"; qboolean mp3_volumectrl_active = false; #endif #ifdef _WIN32 #include "windows.h" static HWND mp3_hwnd = 0; cvar_t mp3_dir = {"mp3_winamp_dir", "c:/program files/winamp"}; #endif #ifdef __XMMS__ #include #include cvar_t mp3_dir = {"mp3_xmms_dir", X11BASE "/bin"}; cvar_t mp3_xmms_session = {"mp3_xmms_session", "0"}; #endif #if defined(__XMMS__) static QLIB_HANDLETYPE_T libxmms_handle = NULL; void (*qxmms_remote_play)(gint session); void (*qxmms_remote_pause)(gint session); void (*qxmms_remote_stop)(gint session); void (*qxmms_remote_jump_to_time)(gint session, gint pos); gboolean (*qxmms_remote_is_running)(gint session); gboolean (*qxmms_remote_is_playing)(gint session); gboolean (*qxmms_remote_is_paused)(gint session); gboolean (*qxmms_remote_is_repeat)(gint session); gboolean (*qxmms_remote_is_shuffle)(gint session); gint (*qxmms_remote_get_playlist_pos)(gint session); void (*qxmms_remote_set_playlist_pos)(gint session, gint pos); gint (*qxmms_remote_get_playlist_length)(gint session); gchar *(*qxmms_remote_get_playlist_title)(gint session, gint pos); void (*qxmms_remote_playlist_prev)(gint session); void (*qxmms_remote_playlist_next)(gint session); gint (*qxmms_remote_get_output_time)(gint session); gint (*qxmms_remote_get_playlist_time)(gint session, gint pos); gint (*qxmms_remote_get_main_volume)(gint session); void (*qxmms_remote_set_main_volume)(gint session, gint v); void (*qxmms_remote_toggle_repeat)(gint session); void (*qxmms_remote_toggle_shuffle)(gint session); void (*qg_free)(gpointer); #define NUM_XMMSPROCS (sizeof(xmmsProcs)/sizeof(xmmsProcs[0])) static qlib_dllfunction_t xmmsProcs[] = { {"xmms_remote_play", (void **) &qxmms_remote_play}, {"xmms_remote_pause", (void **) &qxmms_remote_pause}, {"xmms_remote_stop", (void **) &qxmms_remote_stop}, {"xmms_remote_jump_to_time", (void **) &qxmms_remote_jump_to_time}, {"xmms_remote_is_running", (void **) &qxmms_remote_is_running}, {"xmms_remote_is_playing", (void **) &qxmms_remote_is_playing}, {"xmms_remote_is_paused", (void **) &qxmms_remote_is_paused}, {"xmms_remote_is_repeat", (void **) &qxmms_remote_is_repeat}, {"xmms_remote_is_shuffle", (void **) &qxmms_remote_is_shuffle}, {"xmms_remote_get_playlist_pos", (void **) &qxmms_remote_get_playlist_pos}, {"xmms_remote_set_playlist_pos", (void **) &qxmms_remote_set_playlist_pos}, {"xmms_remote_get_playlist_length", (void **) &qxmms_remote_get_playlist_length}, {"xmms_remote_get_playlist_title", (void **) &qxmms_remote_get_playlist_title}, {"xmms_remote_playlist_prev", (void **) &qxmms_remote_playlist_prev}, {"xmms_remote_playlist_next", (void **) &qxmms_remote_playlist_next}, {"xmms_remote_get_output_time", (void **) &qxmms_remote_get_output_time}, {"xmms_remote_get_playlist_time", (void **) &qxmms_remote_get_playlist_time}, {"xmms_remote_get_main_volume", (void **) &qxmms_remote_get_main_volume}, {"xmms_remote_set_main_volume", (void **) &qxmms_remote_set_main_volume}, {"xmms_remote_toggle_repeat", (void **) &qxmms_remote_toggle_repeat}, {"xmms_remote_toggle_shuffle", (void **) &qxmms_remote_toggle_shuffle}, {"g_free", (void **) &qg_free}, }; static void XMMS_LoadLibrary(void) { if (!(libxmms_handle = dlopen("libxmms.so.1", RTLD_NOW)) && !(libxmms_handle = dlopen("libxmms.so", RTLD_NOW))) return; if (!QLib_ProcessProcdef(libxmms_handle, xmmsProcs, NUM_XMMSPROCS)) { QLIB_FREELIBRARY(libxmms_handle); return; } } static void XMMS_FreeLibrary(void) { if (libxmms_handle) { QLIB_FREELIBRARY(libxmms_handle); } } #endif qboolean MP3_IsActive(void) { #if defined(_WIN32) return true; #elif defined(__XMMS__) return !!libxmms_handle; #endif } #ifdef _WIN32 static qboolean MP3_IsPlayerRunning(void) { return ((mp3_hwnd = FindWindow("FuhQuake Winamp", NULL)) || (mp3_hwnd = FindWindow("Winamp v1.x", NULL))); } void MP3_Execute_f(void) { STARTUPINFO si; PROCESS_INFORMATION pi; char path[256]; int length; if (MP3_IsPlayerRunning()) { Com_Printf("Winamp is already running\n"); return; } memset (&si, 0, sizeof(si)); si.cb = sizeof(si); si.wShowWindow = SW_SHOWMINNOACTIVE; si.dwFlags = STARTF_USESHOWWINDOW; Q_strncpyz(path, mp3_dir.string, sizeof(path) - strlen("/winamp.exe")); length = strlen(path); if (length && (path[length - 1] == '\\' || path[length - 1] == '/')) path[length - 1] = 0; strcat(path, "/winamp.exe"); if (!CreateProcess (NULL, va("%s /CLASS=\"FuhQuake Winamp\"", path), NULL, NULL, FALSE, GetPriorityClass(GetCurrentProcess()), NULL, NULL, &si, &pi)) { Com_Printf ("Couldn't execute winamp\n"); return; } Com_Printf("Winamp is now running\n"); return; } #define WINAMP_COMMAND(Name, Param) \ void MP3_##Name##_f(void) { \ int ret; \ \ if (MP3_IsPlayerRunning()) \ ret = SendMessage(mp3_hwnd, WM_COMMAND, Param, 0); \ else \ Com_Printf("%s\n", mp3_notrunning_msg); \ } WINAMP_COMMAND(Prev, WINAMP_BUTTON1); WINAMP_COMMAND(Play, WINAMP_BUTTON2); WINAMP_COMMAND(Pause, WINAMP_BUTTON3); WINAMP_COMMAND(Stop, WINAMP_BUTTON4); WINAMP_COMMAND(Next, WINAMP_BUTTON5); WINAMP_COMMAND(Rewind, WINAMP_BUTTON1_SHIFT); WINAMP_COMMAND(FastForward, WINAMP_BUTTON5_SHIFT); WINAMP_COMMAND(FadeOut, WINAMP_BUTTON4_SHIFT); int MP3_GetStatus(void) { int ret; if (!MP3_IsPlayerRunning()) return MP3_NOTRUNNING; ret = SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_ISPLAYING); switch (ret) { case 3 : return MP3_PAUSED; break; case 1 : return MP3_PLAYING; break; case 0 : default : return MP3_STOPPED; break; } } qboolean OnChange_mp3_volume(cvar_t *var, char *s) { int vol; if (!MP3_IsPlayerRunning()) return false; if (!mp3_volumectrl_active) return true; vol = (int) (Q_atof(s) * 255.0 + 0.5); vol = bound (0, vol, 255); SendMessage(mp3_hwnd, WM_WA_IPC, vol, IPC_SETVOLUME); return false; } static void WINAMP_Set_ToggleFn(char *name, int setparam, int getparam) { int ret, set; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } if (Cmd_Argc() >= 3) { Com_Printf("Usage: %s [on|off|toggle]\n", Cmd_Argv(0)); return; } ret = SendMessage(mp3_hwnd, WM_WA_IPC, 0, getparam); if (Cmd_Argc() == 1) { Com_Printf("%s is %s\n", name, (ret == 1) ? "on" : "off"); return; } if (!Q_strcasecmp(Cmd_Argv(1), "on")) { set = 1; } else if (!Q_strcasecmp(Cmd_Argv(1), "off")) { set = 0; } else if (!Q_strcasecmp(Cmd_Argv(1), "toggle")) { set = ret ? 0 : 1; } else { Com_Printf("Usage: %s [on|off|toggle]\n", Cmd_Argv(0)); return; } SendMessage(mp3_hwnd, WM_WA_IPC, set, setparam); Com_Printf("%s set to %s\n", name, set ? "on" : "off"); } void MP3_Repeat_f(void) { WINAMP_Set_ToggleFn("Repeat", IPC_SET_REPEAT, IPC_GET_REPEAT); } void MP3_Shuffle_f(void) { WINAMP_Set_ToggleFn("Shuffle", IPC_SET_SHUFFLE, IPC_GET_SHUFFLE); } static void WINAMP_Toggle_ToggleFn(char *name, int setparam, int getparam) { int ret; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } ret = SendMessage(mp3_hwnd, WM_WA_IPC, 0, getparam); SendMessage(mp3_hwnd, WM_WA_IPC, ret ? 0 : 1, setparam); } void MP3_ToggleRepeat_f(void) { WINAMP_Toggle_ToggleFn("Repeat", IPC_SET_REPEAT, IPC_GET_REPEAT); } void MP3_ToggleShuffle_f(void) { WINAMP_Toggle_ToggleFn("Shuffle", IPC_SET_SHUFFLE, IPC_GET_SHUFFLE); } char *MP3_Macro_MP3Info(void) { char *s; static char title[MP3_MAXSONGTITLE]; if (!MP3_IsPlayerRunning()) { Q_strncpyz(title, mp3_notrunning_msg, sizeof(title)); return title; } GetWindowText(mp3_hwnd, title, sizeof(title)); if ((s = strrchr(title, '-')) && s > title) *(s - 1) = 0; for (s = title; *s && isdigit(*s); s++) ; if (*s == '.' && s[1] == ' ' && s[2]) memmove(title, s + 2, strlen(s + 2) + 1); return title; } qboolean MP3_GetOutputtime(int *elapsed, int *total) { int ret1, ret2; if (!MP3_IsPlayerRunning()) return false; if (!(ret1 = SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_GETOUTPUTTIME)) == -1) return false; if (!(ret2 = SendMessage(mp3_hwnd, WM_WA_IPC, 1, IPC_GETOUTPUTTIME)) == -1) return false; *elapsed = ret1 / 1000; *total = ret2; return true; } qboolean MP3_GetToggleState(int *shuffle, int *repeat) { int ret1, ret2; if (!MP3_IsPlayerRunning()) return false; if (!(ret1 = SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_GET_SHUFFLE)) == -1) return false; if (!(ret2 = SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_GET_REPEAT)) == -1) return false; *shuffle = ret1; *repeat = ret2; return true; } #endif #ifdef __XMMS__ static qboolean MP3_IsPlayerRunning(void) { return (qxmms_remote_is_running((gint) XMMS_SESSION)); } static int XMMS_pid = 0; void MP3_Execute_f(void) { char path[MAX_OSPATH], *argv[2] = {"xmms", NULL}, **s; int i, length; if (MP3_IsPlayerRunning()) { Com_Printf("XMMS is already running\n"); return; } Q_strncpyz(path, mp3_dir.string, sizeof(path) - strlen("/xmms")); length = strlen(path); for (i = 0; i < length; i++) { if (path[i] == '\\') path[i] = '/'; } if (length && path[length - 1] == '/') path[length - 1] = 0; strcat(path, "/xmms"); if (!(XMMS_pid = fork())) { execv(path, argv); exit(-1); } if (XMMS_pid == -1) { Com_Printf ("Couldn't execute XMMS\n"); return; } for (i = 0; i < 6; i++) { Sys_MSleep(50); if (MP3_IsPlayerRunning()) { Com_Printf("XMMS is now running\n"); return; } } Com_Printf("XMMS (probably) failed to run\n"); } #define XMMS_COMMAND(Name, Param) \ void MP3_##Name##_f(void) { \ if (MP3_IsPlayerRunning()) { \ qxmms_remote_##Param(XMMS_SESSION); \ } else { \ Com_Printf("%s\n", mp3_notrunning_msg); \ } \ return; \ } XMMS_COMMAND(Prev, playlist_prev); XMMS_COMMAND(Play, play); XMMS_COMMAND(Pause, pause); XMMS_COMMAND(Stop, stop); XMMS_COMMAND(Next, playlist_next); XMMS_COMMAND(FadeOut, stop); void MP3_FastForward_f(void) { int current; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } current = qxmms_remote_get_output_time(XMMS_SESSION) + 5 * 1000; qxmms_remote_jump_to_time(XMMS_SESSION, current); } void MP3_Rewind_f(void) { int current; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } current = qxmms_remote_get_output_time(XMMS_SESSION) - 5 * 1000; current = max(0, current); qxmms_remote_jump_to_time(XMMS_SESSION, current); } int MP3_GetStatus(void) { if (!MP3_IsPlayerRunning()) return MP3_NOTRUNNING; if (qxmms_remote_is_paused(XMMS_SESSION)) return MP3_PAUSED; if (qxmms_remote_is_playing(XMMS_SESSION)) return MP3_PLAYING; return MP3_STOPPED; } qboolean OnChange_mp3_volume(cvar_t *var, char *s) { int vol; if (!MP3_IsPlayerRunning()) return false; if (!mp3_volumectrl_active) return true; vol = (int) (Q_atof(s) * 100 + 0.5); vol = bound(0, vol, 100); qxmms_remote_set_main_volume(XMMS_SESSION, vol); return false; } static void XMMS_Set_ToggleFn(char *name, void *togglefunc, void *getfunc) { int ret, set; gboolean (*xmms_togglefunc)(gint) = togglefunc; gboolean (*xmms_getfunc)(gint) = getfunc; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } if (Cmd_Argc() >= 3) { Com_Printf("Usage: %s [on|off|toggle]\n", Cmd_Argv(0)); return; } ret = xmms_getfunc(XMMS_SESSION); if (Cmd_Argc() == 1) { Com_Printf("%s is %s\n", name, (ret == 1) ? "on" : "off"); return; } if (!Q_strcasecmp(Cmd_Argv(1), "on")) { set = 1; } else if (!Q_strcasecmp(Cmd_Argv(1), "off")) { set = 0; } else if (!Q_strcasecmp(Cmd_Argv(1), "toggle")) { set = ret ? 0 : 1; } else { Com_Printf("Usage: %s [on|off|toggle]\n", Cmd_Argv(0)); return; } if (set && !ret) xmms_togglefunc(XMMS_SESSION); else if (!set && ret) xmms_togglefunc(XMMS_SESSION); Com_Printf("%s set to %s\n", name, set ? "on" : "off"); } void MP3_Repeat_f(void) { XMMS_Set_ToggleFn("Repeat", qxmms_remote_toggle_repeat, qxmms_remote_is_repeat); } void MP3_Shuffle_f(void) { XMMS_Set_ToggleFn("Shuffle", qxmms_remote_toggle_shuffle, qxmms_remote_is_shuffle); } void MP3_ToggleRepeat_f(void) { if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } qxmms_remote_toggle_repeat(XMMS_SESSION); } void MP3_ToggleShuffle_f(void) { if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } qxmms_remote_toggle_shuffle(XMMS_SESSION); } char *MP3_Macro_MP3Info(void) { int playlist_pos; char *s; static char title[MP3_MAXSONGTITLE]; if (!MP3_IsPlayerRunning()) { Com_Printf("XMMS not running\n"); return NULL; } playlist_pos = qxmms_remote_get_playlist_pos(XMMS_SESSION); s = qxmms_remote_get_playlist_title(XMMS_SESSION, playlist_pos); Q_strncpyz(title, s ? s : "", sizeof(title)); g_free(s); return title; } qboolean MP3_GetOutputtime(int *elapsed, int *total) { int status, pos; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return false; } pos = qxmms_remote_get_playlist_pos(XMMS_SESSION); *elapsed = qxmms_remote_get_output_time(XMMS_SESSION) / 1000.0; *total = qxmms_remote_get_playlist_time(XMMS_SESSION, pos) / 1000.0; return true; } qboolean MP3_GetToggleState(int *shuffle, int *repeat) { if (!MP3_IsPlayerRunning()) return false; *shuffle = qxmms_remote_is_shuffle(XMMS_SESSION); *repeat = qxmms_remote_is_repeat(XMMS_SESSION); return true; } #endif #if defined(_WIN32) || defined(__XMMS__) void MP3_SongInfo_f(void) { char *status_string, *title, *s; char elapsed_string[MP3_MAXSONGTITLE]; int status, elapsed, total; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } status = MP3_GetStatus(); if (Cmd_Argc() != 1) { Com_Printf("%s : no arguments expected\n", Cmd_Argv(0)); return; } if (status == MP3_STOPPED) status_string = "\x10Stopped\x11"; else if (status == MP3_PAUSED) status_string = "\x10Paused\x11"; else status_string = "\x10Playing\x11"; for (s = title = MP3_Macro_MP3Info(); *s; s++) *s |= 128; if (!MP3_GetOutputtime(&elapsed, &total) || elapsed < 0 || total < 0) { Com_Printf(va("%s %s\n", status_string, title)); return; } Q_strncpyz(elapsed_string, SecondsToMinutesString(elapsed), sizeof(elapsed_string)); Com_Printf(va("%s %s \x10%s/%s\x11\n", status_string, title, elapsed_string, SecondsToMinutesString(total))); } char *MP3_Menu_SongtTitle(void) { static char title[MP3_MAXSONGTITLE], *macrotitle; int current; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); Q_strncpyz(title, mp3_notrunning_msg, sizeof(title)); return title; } macrotitle = MP3_Macro_MP3Info(); MP3_GetPlaylistInfo(¤t, NULL); if (*macrotitle) Q_strncpyz(title, va("%d. %s", current + 1, macrotitle), sizeof(title)); else Q_strncpyz(title, MP3_PLAYERNAME_ALLCAPS, sizeof(title)); return title; } #endif #ifdef _WIN32 void MP3_LoadPlaylist_f(void) { COPYDATASTRUCT cds; char playlist[64]; if (Cmd_Argc() == 1) { Com_Printf("Usage: %s \n", Cmd_Argv(0)); return; } if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } Q_strncpyz(playlist, Cmd_Args(), sizeof(playlist)); if (!strcmp(COM_FileExtension(playlist), "pls")) { Com_Printf("Error: .pls playlists are not supported. Try loading a .m3u playlist\n"); return; } COM_ForceExtension(playlist, ".m3u"); SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_DELETE); cds.dwData = IPC_PLAYFILE; cds.lpData = playlist; cds.cbData = strlen(playlist) + 1; SendMessage(mp3_hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); } long MP3_GetPlaylist(char **buf) { FILE *f; char path[512]; int pathlength; long filelength; COPYDATASTRUCT cds; if (!MP3_IsPlayerRunning()) return -1; cds.dwData = IPC_CHDIR; cds.lpData = mp3_dir.string; cds.cbData = strlen(mp3_dir.string) + 1; SendMessage(mp3_hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_WRITEPLAYLIST); Q_strncpyz(path, mp3_dir.string, sizeof(path)); pathlength = strlen(path); if (pathlength && (path[pathlength - 1] == '\\' || path[pathlength - 1] == '/')) path[pathlength - 1] = 0; strcat(path, "/winamp.m3u"); filelength = COM_FileOpenRead(path, &f); if (!f) return -1; *buf = Q_Malloc(filelength); if (filelength != fread(*buf, 1, filelength, f)) { free(*buf); fclose(f); return -1; } fclose(f); return filelength; } void MP3_GetPlaylistInfo(int *current, int *length) { if (!MP3_IsPlayerRunning()) return; if (length) *length = SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_GETLISTLENGTH); if (current) *current = SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_GETLISTPOS); } void MP3_PrintPlaylist_f(void) { char *playlist_buf, *entries[256]; unsigned int length; int i, playlist_size, current; if ((length = MP3_GetPlaylist(&playlist_buf)) == -1) { Com_Printf("%s\n", mp3_notrunning_msg); return; } MP3_GetPlaylistInfo(¤t, NULL); playlist_size = MP3_ParsePlaylist_EXTM3U(playlist_buf, length, entries, sizeof(entries) / sizeof(entries[0]), 128); for (i = 0; i < playlist_size; i++) { Com_Printf("%s%3d %s\n", i == current ? "\x02" : "", i + 1, entries[i]); free(entries[i]); } free(playlist_buf); } void MP3_PlayTrackNum_f(void) { int pos, length; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } if (Cmd_Argc() != 2) { Com_Printf("Usage: %s \n", Cmd_Argv(0)); return; } MP3_GetPlaylistInfo(NULL, &length); pos = Q_atoi(Cmd_Argv(1)) - 1; if (pos < 0 || pos >= length) return; SendMessage(mp3_hwnd, WM_WA_IPC, pos, IPC_SETPLAYLISTPOS); MP3_Play_f(); } #endif #ifdef __XMMS__ void MP3_LoadPlaylist_f(void) { Com_Printf("The %s command is not (yet) supported.\n", Cmd_Argv(0)); } void MP3_GetPlaylistInfo(int *current, int *length) { if (!MP3_IsPlayerRunning()) return; if (length) *length = qxmms_remote_get_playlist_length(XMMS_SESSION); if (current) *current = qxmms_remote_get_playlist_pos(XMMS_SESSION); } void MP3_PrintPlaylist_f(void) { int current, length, i; char *title, *s; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } MP3_GetPlaylistInfo(¤t, &length); for (i = 0 ; i < length; i ++) { title = qxmms_remote_get_playlist_title(XMMS_SESSION, i); if (i == current) for (s = title; *s; s++) *s |= 128; Com_Printf("%3d %s\n", i + 1, title); } return; } void MP3_PlayTrackNum_f(void) { int pos, length; if (!MP3_IsPlayerRunning()) { Com_Printf("%s\n", mp3_notrunning_msg); return; } if (Cmd_Argc() != 2) { Com_Printf("Usage: %s \n", Cmd_Argv(0)); return; } MP3_GetPlaylistInfo(NULL, &length); pos = Q_atoi(Cmd_Argv(1)) - 1; if (pos < 0 || pos >= length) return; qxmms_remote_set_playlist_pos(XMMS_SESSION, pos); MP3_Play_f(); } #endif int MP3_ParsePlaylist_EXTM3U(char *playlist_buf, unsigned int length, char *entries[], unsigned int maxsize, unsigned int maxsonglen) { int skip = 0, playlist_size = 0; char *s, *t, *buf, *line; buf = playlist_buf; while (playlist_size < maxsize) { for (s = line = buf; s - playlist_buf < length && *s && *s != '\n' && *s != '\r'; s++) ; if (s - playlist_buf >= length) break; *s = 0; buf = s + 2; if (skip || !strncmp(line, "#EXTM3U", 7)) { skip = 0; continue; } if (!strncmp(line, "#EXTINF:", 8)) { if (!(s = strstr(line, ",")) || ++s - playlist_buf >= length) break; if (strlen(s) > maxsonglen) s[maxsonglen] = 0; entries[playlist_size++] = strdup(s); skip = 1; continue; } for (s = line + strlen(line); s > line && *s != '\\' && *s != '/'; s--) ; if (s != line) s++; if ((t = strrchr(s, '.')) && t - playlist_buf < length) *t = 0; for (t = s + strlen(s) - 1; t > s && *t == ' '; t--) *t = 0; if (strlen(s) > maxsonglen) s[maxsonglen] = 0; entries[playlist_size++] = strdup(s); } return playlist_size; } #if defined(_WIN32) || defined(__XMMS__) void MP3_Init(void) { #ifdef __XMMS__ XMMS_LoadLibrary(); #endif if (!MP3_IsActive()) return; mp3_volumectrl_active = !COM_CheckParm("-nomp3volumectrl"); Cmd_AddMacro("mp3info", MP3_Macro_MP3Info); Cmd_AddCommand("mp3_prev", MP3_Prev_f); Cmd_AddCommand("mp3_play", MP3_Play_f); Cmd_AddCommand("mp3_pause", MP3_Pause_f); Cmd_AddCommand("mp3_stop", MP3_Stop_f); Cmd_AddCommand("mp3_next", MP3_Next_f); Cmd_AddCommand("mp3_fforward", MP3_FastForward_f); Cmd_AddCommand("mp3_rewind", MP3_Rewind_f); Cmd_AddCommand("mp3_fadeout", MP3_FadeOut_f); Cmd_AddCommand("mp3_shuffle", MP3_Shuffle_f); Cmd_AddCommand("mp3_repeat", MP3_Repeat_f); Cmd_AddCommand("mp3_playlist", MP3_PrintPlaylist_f); Cmd_AddCommand("mp3_playtrack", MP3_PlayTrackNum_f); Cmd_AddCommand("mp3_songinfo", MP3_SongInfo_f); Cmd_AddCommand("mp3_loadplaylist", MP3_LoadPlaylist_f); Cmd_AddCommand("mp3_start" MP3_PLAYERNAME_NOCAPS, MP3_Execute_f); Cvar_SetCurrentGroup(CVAR_GROUP_MP3); Cvar_Register(&mp3_dir); Cvar_Register(&mp3_scrolltitle); Cvar_Register(&mp3_showtime); Cvar_Register(&mp3_volume); Cvar_Register(&mp3_grabvolume); #ifdef __XMMS__ Cvar_Register(&mp3_xmms_session); #endif Cvar_ResetCurrentGroup(); } #else void MP3_Init(void) {} #endif #if defined(_WIN32) || defined(__XMMS__) void MP3_Frame(void) { float vol; if (!mp3_grabvolume.value) return; if (!MP3_IsPlayerRunning()) return; #ifdef _WIN32 vol = SendMessage(mp3_hwnd, WM_WA_IPC, -666, IPC_SETVOLUME) / 255.0; vol = ((int) (vol * 100)) / 100.0; #else vol = qxmms_remote_get_main_volume(XMMS_SESSION) / 100.0; #endif vol = bound(0, vol, 1); if (vol != mp3_volume.value) { mp3_volume.OnChange = NULL; Cvar_SetValue(&mp3_volume, vol); mp3_volume.OnChange = OnChange_mp3_volume; } } void MP3_Shutdown(void) { #ifdef __XMMS__ if (XMMS_pid) { if (!kill(XMMS_pid, SIGTERM)) waitpid(XMMS_pid, NULL, 0); } #endif } #else void MP3_Frame(void) {} void MP3_Shutdown(void) {} #endif