/* --- 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>&nbsp;</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: &nbsp; <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>&nbsp;|&nbsp;");
	prints(conn,"<a href=\"/sort\">Sort Playlist</a>&nbsp;|&nbsp;<a href=\"/clear\">Clear Playlist</a>");
	prints(conn,"&nbsp;|&nbsp;<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>&nbsp;</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>&nbsp;&middot;&nbsp;<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>&nbsp;</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;

}