1 // ------------------------------------------------
6 // Simple tray icon interface to PeerCast, mostly win32 related stuff.
8 // (c) 2002 peercast.org
9 // ------------------------------------------------
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 // ------------------------------------------------
29 #include "win32/wsys.h"
38 #include "chkMemoryLeak.h"
39 #define DEBUG_NEW new(__FILE__, __LINE__)
43 #define MAX_LOADSTRING 100
46 #define RELAY_CMD 8000
50 #define MAX_CHANNELS 999
55 void loadIcons(HINSTANCE hInstance, HWND hWnd);
58 UINT g_iTaskbarCreated = ~0; // for PCRaw (tray icon)
62 static int currNotify=0;
66 static HMENU trayMenu = NULL,ltrayMenu = NULL; // for PCRaw (tray icon)
68 bool allowMulti=false;
70 bool allowTrayMenu=true;
71 static bool winDistinctionNT=false;
72 int seenNewVersionTime=0;
75 bool chanInfoIsRelayed;
78 ULONG_PTR gdiplusToken;
81 ThreadInfo trafficDlgThread;
82 HWND trafficDlg = NULL;
84 //
\83v
\83\8d\83g
\83^
\83C
\83v
\90é
\8c¾
86 LRESULT CALLBACK TrafficDlgProc(HWND, UINT, WPARAM, LPARAM);
88 // ---------------------------------
89 Sys * APICALL MyPeercastInst::createSys()
91 return new WSys(mainWnd);
93 // ---------------------------------
94 const char * APICALL MyPeercastApp ::getIniFilename()
96 return iniFileName.cstr();
99 // ---------------------------------
100 const char *APICALL MyPeercastApp ::getClientTypeOS()
105 // ---------------------------------
106 const char * APICALL MyPeercastApp::getPath()
108 return exePath.cstr();
111 // --------------------------------- JP-EX
112 void APICALL MyPeercastApp ::openLogFile()
114 logFile.openWriteReplace("log.txt");
116 // --------------------------------- JP-EX
117 void APICALL MyPeercastApp ::getDirectory()
119 char path_buffer[256],drive[32],dir[128];
120 GetModuleFileName(NULL,path_buffer,255);
121 _splitpath(path_buffer,drive,dir,NULL,NULL);
122 sprintf(servMgr->modulePath,"%s%s",drive,dir);
124 // --------------------------------- JP-EX
125 bool APICALL MyPeercastApp ::clearTemp()
127 if (servMgr->clearPLS)
134 class NOTIFYICONDATA2
137 DWORD cbSize; // DWORD
141 UINT uCallbackMessage; // UINT
142 HICON hIcon; // HICON
143 char szTip[128]; // char[128]
144 DWORD dwState; // DWORD
145 DWORD dwStateMask; // DWORD
146 char szInfo[256]; // char[256]
147 UINT uTimeoutOrVersion; // UINT
148 char szInfoTitle[64]; // char[64]
149 DWORD dwInfoFlags; // DWORD
150 //GUID guidItem; > IE 6
153 NOTIFYICONDATA2 trayIcon;
157 HINSTANCE hInst; // current instance
158 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
159 TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
160 TCHAR szWindowClass2[MAX_LOADSTRING]; // The title bar text
162 // Foward declarations of functions included in this code module:
163 ATOM MyRegisterClass(HINSTANCE hInstance);
164 ATOM MyRegisterClass2(HINSTANCE hInstance);
165 ATOM MyRegisterClass3(HINSTANCE hInstance);
166 BOOL InitInstance(HINSTANCE, int);
167 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
168 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
169 LRESULT CALLBACK ChanInfoProc(HWND, UINT, WPARAM, LPARAM);
171 void setTrayIcon(int type, const char *,const char *,bool);
172 void flipNotifyPopup(int id, ServMgr::NOTIFY_TYPE nt);
177 // --------------------------------------------------
178 void LOG2(const char *fmt,...)
183 vsprintf(str,fmt,ap);
184 OutputDebugString(str);
190 // ---------------------------------------
191 int APIENTRY WinMain(HINSTANCE hInstance,
192 HINSTANCE hPrevInstance,
198 ::_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
207 version_ex = 1; // PP
\94Å
\8ag
\92£
\8b@
\94\
\82ð
\96³
\8cø
\82É
\81©
\91å
\89R
\81B
\83o
\81[
\83W
\83\87\83\93\95\
\8bL
\82ðEX
\82É
209 iniFileName.set(".\\peercast.ini");
211 WIN32_FIND_DATA fd; //JP-EX
212 HANDLE hFind; //JP-EX
214 OSVERSIONINFO osInfo; //JP-EX
215 osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); //JP-EX
216 GetVersionEx(&osInfo);
217 if (osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
218 winDistinctionNT = true;
220 winDistinctionNT = false;
222 // off by default now
225 if (strlen(lpCmdLine) > 0)
228 if ((p = strstr(lpCmdLine,"-inifile"))!=NULL)
229 iniFileName.setFromString(p+8);
231 if (strstr(lpCmdLine,"-zen"))
234 if (strstr(lpCmdLine,"-multi"))
237 if (strstr(lpCmdLine,"-kill"))
240 if ((p = strstr(lpCmdLine,"-url"))!=NULL)
255 strncpy(tmpURL,p,sizeof(tmpURL)-1);
261 exePath = iniFileName;
262 char *s = exePath.cstr();
274 if (strnicmp(tmpURL,"peercast://",11)==0)
276 if (strnicmp(tmpURL+11,"pls/",4)==0)
277 chanURL = tmpURL+11+4;
287 // Initialize global strings
288 //LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
289 //LoadString(hInstance, IDC_APP_TITLE, szWindowClass, MAX_LOADSTRING);
291 strcpy(szTitle,"PeerCast");
292 strcpy(szWindowClass,"PeerCast");
293 strcpy(szWindowClass2,"Main");
297 HANDLE mutex = CreateMutex(NULL,TRUE,szWindowClass);
299 if (GetLastError() == ERROR_ALREADY_EXISTS)
301 HWND oldWin = FindWindow(szWindowClass,NULL);
304 //SendMessage(oldWin,WM_SHOWGUI,0,0);
307 SendMessage(oldWin,WM_DESTROY,0,0);
314 copy.dwData = WM_PLAYCHANNEL;
315 copy.cbData = strlen(chanURL)+1; // plus null term
316 copy.lpData = chanURL;
317 SendMessage(oldWin,WM_COPYDATA,NULL,(LPARAM)©);
320 SendMessage(oldWin,WM_SHOWGUI,0,0);
330 MyRegisterClass(hInstance);
331 MyRegisterClass2(hInstance);
333 // Perform application initialization:
334 if (!InitInstance (hInstance, nCmdShow))
337 peercastInst = new MyPeercastInst();
338 peercastApp = new MyPeercastApp();
340 peercastInst->init();
342 LOG_DEBUG("Set OS Type: %s",winDistinctionNT?"WinNT":"Win9x");
344 if (peercastApp->clearTemp()) //JP-EX
346 DeleteFile("play.pls");
347 hFind = FindFirstFile("*.asx",&fd);
348 if (hFind != INVALID_HANDLE_VALUE)
352 DeleteFile((char *)&fd.cFileName);
354 while (FindNextFile(hFind,&fd));
363 servMgr->procConnectArgs(chanURL,info);
364 chanMgr->findAndPlayChannel(info,false);
367 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SIMPLE);
369 // setup menu notifes
370 int mask = peercastInst->getNotifyMask();
371 if (mask & ServMgr::NT_PEERCAST)
372 CheckMenuItem(trayMenu,ID_POPUP_SHOWMESSAGES_PEERCAST,MF_CHECKED|MF_BYCOMMAND);
373 if (mask & ServMgr::NT_BROADCASTERS)
374 CheckMenuItem(trayMenu,ID_POPUP_SHOWMESSAGES_BROADCASTERS,MF_CHECKED|MF_BYCOMMAND);
375 if (mask & ServMgr::NT_TRACKINFO)
376 CheckMenuItem(trayMenu,ID_POPUP_SHOWMESSAGES_TRACKINFO,MF_CHECKED|MF_BYCOMMAND);
378 if (servMgr->startWithGui)
383 // Main message loop:
384 while (GetMessage(&msg, NULL, 0, 0))
386 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
388 TranslateMessage(&msg);
389 DispatchMessage(&msg);
393 Shell_NotifyIcon(NIM_DELETE, (NOTIFYICONDATA*)&trayIcon);
395 peercastInst->saveSettings();
396 peercastInst->quit();
398 Gdiplus::GdiplusShutdown(gdiplusToken);
406 // FUNCTION: MyRegisterClass()
408 // PURPOSE: Registers the window class.
412 // This function and its usage is only necessary if you want this code
413 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
414 // function that was added to Windows 95. It is important to call this function
415 // so that the application will get 'well formed' small icons associated
418 ATOM MyRegisterClass(HINSTANCE hInstance)
422 wcex.cbSize = sizeof(WNDCLASSEX);
424 wcex.style = CS_HREDRAW | CS_VREDRAW;
425 wcex.lpfnWndProc = (WNDPROC)WndProc;
428 wcex.hInstance = hInstance;
429 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SIMPLE);
430 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
431 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
432 // wcex.lpszMenuName = (LPCSTR)IDC_SIMPLE;
433 wcex.lpszMenuName = NULL;
434 wcex.lpszClassName = szWindowClass;
435 wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
437 return RegisterClassEx(&wcex);
440 ATOM MyRegisterClass2(HINSTANCE hInstance)
444 wcex.cbSize = sizeof(WNDCLASSEX);
446 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
447 wcex.lpfnWndProc = (WNDPROC)GUIProc;
450 wcex.hInstance = hInstance;
451 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SIMPLE);
452 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
453 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
454 // wcex.lpszMenuName = (LPCSTR)IDC_SIMPLE;
455 wcex.lpszMenuName = NULL;
456 wcex.lpszClassName = szWindowClass2;
457 wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
459 return RegisterClassEx(&wcex);
462 //-----------------------------
463 void loadIcons(HINSTANCE hInstance, HWND hWnd)
465 icon1 = LoadIcon(hInstance, (LPCTSTR)IDI_SMALL);
466 icon2 = LoadIcon(hInstance, (LPCTSTR)IDI_SMALL2);
468 trayIcon.cbSize = sizeof(trayIcon);
469 trayIcon.hWnd = hWnd;
471 trayIcon.uFlags = NIF_MESSAGE + NIF_ICON + NIF_TIP;
472 trayIcon.uCallbackMessage = WM_TRAYICON;
473 trayIcon.hIcon = icon1;
474 strcpy(trayIcon.szTip, "PeerCast");
476 Shell_NotifyIcon(NIM_ADD, (NOTIFYICONDATA*)&trayIcon);
478 //ShowWindow(hWnd, nCmdShow);
481 if(!trayMenu) // for PCRaw (tray icon)
482 trayMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_TRAYMENU));
483 if(!ltrayMenu) // for PCRaw (tray icon)
484 ltrayMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_LTRAYMENU));
489 //-----------------------------
491 // FUNCTION: InitInstance(HANDLE, int)
493 // PURPOSE: Saves instance handle and creates main window
497 // In this function, we save the instance handle in a global variable and
498 // create and display the main program window.
500 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
504 hInst = hInstance; // Store instance handle in our global variable
506 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
507 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
516 g_iTaskbarCreated = RegisterWindowMessage("TaskbarCreated"); // for PCRaw (tray icon)
518 loadIcons(hInstance,hWnd);
520 using namespace Gdiplus;
521 GdiplusStartupInput gdiplusStartupInput;
522 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
526 //-----------------------------
527 //static String trackTitle;
528 //static String channelComment;
530 //-----------------------------
531 void channelPopup(const char *title, const char *msg, bool isPopup = true)
535 if (*title == '\0') return;
541 trayIcon.uFlags = NIF_ICON|NIF_TIP;
542 strncpy(trayIcon.szTip, both.cstr(),sizeof(trayIcon.szTip)-1);
543 trayIcon.szTip[sizeof(trayIcon.szTip)-1]=0;
545 if (isPopup) trayIcon.uFlags |= 16;
546 trayIcon.uTimeoutOrVersion = 10000;
547 strncpy(trayIcon.szInfo,msg,sizeof(trayIcon.szInfo)-1);
548 strncpy(trayIcon.szInfoTitle,title,sizeof(trayIcon.szInfoTitle)-1);
550 Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA*)&trayIcon);
552 //-----------------------------
553 void clearChannelPopup()
555 trayIcon.uFlags = NIF_ICON|16;
556 trayIcon.uTimeoutOrVersion = 10000;
557 strncpy(trayIcon.szInfo,"",sizeof(trayIcon.szInfo)-1);
558 strncpy(trayIcon.szInfoTitle,"",sizeof(trayIcon.szInfoTitle)-1);
559 Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA*)&trayIcon);
562 //-----------------------------
571 static PopupEntry *PEList = NULL;
574 static void putPopupEntry(PopupEntry *pe)
582 static PopupEntry *getPopupEntry(GnuID id)
585 PopupEntry *pe = PEList;
586 PopupEntry *prev = NULL;
588 if (id.isSame(pe->id)) {
589 if (prev) prev->next = pe->next;
590 else PEList = pe->next;
602 static PopupEntry *getTopPopupEntry()
604 PopupEntry *p = NULL;
608 PEList = PEList->next;
614 //-----------------------------
615 void APICALL MyPeercastApp::channelStart(ChanInfo *info)
618 // lastPlayID = info->id;
620 // if(!isIndexTxt(info)) // for PCRaw (popup)
621 // clearChannelPopup();
623 PopupEntry *pe = getPopupEntry(info->id);
628 if (!isIndexTxt(info))
633 //-----------------------------
634 void APICALL MyPeercastApp::channelStop(ChanInfo *info)
636 // if (info->id.isSame(lastPlayID))
638 // lastPlayID.clear();
640 // if(!isIndexTxt(info)) // for PCRaw (popup)
641 // clearChannelPopup();
644 PopupEntry *pe = getPopupEntry(info->id);
647 pe = getTopPopupEntry();
651 if (ServMgr::NT_TRACKINFO & peercastInst->getNotifyMask())
653 String name,track; //JP-Patch
654 name = pe->name; //JP-Patch
655 track = pe->track; //JP-Patch
656 name.convertTo(String::T_SJIS); //JP-Patch
657 track.convertTo(String::T_SJIS); //JP-Patch
659 // channelPopup(info->name.cstr(),trackTitle.cstr());
660 channelPopup(name.cstr(),track.cstr(), false); //JP-Patch
665 //-----------------------------
666 void APICALL MyPeercastApp::channelUpdate(ChanInfo *info)
670 PopupEntry *pe = getPopupEntry(info->id);
674 tmp.append(info->track.artist);
676 tmp.append(info->track.title);
679 if (!tmp.isSame(pe->track))
681 pe->name = info->name;
683 if (ServMgr::NT_TRACKINFO & peercastInst->getNotifyMask())
686 String name,track; //JP-Patch
687 name = info->name; //JP-Patch
688 track = tmp; //JP-Patch
689 name.convertTo(String::T_SJIS); //JP-Patch
690 track.convertTo(String::T_SJIS); //JP-Patch
691 if(!isIndexTxt(info)) // for PCRaw (popup)
694 // channelPopup(info->name.cstr(),trackTitle.cstr());
695 channelPopup(name.cstr(),track.cstr()); //JP-Patch
698 } else if (!info->comment.isSame(pe->comment))
700 pe->name = info->name;
701 pe->comment = info->comment;
702 if (ServMgr::NT_BROADCASTERS & peercastInst->getNotifyMask())
704 //channelComment = info->comment;
705 String name,comment; //JP-Patch
706 name = info->name; //JP-Patch
707 comment = info->comment; //JP-Patch
708 name.convertTo(String::T_SJIS); //JP-Patch
709 comment.convertTo(String::T_SJIS); //JP-Patch
710 if(!isIndexTxt(info)) // for PCRaw (popup)
713 // channelPopup(info->name.cstr(),channelComment.cstr());
714 channelPopup(name.cstr(),comment.cstr());
719 if (!isIndexTxt(info))
725 //-----------------------------
726 void APICALL MyPeercastApp::notifyMessage(ServMgr::NOTIFY_TYPE type, const char *msg)
728 static bool shownUpgradeAlert=false;
734 if (!shownUpgradeAlert)
736 trayIcon.uFlags = NIF_ICON;
738 if (type == ServMgr::NT_UPGRADE)
740 shownUpgradeAlert = true;
741 trayIcon.hIcon = icon2;
744 trayIcon.hIcon = icon1;
748 if (type == ServMgr::NT_UPGRADE)
752 const char *title="";
756 case ServMgr::NT_UPGRADE:
757 title = "Upgrade alert";
759 case ServMgr::NT_PEERCAST:
760 title = "Message from PeerCast:";
765 if (type & peercastInst->getNotifyMask())
767 trayIcon.uFlags |= 16;
768 trayIcon.uTimeoutOrVersion = 10000;
769 strncpy(trayIcon.szInfo,msg,sizeof(trayIcon.szInfo)-1);
770 strncpy(trayIcon.szInfoTitle,title,sizeof(trayIcon.szInfoTitle)-1);
771 Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA*)&trayIcon);
774 //-----------------------------
778 void createGUI(HWND hWnd)
781 guiWnd = ::CreateWindow(szWindowClass2,
783 WS_OVERLAPPEDWINDOW & ~(WS_MAXIMIZEBOX) /*| WS_VSCROLL | WS_HSCROLL*/,
793 ShowWindow(guiWnd,SW_SHOWNORMAL);
795 //
\8e©
\93®
\82Å
\8dÅ
\91O
\96Ê
796 if (servMgr->topmostGui)
798 ::SetWindowPos(guiWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
804 // addRelayedChannelsMenu(HMENU m)
807 void addRelayedChannelsMenu(HMENU cm)
809 int cnt = GetMenuItemCount(cm);
810 for(int i=0; i<cnt-3; i++)
811 DeleteMenu(cm,0,MF_BYPOSITION);
813 Channel *c = chanMgr->channel;
818 char str[128],name[64];
819 strncpy(name,c->info.name,32);
821 if (strlen(c->info.name) > 32)
825 sprintf(str,"%s (%d kb/s %s)",name,c->info.bitrate,ChanInfo::getTypeStr(c->info.contentType));
826 //InsertMenu(cm,0,MF_BYPOSITION,RELAY_CMD+i,str);
832 typedef int (*COMPARE_FUNC)(const void *,const void *);
834 static int compareHitLists(ChanHitList **c2, ChanHitList **c1)
836 return stricmp(c1[0]->info.name.cstr(),c2[0]->info.name.cstr());
839 static int compareChannels(Channel **c2, Channel **c1)
841 return stricmp(c1[0]->info.name.cstr(),c2[0]->info.name.cstr());
845 // addAllChannelsMenu(HMENU m)
848 void addAllChannelsMenu(HMENU cm)
850 int cnt = GetMenuItemCount(cm);
851 /* for(int i=0; i<cnt-2; i++)
852 DeleteMenu(cm,0,MF_BYPOSITION);*/
854 for(int i=0; i<cnt; i++)
855 DeleteMenu(cm,0,MF_BYPOSITION);
857 HMENU yMenu = CreatePopupMenu();
858 if (!servMgr->rootHost2.isEmpty()){
859 InsertMenu(yMenu,0,MF_BYPOSITION,ID_POPUP_YELLOWPAGES2,servMgr->rootHost2);
861 if (!servMgr->rootHost.isEmpty()){
862 InsertMenu(yMenu,0,MF_BYPOSITION,ID_POPUP_YELLOWPAGES1,servMgr->rootHost);
865 InsertMenu(cm,0,MF_BYPOSITION|MF_POPUP,(UINT)yMenu,"
\83C
\83G
\83\8d\81[
\83y
\81[
\83W");
866 InsertMenu(cm,0,MF_BYPOSITION|MF_SEPARATOR,NULL,NULL);
867 // add channels to menu
869 Channel *ch = chanMgr->channel;
872 char str[128],name[64];
873 String sjis; //JP-Patch
874 sjis = ch->info.name; //JP-Patch
875 sjis.convertTo(String::T_SJIS); //JP-Patch
876 strncpy(name,sjis.cstr(),32);
877 //strncpy(name,ch->info.name,32);
879 //if (strlen(ch->info.name) > 32)
880 if (strlen(sjis.cstr()) > 32) //JP-Patch
883 sprintf(str,"%s (%d kb/s %s)",name,ch->info.bitrate,ChanInfo::getTypeStr(ch->info.contentType));
885 HMENU opMenu = CreatePopupMenu();
886 InsertMenu(opMenu,0,MF_BYPOSITION,INFO_CMD+numActive,"Info");
887 if (ch->info.url.isValidURL())
888 InsertMenu(opMenu,0,MF_BYPOSITION,URL_CMD+numActive,"URL");
889 InsertMenu(opMenu,0,MF_BYPOSITION,PLAY_CMD+numActive,"Play");
891 UINT fl = MF_BYPOSITION|MF_POPUP;
893 fl |= (ch->isPlaying()?MF_CHECKED:0);
895 InsertMenu(cm,0,fl,(UINT)opMenu,str);
904 // InsertMenu(cm,0,MF_BYPOSITION,0,"<No channels>");
913 // flipNotifyPopup(id, flag)
914 void flipNotifyPopup(int id, ServMgr::NOTIFY_TYPE nt)
916 int mask = peercastInst->getNotifyMask();
920 CheckMenuItem(trayMenu,id,MF_CHECKED|MF_BYCOMMAND);
922 CheckMenuItem(trayMenu,id,MF_UNCHECKED|MF_BYCOMMAND);
924 peercastInst->setNotifyMask(mask);
925 peercastInst->saveSettings();
929 static void showHTML(const char *file)
932 sprintf(url,"%s/%s",servMgr->htmlPath,file);
934 // sys->callLocalURL(url,servMgr->serverHost.port);
935 sys->callLocalURL(url, // for PCRaw (url)
936 (servMgr->allowServer1&Servent::ALLOW_HTML)?(servMgr->serverHost.port):(servMgr->serverHost.port+1));
939 static ChanInfo getChannelInfo(int index)
941 Channel *c = chanMgr->findChannelByIndex(index);
950 // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
952 // PURPOSE: Processes messages for the main window.
954 // WM_COMMAND - process the application menu
955 // WM_PAINT - Paint the main window
956 // WM_DESTROY - post a quit message and return
959 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
965 if(message == g_iTaskbarCreated) // for PCRaw (tray icon)
966 loadIcons(hInst, hWnd);
980 SendMessage(hWnd,WM_SHOWMENU,2,0);
981 SetForegroundWindow(hWnd);
985 SendMessage(hWnd,WM_SHOWMENU,1,0);
986 SetForegroundWindow(hWnd);
988 case WM_LBUTTONDBLCLK:
996 COPYDATASTRUCT *pc = (COPYDATASTRUCT *)lParam;
997 LOG_DEBUG("URL request: %s",pc->lpData);
998 if (pc->dwData == WM_PLAYCHANNEL)
1001 servMgr->procConnectArgs((char *)pc->lpData,info);
1002 chanMgr->findAndPlayChannel(info,false);
1004 //sys->callLocalURL((const char *)pc->lpData,servMgr->serverHost.port);
1007 case WM_GETPORTNUMBER:
1010 port=servMgr->serverHost.port;
1017 if (servMgr->saveGuiPos){
1018 CheckMenuItem(trayMenu, ID_POPUP_SAVE_GUI_POS, MF_CHECKED|MF_BYCOMMAND);
1020 CheckMenuItem(trayMenu, ID_POPUP_SAVE_GUI_POS, MF_UNCHECKED|MF_BYCOMMAND);
1023 //
\8e©
\93®GUI/
\8dÅ
\91O
\96Ê
\8b@
\94\
1024 if (servMgr->topmostGui)
1026 CheckMenuItem(trayMenu, ID_POPUP_TOPMOST, MF_CHECKED|MF_BYCOMMAND);
1029 CheckMenuItem(trayMenu, ID_POPUP_TOPMOST, MF_UNCHECKED|MF_BYCOMMAND);
1032 if (servMgr->startWithGui)
1034 CheckMenuItem(trayMenu, ID_POPUP_START_WITH_GUI, MF_CHECKED|MF_BYCOMMAND);
1037 CheckMenuItem(trayMenu, ID_POPUP_START_WITH_GUI, MF_UNCHECKED|MF_BYCOMMAND);
1040 SetForegroundWindow(hWnd);
1041 bool skipMenu=false;
1043 allowTrayMenu = false;
1045 // check for notifications
1046 if (currNotify & ServMgr::NT_UPGRADE)
1048 if (servMgr->downloadURL[0])
1050 if ((sys->getTime()-seenNewVersionTime) > (60*60)) // notify every hour
1052 if (MessageBox(hWnd,"A newer version of PeerCast is available, press OK to upgrade.","PeerCast",MB_OKCANCEL|MB_APPLMODAL|MB_ICONEXCLAMATION) == IDOK)
1053 sys->getURL(servMgr->downloadURL);
1055 seenNewVersionTime=sys->getTime();
1068 SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWnd, 0);
1069 GetCursorPos(&point);
1071 if (point.x < rcWnd.left){
1072 point.x = rcWnd.left;
1073 flg |= TPM_LEFTALIGN;
1075 if (point.x > rcWnd.right){
1076 point.x = rcWnd.right;
1077 flg |= TPM_RIGHTALIGN;
1079 if (point.y < rcWnd.top){
1080 point.y = rcWnd.top;
1081 flg |= TPM_TOPALIGN;
1083 if (point.y > rcWnd.bottom){
1084 point.y = rcWnd.bottom;
1085 flg |= TPM_BOTTOMALIGN;
1088 flg = TPM_RIGHTALIGN;
1094 menu = GetSubMenu(trayMenu,0);
1095 addAllChannelsMenu(GetSubMenu(menu,0));
1096 addRelayedChannelsMenu(GetSubMenu(menu,1));
1099 menu = GetSubMenu(ltrayMenu,0);
1100 addAllChannelsMenu(menu);
1103 if (!TrackPopupMenu(menu,flg,point.x,point.y,0,hWnd,NULL))
1105 LOG_ERROR("Can`t track popup menu: %d",GetLastError());
1107 PostMessage(hWnd,WM_NULL,0,0);
1110 allowTrayMenu = true;
1120 wmId = LOWORD(wParam);
1121 wmEvent = HIWORD(wParam);
1123 if ((wmId >= INFO_CMD) && (wmId < INFO_CMD+MAX_CHANNELS))
1125 int c = wmId - INFO_CMD;
1126 chanInfo = getChannelInfo(c);
1127 chanInfoIsRelayed = false;
1128 if (winDistinctionNT)
1129 DialogBox(hInst, (LPCTSTR)IDD_CHANINFO, hWnd, (DLGPROC)ChanInfoProc);
1132 HWND WKDLG; //JP-Patch
1133 WKDLG = CreateDialog(hInst, (LPCTSTR)IDD_CHANINFO, hWnd, (DLGPROC)ChanInfoProc); //JP-Patch
1134 ShowWindow(WKDLG,SW_SHOWNORMAL); //JP-Patch
1138 if ((wmId >= URL_CMD) && (wmId < URL_CMD+MAX_CHANNELS))
1140 int c = wmId - URL_CMD;
1141 chanInfo = getChannelInfo(c);
1142 if (chanInfo.url.isValidURL())
1143 sys->getURL(chanInfo.url);
1146 if ((wmId >= PLAY_CMD) && (wmId < PLAY_CMD+MAX_CHANNELS))
1148 int c = wmId - PLAY_CMD;
1149 chanInfo = getChannelInfo(c);
1150 chanMgr->findAndPlayChannel(chanInfo,false);
1153 if ((wmId >= RELAY_CMD) && (wmId < RELAY_CMD+MAX_CHANNELS))
1155 int c = wmId - RELAY_CMD;
1156 chanInfo = getChannelInfo(c);
1157 chanMgr->findAndPlayChannel(chanInfo,true);
1161 // Parse the menu selections:
1164 case ID_POPUP_SHOWMESSAGES_PEERCAST:
1165 flipNotifyPopup(ID_POPUP_SHOWMESSAGES_PEERCAST,ServMgr::NT_PEERCAST);
1167 case ID_POPUP_SHOWMESSAGES_BROADCASTERS:
1168 flipNotifyPopup(ID_POPUP_SHOWMESSAGES_BROADCASTERS,ServMgr::NT_BROADCASTERS);
1170 case ID_POPUP_SHOWMESSAGES_TRACKINFO:
1171 flipNotifyPopup(ID_POPUP_SHOWMESSAGES_TRACKINFO,ServMgr::NT_TRACKINFO);
1174 case ID_POPUP_ABOUT:
1176 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
1178 case ID_POPUP_SHOWGUI:
1179 case IDM_SETTINGS_GUI:
1180 case ID_POPUP_ADVANCED_SHOWGUI:
1185 case ID_POPUP_YELLOWPAGES:
1186 sys->getURL("http://yp.peercast.org/");
1188 case ID_POPUP_YELLOWPAGES1:
1189 sprintf(buf, "http://%s",servMgr->rootHost.cstr());
1192 case ID_POPUP_YELLOWPAGES2:
1193 sprintf(buf, "http://%s",servMgr->rootHost2.cstr());
1197 case ID_POPUP_ADVANCED_VIEWLOG:
1198 showHTML("viewlog.html");
1200 case ID_POPUP_ADVANCED_SAVESETTINGS:
1201 servMgr->saveSettings(iniFileName.cstr());
1203 case ID_POPUP_ADVANCED_INFORMATION:
1204 showHTML("index.html");
1206 case ID_FIND_CHANNELS:
1207 case ID_POPUP_ADVANCED_ALLCHANNELS:
1208 case ID_POPUP_UPGRADE:
1209 sys->callLocalURL("admin?cmd=upgrade",servMgr->serverHost.port);
1211 case ID_POPUP_ADVANCED_RELAYEDCHANNELS:
1212 case ID_POPUP_FAVORITES_EDIT:
1213 showHTML("relays.html");
1215 case ID_POPUP_ADVANCED_BROADCAST:
1216 showHTML("broadcast.html");
1218 case ID_POPUP_SETTINGS:
1219 showHTML("settings.html");
1221 case ID_POPUP_CONNECTIONS:
1222 showHTML("connections.html");
1225 sys->getURL("http://www.peercast.org/help.php");
1228 case ID_POPUP_SAVE_GUI_POS:
1229 if (servMgr->saveGuiPos){
1230 servMgr->saveGuiPos = false;
1231 CheckMenuItem(trayMenu, ID_POPUP_SAVE_GUI_POS, MF_UNCHECKED|MF_BYCOMMAND);
1233 servMgr->saveGuiPos = true;
1234 CheckMenuItem(trayMenu, ID_POPUP_SAVE_GUI_POS, MF_CHECKED|MF_BYCOMMAND);
1236 peercastInst->saveSettings();
1239 case ID_POPUP_KEEP_DOWNSTREAMS:
1240 if (servMgr->keepDownstreams){
1241 servMgr->keepDownstreams = false;
1242 CheckMenuItem(trayMenu, ID_POPUP_KEEP_DOWNSTREAMS, MF_UNCHECKED|MF_BYCOMMAND);
1244 servMgr->keepDownstreams = true;
1245 CheckMenuItem(trayMenu, ID_POPUP_KEEP_DOWNSTREAMS, MF_CHECKED|MF_BYCOMMAND);
1247 //peercastInst->saveSettings();
1250 case ID_POPUP_TOPMOST:
1251 //
\8dÅ
\91O
\96Ê
\95\
\8e¦
1252 if (servMgr->topmostGui)
1254 servMgr->topmostGui = false;
1255 CheckMenuItem(trayMenu, ID_POPUP_TOPMOST, MF_UNCHECKED|MF_BYCOMMAND);
1258 servMgr->topmostGui = true;
1259 CheckMenuItem(trayMenu, ID_POPUP_TOPMOST, MF_CHECKED|MF_BYCOMMAND);
1261 peercastInst->saveSettings();
1264 case ID_POPUP_START_WITH_GUI:
1265 //
\8bN
\93®
\8e\9e\82ÉGUI
\95\
\8e¦
1266 if (servMgr->startWithGui)
1268 servMgr->startWithGui = false;
1269 CheckMenuItem(trayMenu, ID_POPUP_START_WITH_GUI, MF_UNCHECKED|MF_BYCOMMAND);
1272 servMgr->startWithGui = true;
1273 CheckMenuItem(trayMenu, ID_POPUP_START_WITH_GUI, MF_CHECKED|MF_BYCOMMAND);
1275 peercastInst->saveSettings();
1278 case ID_POPUP_TRAFFIC:
1279 //
\83g
\83\89\83t
\83B
\83b
\83N
\83\82\83j
\83^
\8bN
\93®
1280 if (winDistinctionNT)
1281 DialogBox(hInst, (LPCTSTR)IDD_TRAFFIC, hWnd, (DLGPROC)TrafficDlgProc);
1284 HWND WKDLG; //JP-Patch
1285 WKDLG = CreateDialog(hInst, (LPCTSTR)IDD_CHANINFO, hWnd, (DLGPROC)TrafficDlgProc); //JP-Patch
1286 ShowWindow(WKDLG,SW_SHOWNORMAL); //JP-Patch
1290 case ID_POPUP_EXIT_CONFIRM:
1292 DestroyWindow(hWnd);
1295 return DefWindowProc(hWnd, message, wParam, lParam);
1302 return DefWindowProc(hWnd, message, wParam, lParam);
1306 // Mesage handler for about box.
1307 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1312 //SendDlgItemMessage(hDlg,IDC_ABOUTVER,WM_SETTEXT,0,(LONG)PCX_AGENT);
1313 // SendDlgItemMessage(hDlg,IDC_ABOUTVER,WM_SETTEXT,0,(LONG)PCX_AGENTJP);
1316 SendDlgItemMessage(hDlg,IDC_ABOUTVER,WM_SETTEXT,0,(LONG)PCX_AGENTEX);
1319 SendDlgItemMessage(hDlg,IDC_ABOUTVER,WM_SETTEXT,0,(LONG)PCX_AGENTVP);
1325 switch (LOWORD(wParam))
1329 EndDialog(hDlg, LOWORD(wParam));
1332 sys->getURL("http://www.peercast.org");
1333 EndDialog(hDlg, LOWORD(wParam));
1344 // Mesage handler for chaninfo box
1345 LRESULT CALLBACK ChanInfoProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1352 //strcpy(str,chanInfo.track.artist.cstr());
1353 strcpy(str,chanInfo.track.artist); //JP-Patch
1355 //strcat(str,chanInfo.track.title.cstr());
1356 strcat(str,chanInfo.track.title);
1357 String name,track,comment,desc,genre; //JP-Patch
1358 name = chanInfo.name; //JP-Patch
1359 track = str; //JP-Patch
1360 comment = chanInfo.comment; //JP-Patch
1361 desc = chanInfo.desc; //JP-Patc
1362 genre = chanInfo.genre; //JP-Patch
1363 name.convertTo(String::T_SJIS); //JP-Patc
1364 track.convertTo(String::T_SJIS); //JP-Patch
1365 comment.convertTo(String::T_SJIS); //JP-Patch
1366 desc.convertTo(String::T_SJIS); //JP-Patch
1367 genre.convertTo(String::T_SJIS); //JP-Patch
1369 //SendDlgItemMessage(hDlg,IDC_EDIT_NAME,WM_SETTEXT,0,(LONG)chanInfo.name.cstr());
1370 SendDlgItemMessage(hDlg,IDC_EDIT_NAME,WM_SETTEXT,0,(LONG)name.cstr()); //JP-Patch
1371 //SendDlgItemMessage(hDlg,IDC_EDIT_PLAYING,WM_SETTEXT,0,(LONG)str);
1372 SendDlgItemMessage(hDlg,IDC_EDIT_PLAYING,WM_SETTEXT,0,(LONG)track.cstr()); //JP-Patch
1373 //SendDlgItemMessage(hDlg,IDC_EDIT_MESSAGE,WM_SETTEXT,0,(LONG)chanInfo.comment.cstr());
1374 SendDlgItemMessage(hDlg,IDC_EDIT_MESSAGE,WM_SETTEXT,0,(LONG)comment.cstr()); //JP-Patch
1375 //SendDlgItemMessage(hDlg,IDC_EDIT_DESC,WM_SETTEXT,0,(LONG)chanInfo.desc.cstr());
1376 SendDlgItemMessage(hDlg,IDC_EDIT_DESC,WM_SETTEXT,0,(LONG)desc.cstr()); //JP-Patch
1377 //SendDlgItemMessage(hDlg,IDC_EDIT_GENRE,WM_SETTEXT,0,(LONG)chanInfo.genre.cstr());
1378 SendDlgItemMessage(hDlg,IDC_EDIT_GENRE,WM_SETTEXT,0,(LONG)genre.cstr()); //JP-Patch
1380 sprintf(str,"%d kb/s %s",chanInfo.bitrate,ChanInfo::getTypeStr(chanInfo.contentType));
1381 SendDlgItemMessage(hDlg,IDC_FORMAT,WM_SETTEXT,0,(LONG)str);
1384 if (!chanInfo.url.isValidURL())
1385 EnableWindow(GetDlgItem(hDlg,IDC_CONTACT),false);
1387 Channel *ch = chanMgr->findChannelByID(chanInfo.id);
1390 SendDlgItemMessage(hDlg,IDC_EDIT_STATUS,WM_SETTEXT,0,(LONG)ch->getStatusStr());
1391 SendDlgItemMessage(hDlg, IDC_KEEP,BM_SETCHECK, ch->stayConnected, 0);
1393 //
\8c»
\8dÝ
\82Ì
\8cÅ
\97L
\83\8a\83\8c\81[
\8fã
\8cÀ
\90Ý
\92è
\82ð
\95\
\8e¦(0
\82Í
\96³
\8cø)
1394 ::SetDlgItemInt(hDlg, IDC_EDIT_MAXRELAYS, ch->maxRelays, false);
1397 // index.txt
\82È
\82Ì
\82Å
\96³
\8cø
\82É
1398 ::EnableWindow(::GetDlgItem(hDlg, IDC_EDIT_MAXRELAYS), false);
1399 ::EnableWindow(::GetDlgItem(hDlg, IDC_APPLY_MAXRELAYS), false);
1403 SendDlgItemMessage(hDlg,IDC_EDIT_STATUS,WM_SETTEXT,0,(LONG)"OK");
1404 EnableWindow(GetDlgItem(hDlg,IDC_KEEP),false);
1411 HWND hDsk = GetDesktopWindow();
1412 GetWindowRect(hDsk,&drect);
1413 GetWindowRect(hDlg,&rect);
1414 GetCursorPos(&point);
1417 size.x = rect.right-rect.left;
1418 size.y = rect.bottom-rect.top;
1420 if (point.x-drect.left < size.x)
1423 pos.x = point.x-size.x;
1425 if (point.y-drect.top < size.y)
1428 pos.y = point.y-size.y;
1430 SetWindowPos(hDlg,HWND_TOPMOST,pos.x,pos.y,size.x,size.y,0);
1437 char str[1024],idstr[64];
1438 chanInfo.id.toStr(idstr);
1440 switch (LOWORD(wParam))
1444 sys->getURL(chanInfo.url);
1449 sprintf(str,"admin?page=chaninfo&id=%s&relay=%d",idstr,chanInfoIsRelayed);
1450 sys->callLocalURL(str,servMgr->serverHost.port);
1455 Channel *ch = chanMgr->findChannelByID(chanInfo.id);
1457 ch->stayConnected = SendDlgItemMessage(hDlg, IDC_KEEP,BM_GETCHECK, 0, 0) == BST_CHECKED;;
1464 chanMgr->findAndPlayChannel(chanInfo,false);
1468 case IDC_APPLY_MAXRELAYS:
1470 //
\83`
\83\83\83\93\83l
\83\8b\8cÅ
\97L
\82Ì
\8dÅ
\91å
\83\8a\83\8c\81[
\90\94\82ð
\90Ý
\92è
1474 //
\93ü
\97Í
\92l
\8eæ
\93¾
1475 mr = ::GetDlgItemInt(hDlg, IDC_EDIT_MAXRELAYS, &bSucc, false);
1479 Channel *ch = chanMgr->findChannelByID(chanInfo.id);
1480 if (ch && !isIndexTxt(ch))
1486 MessageBox(hDlg, "
\93ü
\97Í
\92l
\82ª
\95s
\90³
\82Å
\82·
\81B", "Error", MB_OK|MB_ICONERROR|MB_APPLMODAL);
1487 Channel *ch = chanMgr->findChannelByID(chanInfo.id);
1489 ::SetDlgItemInt(hDlg, IDC_EDIT_MAXRELAYS, ch->maxRelays, false);
1497 if (winDistinctionNT)
1500 DestroyWindow(hDlg); //JP-Patch
1504 if (LOWORD(wParam) == WA_INACTIVE)
1505 if (winDistinctionNT)
1508 DestroyWindow(hDlg); //JP-Patch
1519 // control thread (Traffic dialog)
1520 THREAD_PROC trafficDlgUpdate(ThreadInfo *thread)
1522 thread->finish = false;
1524 while (trafficDlg && thread->active)
1526 SendMessage(trafficDlg, WM_UPDATETRAFFIC, 0, 0);
1530 thread->finish = true;
1535 // Dialog procedure (Traffic dialog)
1536 LRESULT CALLBACK TrafficDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1541 //
\8aù
\82É
\8aJ
\82¢
\82Ä
\82é
1542 if (trafficDlg || trafficDlgThread.active)
1544 if (winDistinctionNT)
1547 DestroyWindow(hDlg);
1552 trafficDlgThread.func = trafficDlgUpdate;
1553 if (!sys->startThread(&trafficDlgThread)){
1554 MessageBox(NULL,"Unable to start GUI","PeerCast",MB_OK|MB_ICONERROR);
1555 PostMessage(hDlg,WM_DESTROY,0,0);
1560 case WM_UPDATETRAFFIC:
1562 enum unitSymbol { B, KB, MB, GB };
1563 const unsigned long int unit[] = { 1, 1024, 1024*1024, 1024*1024*1024 };
1564 char suffix[][3] = { "B", "KB", "MB", "GB" };
1565 const int bufsize = 60;
1566 char szUp[bufsize], szDown[bufsize];
1567 unsigned long long int totalDown = stats.getCurrent(Stats::BYTESIN) - stats.getCurrent(Stats::LOCALBYTESIN);
1568 unsigned long long int totalUp = stats.getCurrent(Stats::BYTESOUT) - stats.getCurrent(Stats::LOCALBYTESOUT);
1571 for (int i=GB; i>0; --i)
1573 if (totalUp >= unit[i])
1575 sprintf_s<bufsize>(szUp, "%.2f%s", (double)totalUp/unit[i], suffix[i]);
1580 sprintf_s<bufsize>(szUp, "%d%s", totalUp, suffix[0]);
1584 for (int i=GB; i>0; --i)
1586 if (totalDown >= unit[i])
1588 sprintf_s<bufsize>(szDown, "%.2f%s", (double)totalDown/unit[i], suffix[i]);
1593 sprintf_s<bufsize>(szDown, "%d%s", totalDown, suffix[0]);
1596 SetDlgItemText(hDlg, IDC_STATIC_UP, szUp);
1597 SetDlgItemText(hDlg, IDC_STATIC_DOWN, szDown);
1603 trafficDlgThread.active = false;
1604 if (winDistinctionNT)
1607 DestroyWindow(hDlg);