- Install to ~/.local/bin/winamp-mpris - Use ~/.local/state/winamp-mpris/bridge.log for logging - Use $XDG_RUNTIME_DIR/winamp-mpris.pid for PID management - Add detailed user notification for 401 Unauthorized errors - Add install.sh for automated, standard-compliant setup - Include Winamp Web Interface source code and installer in repository
1027 lines
28 KiB
C++
1027 lines
28 KiB
C++
/* --- OP_WINAMP.CPP ---
|
|
/
|
|
/ Written by Phil Himsworth, 2001-2002.
|
|
/
|
|
/*/
|
|
|
|
#include <windows.h>
|
|
#include "types.h"
|
|
#include "main.h"
|
|
#include "plugin.h"
|
|
#include "html.h"
|
|
#include "wamessage.h"
|
|
#include "op_winamp.h"
|
|
#include "resource.h"
|
|
|
|
extern char mp3root[MAX_PATH], playlistdir[MAX_PATH], logfiledir[MAX_PATH], filetypes[255];
|
|
extern int browse_enable, dl_wa_files, dl_other_files, show_other_files, frames, title_refresh, securepassword;
|
|
|
|
extern char szAppVer[];
|
|
extern char pagetitle[255];
|
|
|
|
|
|
extern winampGeneralPurposePlugin plugin;
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Send an image from a resource
|
|
int CControl::Image(connection * conn,int type)
|
|
{
|
|
//char * img = &conn->http.file[5];
|
|
char img[30];
|
|
GetArgValue(conn,"image",(char*)&img,30);
|
|
//MessageBox(NULL,img,"gen_httpSrv debug",MB_OK | MB_TOPMOST);
|
|
int imageid = atoi2(img);
|
|
|
|
char dll[MAX_PATH];
|
|
GetModuleFileName(plugin.hDllInstance,dll,sizeof(dll));
|
|
HMODULE hm = GetModuleHandle(dll);
|
|
if (hm == NULL)
|
|
MessageBox(NULL,"gmh failed","gen_httpSrv debug",MB_OK);
|
|
|
|
HRSRC resimage = FindResource(hm,MAKEINTRESOURCE(imageid),"Image");
|
|
if (!resimage) // after an image that doesn't exist
|
|
{
|
|
|
|
//MessageBox(NULL,"Bad image","gen_httpSrv debug",MB_OK);
|
|
return ST_CLOSE;
|
|
//closesocket(conn.socket);
|
|
//return true;
|
|
}
|
|
|
|
HGLOBAL image = LoadResource(hm, resimage);
|
|
DWORD imglen = SizeofResource(hm, resimage);
|
|
|
|
switch(type)
|
|
{
|
|
case IMG_GIF:
|
|
OpenHTTPHeader(conn,"image/gif",(int)imglen,NULL);
|
|
break;
|
|
case IMG_ICO:
|
|
OpenHTTPHeader(conn,"image/x-icon",(int)imglen,NULL);
|
|
break;
|
|
}
|
|
|
|
if(conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
flush(conn);
|
|
send(conn->socket,(char*)image,imglen,0);
|
|
return ST_CLOSE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Sends top frame with buttons and the like
|
|
int CControl::TopFrame(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
CloseHeader(conn);
|
|
OpenHeaderBody(conn);
|
|
LinkTable(conn);
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Tiny title
|
|
int CControl::SmallTitle(connection * conn)
|
|
{
|
|
conn->log = false;
|
|
OpenHTTPHeader(conn,"text/plain",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
SongInfo(conn);
|
|
prints(conn,"\n\n");
|
|
|
|
return ST_CLOSE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Sends full title information
|
|
int CControl::Title(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
else
|
|
{
|
|
OpenHtmlHeader(conn);
|
|
prints(conn,"<meta http-equiv=\"Refresh\" content=\"");
|
|
printsi(conn,title_refresh);
|
|
prints(conn,"; url=/title\">\n");
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
FullSongInfo(conn);
|
|
|
|
prints(conn,"\n");
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Shuts down winamp and the computer, in theory. Doesn't, though...
|
|
int CControl::Shutdown(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Turning off...</p>\n");
|
|
|
|
ExitWindows(0,0);
|
|
PostMessage(WAwnd(),WM_CLOSE,0,0);
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Clears playlist
|
|
int CControl::Clear(connection * conn)
|
|
{
|
|
SendMessage(WAwnd(),WM_USER,0,WAU_CLEARPLIST);
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
RefreshHeader(conn,"/list");
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Playlist cleared</p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Download a song
|
|
int CControl::Download(connection * conn)
|
|
{
|
|
// exactly the same filename processing as Load, below.
|
|
char filepath[MAX_PATH];
|
|
GetArgValue(conn,"file",filepath,MAX_PATH);
|
|
|
|
//char *relfilepath = &conn->http.file[4];
|
|
Unescape_url(filepath);
|
|
ReplaceSlashes(filepath);
|
|
|
|
if (!GoodPath(filepath))
|
|
ReportError(conn,"<p>The path requested is illegal.</p>\n<p>It cotains the <b>..</b> directory, which could present a security risk.</p>\n");
|
|
else
|
|
{
|
|
bool wafile = IsWinampFile(GetFilename(filepath));
|
|
|
|
if ((wafile && dl_wa_files==0) || (!wafile && dl_other_files==0))
|
|
ReportError(conn,"<p>Downloading files of this type is not permitted from this server.</p>");
|
|
else
|
|
{
|
|
char fullfilepath[MAX_PATH];
|
|
int pathlen = wsprintf(fullfilepath,"%s%s",mp3root,filepath);
|
|
Unescape_url((char*)&fullfilepath);
|
|
|
|
/*
|
|
- Open a header with the right MIME type - needs file size
|
|
- Call TransmitFile()
|
|
- Rockin'.
|
|
*/
|
|
|
|
HANDLE hFile = CreateFile( fullfilepath,
|
|
GENERIC_READ,
|
|
0,
|
|
0,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
|
0);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
ReportError(conn,"<p>Couldn't open the file.</p>\n<p>Check the file exists and the name is correct.</p>\n");
|
|
else
|
|
{
|
|
DWORD dwSize = GetFileSize(hFile, NULL);
|
|
OpenHTTPHeader(conn,"audio/mpeg",dwSize,GetFilename(fullfilepath));
|
|
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
flush(conn);
|
|
|
|
TransmitFile(conn->socket, hFile, dwSize, 0, NULL, NULL, NULL);
|
|
CloseHandle(hFile);
|
|
return ST_CLOSE;
|
|
}
|
|
}
|
|
}
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Load a song into the playlist
|
|
int CControl::Load(connection * conn)
|
|
{
|
|
char relfilepath[MAX_PATH];
|
|
char filepath[MAX_PATH];
|
|
char shortcutfilepath[MAX_PATH];
|
|
char playmode[10];
|
|
GetArgValue(conn,"path",relfilepath,MAX_PATH);
|
|
Unescape_url(relfilepath);
|
|
|
|
char refreshto[MAX_PATH];
|
|
|
|
if (relfilepath[0] == '\\' && relfilepath[1] != '\\') // single slash - local file (not UNC '\\' or HTTP 'http://...')
|
|
{
|
|
if (!GoodPath(relfilepath))
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p><b>Error!</b> The path requested is illegal.</p>\n");
|
|
prints(conn,"<p> </p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
else // Local path is okay
|
|
{
|
|
// need to check whether it's a url shortcut file
|
|
fileinfo file;
|
|
lstrcpy(file.name,relfilepath);
|
|
IsWinampFile(&file);
|
|
if (file.urlsct) // url shortcut; load contained address into 'filepath'
|
|
{
|
|
wsprintf(shortcutfilepath,"%s%s",mp3root,relfilepath);
|
|
GetPrivateProfileString("InternetShortcut","URL","",filepath,MAX_PATH,shortcutfilepath);
|
|
}
|
|
else // not a shortcut; just put the right path into filepath
|
|
{
|
|
wsprintf(filepath,"%s%s",mp3root,relfilepath);
|
|
}
|
|
|
|
// refresh to "/browse?path=<directory containing file>"
|
|
char * p;
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
{
|
|
char refreshtemp[MAX_PATH];
|
|
wsprintf(refreshtemp,"%s",relfilepath);
|
|
|
|
p=refreshtemp+lstrlen(refreshtemp);
|
|
while (p >= refreshtemp && *p != '\\') p--;
|
|
if (++p >= refreshtemp) *p = 0;
|
|
Escape_url(refreshtemp);
|
|
wsprintf(refreshto,"/browse?path=%s",refreshtemp);
|
|
}
|
|
}
|
|
}
|
|
else // HTTP or UNC name; load directly
|
|
{
|
|
wsprintf(filepath,"%s",relfilepath);
|
|
}
|
|
|
|
//MessageBox(NULL,filepath,"filepath",MB_OK | MB_TOPMOST);
|
|
|
|
|
|
int pathlen = lstrlen(filepath);
|
|
COPYDATASTRUCT cds;
|
|
cds.dwData = IPC_PLAYFILE;
|
|
cds.lpData = (void *)&filepath;
|
|
cds.cbData = pathlen+1;
|
|
SendMessage(WAwnd(),WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
|
|
|
|
if (GetArgValue(conn,"play",playmode,10))
|
|
{
|
|
if (StrComp(playmode,"now"))
|
|
{
|
|
int pl_len = SendMessage(WAwnd(),WM_USER,0,WAU_PLCOUNT);
|
|
SendMessage(WAwnd(),WM_USER,pl_len-1,WAU_SETPLPOS);
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_PLAY,0);
|
|
}
|
|
}
|
|
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
GetArgValue(conn,"refresh",refreshto,10); // will overwrite existing value if
|
|
// the param exists
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<p>Load file command sent: <b>");
|
|
prints(conn,relfilepath); // actually relfilepath
|
|
prints(conn,"</b></p>\n");
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Send playlist page
|
|
int CControl::List(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
if (frames == 1)
|
|
LinkBar(conn);
|
|
|
|
prints(conn,"<h3>\n<i>\n... Current Playlist ...\n</i></h3>\n");
|
|
|
|
prints(conn,"<form action=\"/list\" method=\"get\">\n");
|
|
prints(conn,"Show only songs containing: <input type=\"text\" name=\"sub\" size=\"30\">\n");
|
|
prints(conn,"<input type=\"submit\" value=\"Search\">\n");
|
|
prints(conn,"</form>\n");
|
|
|
|
prints(conn,"<h6>\n<a href=\"#current\">Jump to Current Track</a> | ");
|
|
prints(conn,"<a href=\"/sort\">Sort Playlist</a> | <a href=\"/clear\">Clear Playlist</a>");
|
|
prints(conn," | <a href=\"save\">Save Playlist</a></h6>\n<ol>\n");
|
|
|
|
char song[255], lcasesong[255], substring[255];
|
|
|
|
bool restrict = GetArgValue(conn,"sub",substring,255); // search for substring?
|
|
if (restrict && substring[0] == 0) // if it's blank, show all
|
|
restrict = false;
|
|
|
|
if (restrict)
|
|
{
|
|
Unescape_url(substring);
|
|
CharLower(substring);
|
|
prints(conn,"<p>Showing songs containing: ");
|
|
prints(conn,substring);
|
|
prints(conn,"</p>\n");
|
|
}
|
|
|
|
prints(conn,"<ol>\n");
|
|
|
|
int current = SendMessage(WAwnd(),WM_USER, 0, WAU_GETPLPOS);
|
|
char tbuffer[255];
|
|
int t = SendMessage(WAwnd(),WM_USER, 0, WAU_PLCOUNT);
|
|
for (int count=0;count<t;count++)
|
|
{
|
|
lstrcpy(song,(char*)SendMessage(WAwnd(),WM_USER, count, WAU_GETTITLE));
|
|
lstrcpy(lcasesong,song);
|
|
CharLower(lcasesong);
|
|
if (strstr2(lcasesong,substring) || restrict == false)
|
|
{
|
|
if (count == current)
|
|
prints(conn,"<b><a name=\"current\"></a>");
|
|
|
|
prints(conn,"<li>");
|
|
|
|
wsprintf(tbuffer,"/delete?track=%d",count+1);
|
|
ImgLink(conn,tbuffer,IDR_IMG_LIST_DEL,"Remove",0,0,T_MAIN);
|
|
wsprintf(tbuffer,"/play?track=%d",count+1);
|
|
ImgLink(conn,tbuffer,IDR_IMG_LIST_PLAY,"Play",0,0,T_BOTTOM);
|
|
|
|
if (frames == 3)
|
|
wsprintf(tbuffer,"<a href=\"/play?track=%d\" target=\"bottom\">%s</a></li>\n", count+1, song);
|
|
else
|
|
wsprintf(tbuffer,"<a href=\"/play?track=%d\" >%s</a></li>\n", count+1, song);
|
|
|
|
prints(conn,tbuffer);
|
|
if (count == current)
|
|
prints(conn,"</b>");
|
|
}
|
|
|
|
}
|
|
|
|
prints(conn,"</ol>\n</p>");
|
|
if (frames == 1)
|
|
LinkBar(conn);
|
|
prints(conn,"<p> </p>");
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Next track
|
|
int CControl::Next(connection * conn)
|
|
{
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_NEXT,0);
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Next track command sent</p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Previous track
|
|
int CControl::Prev(connection * conn)
|
|
{
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_PREV,0);
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
RefreshHeader(conn,refreshto);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Previous track command sent</p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Start playback
|
|
int CControl::Play(connection * conn)
|
|
{
|
|
char strtrack[10];
|
|
if (GetArgValue(conn,"track",strtrack,10))
|
|
{
|
|
int track = atoi2(strtrack) - 1;
|
|
if (track >= 0)
|
|
SendMessage(WAwnd(),WM_USER,track,WAU_SETPLPOS);
|
|
}
|
|
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_PLAY,0);
|
|
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Play command sent</p>\n");
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Stop playback
|
|
int CControl::Stop(connection * conn)
|
|
{
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_STOP,0);
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
OpenHtmlHeader(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
RefreshHeader(conn,refreshto);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Stop command sent</p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Stop with fadeout
|
|
int CControl::StopSlow(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Stopping...");
|
|
flush(conn);
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_STOPFADE,0);
|
|
prints(conn," OK!</p>\n");
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Pause. Why am I even bothering to comment these?!?
|
|
int CControl::Pause(connection * conn)
|
|
{
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_PAUSE,0);
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
RefreshHeader(conn,refreshto);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Pause command sent</p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Change volume
|
|
int CControl::Volume(connection * conn)
|
|
{
|
|
char strvol[20];
|
|
GetArgValue(conn,"volume",strvol,20);
|
|
|
|
int vol = atoi2(strvol); // Mwuahaha, die Clib
|
|
vol = (int)(vol * 25.5);
|
|
SendMessage(WAwnd(),WM_USER,vol,122);
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
{
|
|
if (frames == 3)
|
|
wsprintf(refreshto,"/title");
|
|
else
|
|
wsprintf(refreshto,"/main");
|
|
}
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<p>Change volume command sent</p>\n");
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Change repeat / random modes
|
|
int CControl::Playmode(connection * conn)
|
|
{
|
|
char repeat[10], random[10];
|
|
if (!GetArgValue(conn,"repeat",repeat,10))
|
|
wsprintf(repeat,"none");
|
|
if (!GetArgValue(conn,"random",random,10))
|
|
wsprintf(random,"none");
|
|
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
wsprintf(refreshto,"/main");
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
if (StrComp(repeat,"on"))
|
|
{
|
|
SendMessage(WAwnd(),WM_USER,1,WAU_SETREPEAT);
|
|
prints(conn,"<p>Repeat set to <b>ON</b></p>");
|
|
}
|
|
if (StrComp(repeat,"off"))
|
|
{
|
|
SendMessage(WAwnd(),WM_USER,0,WAU_SETREPEAT);
|
|
prints(conn,"<p>Repeat set to <b>OFF</b></p>");
|
|
}
|
|
if (StrComp(repeat,"toggle"))
|
|
{
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_REPEATT,0);
|
|
prints(conn,"<p>Repeat toggled</p>");
|
|
}
|
|
|
|
if (StrComp(random,"on"))
|
|
{
|
|
SendMessage(WAwnd(),WM_USER,1,WAU_SETRANDOM);
|
|
prints(conn,"<p>Random set to <b>ON</b></p>");
|
|
}
|
|
if (StrComp(random,"off"))
|
|
{
|
|
SendMessage(WAwnd(),WM_USER,0,WAU_SETRANDOM);
|
|
prints(conn,"<p>Random set to <b>OFF</b></p>");
|
|
}
|
|
if (StrComp(random,"toggle"))
|
|
{
|
|
SendMessage(WAwnd(),WM_COMMAND,WAC_RANDOMT,0);
|
|
prints(conn,"<p>Random toggled</p>");
|
|
}
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// About box
|
|
int CControl::About(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
prints(conn,"<body>\n");
|
|
prints(conn,"<p align=center><b>Winamp Web Interface</b><br>\nVersion ");
|
|
prints(conn,szAppVer);
|
|
prints(conn,"</p>\n");
|
|
prints(conn,"<p align=center>\n<i>\nPhil Himsworth 2002<br>\n");
|
|
prints(conn,"<a href=mailto:contact@flippet.net>contact@flippet.net</a> · <a href=http://www.flippet.net target=\"AnotherWindow\">www.flippet.net</a>\n</i>\n</p>\n\n");
|
|
prints(conn,"</body>\n");
|
|
flush(conn);
|
|
closesocket(conn->socket);
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Main window
|
|
int CControl::Main(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<h1 align=center>\n<i>\n");
|
|
prints(conn,pagetitle);
|
|
prints(conn,"\n</i>\n\n</h1>\n");
|
|
|
|
prints(conn,"<h6 align=center>\n<a href=\"JavaScript:about()\">About Winamp Web Interface v.");
|
|
prints(conn,szAppVer);
|
|
prints(conn,"</a></h6>");
|
|
|
|
prints(conn,"<hr>\n");
|
|
|
|
prints(conn,"<h3>\n<i>\n... Winamp Status ...\n</i></h3>\n");
|
|
prints(conn,"<p>\n");
|
|
|
|
FullSongInfo(conn);
|
|
prints(conn,"</p>\n");
|
|
|
|
int repeat = SendMessage(WAwnd(),WM_USER,0,WAU_GETREPEAT);
|
|
int random = SendMessage(WAwnd(),WM_USER,0,WAU_GETRANDOM);
|
|
|
|
prints(conn,"<p>Repeat is ");
|
|
if (repeat == 1)
|
|
prints(conn,"<b>on</b> ");
|
|
if (repeat == 0)
|
|
prints(conn,"<b>off</b> ");
|
|
|
|
prints(conn,"[ ");
|
|
Link(conn,"/playmode?repeat=on","on",T_NONE);
|
|
prints(conn," | ");
|
|
Link(conn,"/playmode?repeat=off","off",T_NONE);
|
|
prints(conn," | ");
|
|
Link(conn,"/playmode?repeat=toggle","toggle",T_NONE);
|
|
prints(conn," ]");
|
|
|
|
prints(conn,"<br>Random is ");
|
|
if (random == 1)
|
|
prints(conn,"<b>on</b> ");
|
|
if (random == 0)
|
|
prints(conn,"<b>off</b> ");
|
|
|
|
prints(conn,"[ ");
|
|
Link(conn,"/playmode?random=on","on",T_NONE);
|
|
prints(conn," | ");
|
|
Link(conn,"/playmode?random=off","off",T_NONE);
|
|
prints(conn," | ");
|
|
Link(conn,"/playmode?random=toggle","toggle",T_NONE);
|
|
prints(conn," ]");
|
|
|
|
prints(conn,"</p>\n");
|
|
|
|
if (frames == 1)
|
|
LinkBar(conn);
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// PDA mode - small
|
|
int CControl::pda(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
CloseHeader(conn);
|
|
prints(conn,"<body bgcolor=\"#000000\">\n");
|
|
prints(conn,"<p align=\"center\">\n");
|
|
|
|
ImgLink(conn,"/prev?refresh=pda",IDR_IMG_PREV,"Previous Track",0,0,T_NONE);
|
|
|
|
Img(conn,IDR_IMG_BLACK,"",2,30);
|
|
ImgLink(conn,"/play?refresh=pda",IDR_IMG_PLAY,"Play",0,0,T_NONE);
|
|
|
|
Img(conn,IDR_IMG_BLACK,"",2,30);
|
|
ImgLink(conn,"/pause?refresh=pda",IDR_IMG_PAUSE,"Pause",0,0,T_NONE);
|
|
|
|
Img(conn,IDR_IMG_BLACK,"",2,30);
|
|
ImgLink(conn,"/stop?refresh=pda",IDR_IMG_STOP,"Stop",0,0,T_NONE);
|
|
|
|
Img(conn,IDR_IMG_BLACK,"",2,30);
|
|
ImgLink(conn,"/next?refresh=pda",IDR_IMG_NEXT,"Next Track",0,0,T_NONE);
|
|
|
|
prints(conn,"</p>\n<p align=\"center\">\n");
|
|
// Volume control links
|
|
ImgLink(conn,"/vol?volume=0&refresh=pda",IDR_VOL_00,"0/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=1&refresh=pda",IDR_VOL_01,"1/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=2&refresh=pda",IDR_VOL_02,"2/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=3&refresh=pda",IDR_VOL_03,"3/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=4&refresh=pda",IDR_VOL_04,"4/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=5&refresh=pda",IDR_VOL_05,"5/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=6&refresh=pda",IDR_VOL_06,"6/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=7&refresh=pda",IDR_VOL_07,"7/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=8&refresh=pda",IDR_VOL_08,"8/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=9&refresh=pda",IDR_VOL_09,"9/10",0,0,T_NONE);
|
|
ImgLink(conn,"/vol?volume=10&refresh=pda",IDR_VOL_10,"10/10",0,0,T_NONE);
|
|
|
|
prints(conn,"\n</p>\n<p align=\"center\">\n");
|
|
|
|
int repeat = SendMessage(WAwnd(),WM_USER,0,WAU_GETREPEAT);
|
|
int random = SendMessage(WAwnd(),WM_USER,0,WAU_GETRANDOM);
|
|
|
|
if (repeat)
|
|
ImgLink(conn,"/playmode?repeat=toggle&refresh=pda",IDR_IMG_RPT_ON,"Toggle Repeat",0,0,T_NONE);
|
|
else
|
|
ImgLink(conn,"/playmode?repeat=toggle&refresh=pda",IDR_IMG_RPT_OFF,"Toggle Repeat",0,0,T_NONE);
|
|
|
|
if (random)
|
|
ImgLink(conn,"/playmode?random=toggle&refresh=pda",IDR_IMG_RND_ON,"Toggle Random",0,0,T_NONE);
|
|
else
|
|
ImgLink(conn,"/playmode?random=toggle&refresh=pda",IDR_IMG_RND_OFF,"Toggle Random",0,0,T_NONE);
|
|
|
|
prints(conn,"</p>\n");
|
|
|
|
return ST_CLOSEBODY;
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Delete playlist entry. Uses DeletePlaylistEntry2()
|
|
int CControl::Delete(connection * conn) // using Playlist Window message
|
|
{
|
|
char strtrack[20];
|
|
GetArgValue(conn,"track",strtrack,20);
|
|
int track = atoi2(strtrack);
|
|
return DeletePlaylistEntry2(conn,track-1);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Returns wawi.css
|
|
int CControl::UserStyle(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/plain",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
char style_file[MAX_PATH], *p;
|
|
GetModuleFileName(plugin.hDllInstance,style_file,sizeof(style_file));
|
|
p=style_file+lstrlen(style_file);
|
|
while (p >= style_file && *p != '\\') p--;
|
|
if (++p >= style_file) *p = 0;
|
|
lstrcat(style_file,"wawi.css");
|
|
|
|
HANDLE hFile = CreateFile( style_file,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
prints(conn,"BODY\n{\nFONT-FAMILY: arial,sans-serif\n}\nA:link\n{\nCOLOR: blue;\nTEXT-DECORATION: none\n}\nA:visited\n{\nCOLOR: blue;\nTEXT-DECORATION: none\n}\nA:active\n{\nCOLOR: #ff9050;\nTEXT-DECORATION: none\n}\nA:hover\n{\nCOLOR: #e4a029;\nTEXT-DECORATION: none\n}\n\n");
|
|
return ST_CLOSE;
|
|
}
|
|
|
|
DWORD dwSize = GetFileSize(hFile, NULL);
|
|
|
|
flush(conn);
|
|
|
|
TransmitFile(conn->socket, hFile, dwSize, 0, NULL, NULL, NULL);
|
|
CloseHandle(hFile);
|
|
prints(conn,"\n\n");
|
|
return ST_CLOSE;
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Sorts playlist
|
|
int CControl::Sort(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
wsprintf(refreshto,"/list");
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
prints(conn,"<p>Sorting...");
|
|
flush(conn);
|
|
HWND playlistwnd = FindWindow("Winamp PE","Winamp Playlist Editor");
|
|
if (playlistwnd == NULL)
|
|
prints(conn,"<b>Error</b>: Couldn't find Winamp Playlist window...</p>");
|
|
else
|
|
{
|
|
SendMessage(playlistwnd,WM_COMMAND,PLC_SORTTITLE,0);
|
|
prints(conn," OK!</p>\n");
|
|
}
|
|
|
|
return ST_CLOSEBODY;
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Saves playlist
|
|
int CControl::SavePlaylist(connection * conn)
|
|
{
|
|
OpenHTTPHeader(conn,"text/html",0,NULL);
|
|
if (conn->http.reqID == RID_HEAD)
|
|
return ST_CLOSE;
|
|
|
|
OpenHtmlHeader(conn);
|
|
Style(conn);
|
|
|
|
char location[MAX_PATH];
|
|
char nicelocation[MAX_PATH];
|
|
char fulllocation[MAX_PATH];
|
|
|
|
// see if a location is specified; ask if not
|
|
if (!GetArgValue(conn,"location",location,MAX_PATH))
|
|
{
|
|
// no location; pop up form
|
|
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<h3><i>... Save Playlist ... </i></h3>\n");
|
|
prints(conn,"<form action=\"/save\" method=\"get\">\n");
|
|
prints(conn,"<p> Playlist Name: <input type=\"text\" name=\"location\" size=\"40\">\n");
|
|
prints(conn,"<input type=\"submit\" value=\"Save\"></p>\n");
|
|
prints(conn,"</form>\n");
|
|
prints(conn,"<p> </p>\n");
|
|
Link(conn,"/list","Return to Playlist",T_NONE);
|
|
}
|
|
else
|
|
{
|
|
char refreshto[MAX_PATH];
|
|
if (!GetArgValue(conn,"refresh",refreshto,10))
|
|
wsprintf(refreshto,"/list");
|
|
|
|
// location given; save it to mp3root \ playlist directory \ location
|
|
int dirlen = strlen(playlistdir);
|
|
if (dirlen == 0)
|
|
wsprintf(nicelocation,"%s.m3u",location);
|
|
else
|
|
wsprintf(nicelocation,"%s\\%s.m3u",playlistdir,location);
|
|
|
|
wsprintf(fulllocation,"%s\\%s",mp3root,nicelocation);
|
|
|
|
//MessageBox(NULL,fulllocation,nicelocation,MB_OK | MB_TOPMOST);
|
|
|
|
SendMessage(WAwnd(),WM_USER,0,WAU_PLSAVE);
|
|
|
|
// Find winamp.m3u; it's in the same dir as exe of current process.
|
|
DWORD wapid = GetWindowThreadProcessId(WAwnd(),NULL);
|
|
HMODULE hMod = (HMODULE)OpenProcess(PROCESS_ALL_ACCESS,false,wapid);
|
|
|
|
char playlistfile[MAX_PATH], *p;
|
|
GetModuleFileName(hMod,playlistfile,sizeof(playlistfile));
|
|
CloseHandle(hMod);
|
|
|
|
// Make \path\winamp.exe into \path\winamp.m3u
|
|
p=playlistfile+lstrlen(playlistfile);
|
|
while (p >= playlistfile && *p != '\\') p--;
|
|
if (++p >= playlistfile) *p = 0;
|
|
lstrcat(playlistfile,"winamp.m3u");
|
|
|
|
if (CopyFile(playlistfile,fulllocation,true) == 0)
|
|
{
|
|
// function failed; try again
|
|
if (CopyFile(playlistfile,fulllocation,false) == 0)
|
|
{
|
|
// failed totally; tell them
|
|
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<p><b>Error!</b></p><p>Couldn't save the playlist to <b>");
|
|
prints(conn,nicelocation);
|
|
prints(conn,"</b></p>\n<p>Does the directory exist?</p>");
|
|
Link(conn,"list","Back to Playlist",T_NONE);
|
|
}
|
|
else
|
|
{
|
|
// file overwritten
|
|
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<p>Playlist saved to <b>");
|
|
prints(conn,nicelocation);
|
|
prints(conn,"<b>\n<p>Previous playlist overwritten.</p>\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// file copied ok
|
|
|
|
RefreshHeader(conn,refreshto);
|
|
CloseHeader(conn);
|
|
OpenPageBody(conn);
|
|
|
|
prints(conn,"<p>Playlist saved to <b>");
|
|
prints(conn,nicelocation);
|
|
prints(conn,"</b></p>\n");
|
|
}
|
|
|
|
}
|
|
|
|
if (frames == 1)
|
|
LinkBar(conn);
|
|
|
|
return ST_CLOSEBODY;
|
|
|
|
} |