From 7c53c3c262dd67bbe9bcac3971621face2455f82 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Sun, 2 Feb 2014 09:39:36 +0000 Subject: Miranda API update mRadio:refactoring git-svn-id: http://svn.miranda-ng.org/main/trunk@8000 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/ExternalAPI/delphi/m_userinfoex.inc | 46 -- plugins/mRadio/i_bass.inc | 969 ----------------------- plugins/mRadio/i_cc.inc | 433 ----------- plugins/mRadio/i_frameapi.inc | 238 ------ plugins/mRadio/i_hotkey.inc | 1 - plugins/mRadio/i_myservice.inc | 141 +++- plugins/mRadio/i_optdlg.inc | 477 ++++-------- plugins/mRadio/i_service.inc | 16 +- plugins/mRadio/i_tray.inc | 91 ++- plugins/mRadio/i_variables.inc | 2 +- plugins/mRadio/i_vars.inc | 162 ---- plugins/mRadio/i_visual.inc | 4 + plugins/mRadio/mradio.dpr | 266 ++----- plugins/mRadio/rbass.pas | 1106 +++++++++++++++++++++++++++ plugins/mRadio/rccenter.pas | 443 +++++++++++ plugins/mRadio/rframeapi.pas | 266 +++++++ plugins/mRadio/rglobal.pas | 257 +++++++ plugins/mRadio/roptions.pas | 251 ++++++ 18 files changed, 2754 insertions(+), 2415 deletions(-) delete mode 100644 plugins/mRadio/i_bass.inc delete mode 100644 plugins/mRadio/i_cc.inc delete mode 100644 plugins/mRadio/i_frameapi.inc delete mode 100644 plugins/mRadio/i_vars.inc create mode 100644 plugins/mRadio/rbass.pas create mode 100644 plugins/mRadio/rccenter.pas create mode 100644 plugins/mRadio/rframeapi.pas create mode 100644 plugins/mRadio/rglobal.pas create mode 100644 plugins/mRadio/roptions.pas (limited to 'plugins') diff --git a/plugins/ExternalAPI/delphi/m_userinfoex.inc b/plugins/ExternalAPI/delphi/m_userinfoex.inc index 9afa252016..05f2c54849 100644 --- a/plugins/ExternalAPI/delphi/m_userinfoex.inc +++ b/plugins/ExternalAPI/delphi/m_userinfoex.inc @@ -257,52 +257,6 @@ Slightly modified version of MButtonClass, to draw both text and icon in a butto } UINFOBUTTONCLASS = 'UInfoButtonClass'; -(*!! DELETED -{************************************************************* - * Messagebox module -} - -{ UserInfo/MsgBox v0.1.0.3+ -Some little changed message box for nicer look of miranda's messages or questions :-) -wParam=hContact - can be null -lParam=(TMsgBox* )pMsg - structure that holds information about the look of the message dialog -uType member of TMsgBox can be a combination of the following values, where most of them are defined in winuser.h: -MB_OK -MB_OKCANCEL -MB_YESALLNO -MB_YESNO -For valid icon values use one of the following MB_ICON_... -Funktion returns: IDOK, IDYES, IDALL, IDNO or IDCANCEL -} - MB_YESALLNO = $00000007; - MB_UNICODE = $10000000; - -{ -valid predefined icon values -} - MB_ICON_NONE = $00000000; - MB_ICON_ERROR = $00000010; - MB_ICON_QUESTION = $00000020; - MB_ICON_WARNING = $00000030; - MB_ICON_INFO = $00000040; - MB_ICON_OTHER = $000000F0; // use icon TMsgBox->hiMsg - -type - PMsgBox = ^TMsgBox; - TMsgBox = record - uSize :uint; // size of this structure - uType :uint; // parameters - hiLogo :HICON; // right upper icon of the info bar - hiMsg :HICON; // icon left next to the message text - szTitle :TCHAR; // dialog window title text - szInfoText:TCHAR; // text of the infobar on the top of the dialog - szMsg :TCHAR; // the message text - hParent :hwnd; // parent window for the messagebox - end; - -const - MS_MSGBOX:PAnsiChar = 'UserInfo/MsgBox'; -*) {************************************************************* * contact info module } diff --git a/plugins/mRadio/i_bass.inc b/plugins/mRadio/i_bass.inc deleted file mode 100644 index 5e430de282..0000000000 --- a/plugins/mRadio/i_bass.inc +++ /dev/null @@ -1,969 +0,0 @@ -{BASS dll code} -const - signMP3 = $FBFF; - signID3 = $00334449; - signOGG = $5367674F; - OGGHdrSize = 26; // +1=NumSegments -const - BASSName = 'bass.dll'; - StationHeader:PByte=nil; -const - basspath:PWideChar=nil; -var - hdrlen:integer; - syncMETA, - syncOGG, - syncWMA, - syncWMA1, - syncEND:HSYNC; - SaveHeader:bool; - -procedure SetSndVol(arg:integer); -begin - if arg<0 then - arg:=gVolume - else - gVolume:=arg; - - if chan<>0 then - begin - if arg<0 then arg:=0; - BASS_ChannelSetAttribute(chan,BASS_ATTRIB_VOL,arg/100); - end; -end; - -procedure BassError(text:PWideChar); -begin - MessageboxW(0,TranslateW(text),TranslateW('Sorry!'),MB_ICONERROR) -end; - -procedure ErrorCustom(text:pWideChar=nil); -var - buf:array [0..255] of WideChar; - idx:integer; - pcw:pWideChar; -begin - idx:=BASS_ErrorGetCode(); - if (idx<0) or (idx>BASS_ERROR_MAXNUMBER) then - begin - if text=nil then - pcw:='Unknown error' - else - pcw:=text; - end - else - pcw:=FastAnsiToWideBuf(BASS_ERRORS[idx],@buf); - - MessageBoxW(0,TranslateW(pcw), - TranslateW('Oops! BASS error'),MB_ICONERROR) -end; - -procedure EQ_OFF; -var - i:dword; -begin - if chan<>0 then - for i:=0 to 9 do - BASS_ChannelRemoveFX(chan,eq[i].fx); - isEQ_OFF:=BST_CHECKED; -end; - -procedure EQ_ON; -var - i:dword; -begin - if chan<>0 then - begin - for i:=0 to 9 do - eq[i].fx:=BASS_ChannelSetFX(chan,BASS_FX_DX8_PARAMEQ,1); - for i:=0 to 9 do - BASS_FXSetParameters(eq[i].fx,@eq[i].param); - isEQ_OFF:=BST_UNCHECKED; - end; -end; - -function MyLoadBASS(root:PwideChar;custom:pWideChar):bool; -var - pc:PWideChar; - buf:array [0..MAX_PATH-1] of WideChar; -begin - result:=true; - mGetMem(basspath,1024); - pc:=StrCopyEW(basspath,custom); - if (pc-1)^<>'\' then - begin - pc^:='\'; - inc(pc); - end; - StrCopyW(pc,BASSName); - if not Load_BASSDLL(basspath) then - begin - pc:=StrCopyW(StrCopyEW(basspath,root),BASSName); - if not Load_BASSDLL(basspath) then - begin - pc:=StrCopyW(StrCopyEW(pc,'plugins\'),BASSName); - if not Load_BASSDLL(basspath) then - begin - pc:=StrCopyW(StrCopyEW(pc,'bass\'),BASSName); - if not Load_BASSDLL(basspath) then - begin - if (custom<>nil) and (custom^<>#0) then - BassError('BASS.DLL not found!'); - result:=false; - end; - end; - end; - end; - - if (not result) and ((custom=nil) or (custom^=#0)) then - begin - if MessageboxA(0,Translate('BASS.DLL not found! Choose BASS.dll path manually'), - cPluginName,MB_YESNO)=IDYES then - begin - pc := nil; - if SelectDirectory(TranslateW('Choose BASS.dll path'),pc,0) then - begin - PathToRelativeW(pc,buf); - pc:=StrCopyEW(basspath,buf); - if (pc-1)^<>'\' then - begin - pc^:='\'; - inc(pc); - end; - pc^:=#0; - DBWriteUnicode(0,PluginName,optBASSPath,basspath); - StrCopyW(pc,BASSName); - - if not Load_BASSDLL(basspath) then - BassError('BASS.DLL not found!') - else - result:=true; - end; - - end; - end; - - if result then - begin - if (BASS_GetVersion shr 16)0 then - begin - if syncMETA<>0 then - begin - BASS_ChannelRemoveSync(chan,syncMETA); - syncMETA:=0 - end; - if syncEND<>0 then - begin - BASS_ChannelRemoveSync(chan,syncEND); - syncEND:=0 - end; - if syncWMA<>0 then - begin - BASS_ChannelRemoveSync(chan,syncWMA); - syncWMA:=0 - end; - if syncOGG<>0 then - begin - BASS_ChannelRemoveSync(chan,syncOGG); - syncOGG:=0 - end; - if syncWMA1<>0 then - begin - BASS_ChannelRemoveSync(chan,syncWMA1); - syncWMA1:=0 - end; - end; -end; - -procedure MyFreeBASS; -begin - MyStopBASS; - BASS_Free; - BASS_PluginFree(0); -end; - -procedure StopStation; -begin - if chan<>0 then - BASS_StreamFree(chan); // close old stream - chan:=0; - mFreeMem(StationHeader); - mFreeMem(ActiveURLw); - DBDeleteSetting(ActiveContact,strCList,optStatusMsg); - MyStopBASS; -end; - -function GetDeviceNumber:integer; -var - i:integer; - info:BASS_DEVICEINFO; -begin - // default device - result:=-1; - i:=1; - repeat - if not BASS_GetDeviceInfo(i,info) then - break; - if (info.flags and BASS_DEVICE_ENABLED)<>0 then - if StrCmp(info.name,usedevice)=0 then - begin - // not default device - if (info.flags and BASS_DEVICE_DEFAULT)=0 then - result:=i; - break; - end; - inc(i); - until false; -end; - -function MyInitBASS:int; -var - fd:TWin32FindDataW; - fh:THANDLE; - buf:array [0..MAX_PATH-1] of WideChar; -// buf1:array [0..31] of WideChar; - pc:PWideChar; - p:Bool; - num:integer; -begin - if Inited then - begin - result:=1; - exit; - end; - - Inited:=true; - BASS_Free; - - num:=GetDeviceNumber; - p:=BASS_Init(num,44100,BASS_DEVICE_3D,0,nil); - if not p then - p:=BASS_Init(num,44100,0,0,nil); - // not default device choosed - check default now - if (not p) and (num>=0) then - begin - p:=BASS_Init(-1,44100,BASS_DEVICE_3D,0,nil); - if not p then - p:=BASS_Init(-1,44100,0,0,nil); - end; - - if not p then - begin - ErrorCustom('Can''t initialize device'); - result:=0; - end - else - begin - pc:=StrCopyW(StrCopyEW(buf,basspath),'bass*.dll'); - fh:=FindFirstFileW(buf,fd); - if fh<>INVALID_HANDLE_VALUE then - begin - repeat - StrCopyW(pc,fd.cFileName); - if BASS_PluginLoad(pAnsiChar(@buf),BASS_UNICODE)=0 then - until not FindNextFileW(fh,fd); - FindClose(fh); - end; - // enable ASX processing (if WMA loaded) - BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST, 2); // 2 - enable internet and local playlists - - fh:=DBReadByte(0,PluginName,optEAXType,0); - if fh=0 then - BASS_SetEAXParameters(-1,0,-1,-1) - else - BASS_SetEAXPreset(EAXItems[fh].code); - result:=1; - end; -end; - -function GetMusicFormat:PAnsiChar; -var - bci:BASS_CHANNELINFO; -begin - BASS_ChannelGetInfo(chan,bci); - case bci.ctype of - BASS_CTYPE_STREAM_OGG: result:='OGG'; - BASS_CTYPE_STREAM_MP1, - BASS_CTYPE_STREAM_MP2, - BASS_CTYPE_STREAM_MP3: result:='MP3'; - BASS_CTYPE_STREAM_WMA, - BASS_CTYPE_STREAM_WMA_MP3: result:='WMA'; - {BASS_CTYPE_STREAM_AAC,}$10b00: result:='AAC'; - {BASS_CTYPE_STREAM_MP4:}$10b01: result:='MP4'; - {BASS_CTYPE_STREAM_AC3:}$11000: result:='AC3'; - else - result:=nil; - end; -end; - -function GetFileExt(buf:pWideChar;sign:pointer):pWideChar; -var - pc:pAnsiChar; -begin - result:=buf; - pc:=GetMusicFormat; - if pc=nil then - begin - StrCopyW(buf,'sav'); - if sign<>nil then - begin - if pdword(sign)^=signOGG then - StrCopyW(buf,'ogg') - else if ((pdword(sign)^ and $00FFFFFF)=signID3) or (pword(sign)^=signMP3) then - StrCopyW(buf,'mp3'); - end; - end - else - begin - FastAnsiToWideBuf(pc,buf); - LowerCase(buf); - end; -end; - -function MakeFileName(sign:pointer):pWideChar; -var - p,pcw:PWideChar; - buf:pWideChar; -begin -// allocate buffer - mGetMem(buf,MAX_PATH*SizeOf(WideChar)); -// path - if recpath<>nil then - begin - ConvertFileName(recpath,buf,ActiveContact); - if not ForceDirectories(buf) then - begin - result:=nil; - exit; - end; - pcw:=StrEndW(buf); - if (pcw-1)^<>'\' then - begin - pcw^:='\'; - inc(pcw); - end; - end - else - pcw:=buf; -// name -//!! - p:=MakeMessage; - pcw:=StrCopyEW(pcw,p); - mFreeMem(p); - if (pcw=buf) or ((pcw-1)^='\') then - pcw:=StrEndW(IntToHex(pcw,GetCurrentTime)); -// ext - pcw^:='.'; inc(pcw); - GetFileExt(pcw,sign); - - result:=buf; -end; - -procedure StatusProc(buffer:Pointer;len,user:DWORD); stdcall; -var - pc:pWideChar; - pb:PByte; - i,sum:integer; - flag:bool; - doRecord:bool; -begin - flag:=true; - doRecord:=CallService(MS_RADIO_COMMAND,MRC_RECORD,LPARAM(-1))<>0; - if (buffer<>nil) and (len<>0) and SaveHeader then - begin - SaveHeader:=false; - if pdword(buffer)^=signOGG then // if header ALL in buffer - begin - pb:=buffer; - flag:=false; - repeat - inc(pb,OGGHdrSize); - i:=pb^; //patterns - sum:=0; - inc(pb); - while i>0 do - begin - inc(sum,pb^); - inc(pb); - dec(i); - end; - inc(pb,sum); //here must be next sign - flag:=not flag; - until not flag; - hdrlen:=PAnsiChar(pb)-PAnsiChar(buffer); - mGetMem(StationHeader,hdrlen); - move(buffer^,StationHeader^,hdrlen); - end; - end; - if (buffer=nil) or not doRecord then // end of stream or stop record - begin - if not doRecord or (doContRec=BST_UNCHECKED) then - if hRecord<>0 then - begin - if buffer<>nil then // write tail - BlockWrite(hRecord,buffer^,len); - CloseHandle(hRecord); - hRecord:=0; - end; - end - else - begin - if len=0 then // HTTP or ICY tags - begin -{ -while PAnsiChar(buffer)^<>#0 do -begin -messagebox(0,PAnsiChar(buffer),'ICY-HTTP',0); -while PAnsiChar(buffer)^<>#0 do inc(PAnsiChar(buffer)); inc(PAnsiChar(buffer)); -end; -} - end - else - begin - if doRecord then - begin - if hRecord=0 then - begin - pc:=MakeFileName(StationHeader); - if pc<>nil then - hRecord:=Rewrite(pc) - else - hRecord:=THANDLE(INVALID_HANDLE_VALUE); - if hRecord=THANDLE(INVALID_HANDLE_VALUE) then - hRecord:=0 - else if flag and (StationHeader<>nil) then - begin - BlockWrite(hRecord,StationHeader^,hdrlen); -// permissible to skip to the next Page (OggS) but this is not necessary - end; - mFreeMem(pc); - end; - if hRecord<>0 then - BlockWrite(hRecord,buffer^,len); - end; - end; - end; -end; - -{$IFDEF Debug} -procedure logmeta(tag,a,b:pansiChar); -var - f:thandle; - p:pansichar; -begin - f:=Append(pansichar('mradio.log')); - BlockWrite(f,tag^,StrLen(tag)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - BlockWrite(f,a^,StrLen(a)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - BlockWrite(f,b^,StrLen(b)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - CloseHandle(f); -end; -{$ENDIF} - -function DoMeta(meta:PAnsiChar;TagType:int_ptr):Boolean; -var - pcw:pWideChar; - buf:array [0..511] of AnsiChar; - artist,title:PAnsiChar; - oldartist,oldtitle:pAnsiChar; - ppc,pc:pAnsiChar; - idx,lcp:integer; - needtofree:Boolean; - CurDescrW:PWideChar; - old:boolean; - -// tag:PAnsiChar; - gotartist,gottitle:boolean; // indicate what we got artist/title -begin - result:=false; - - if meta=nil then - meta:=BASS_ChannelGetTags(chan,TagType); - if meta<>nil then - begin - // for cases when artist or title presents but empty - gotartist:=false; - gottitle :=false; - needtofree:=false; - lcp:=CP_UTF8; - buf[0]:=#0; - artist:=nil; - title :=nil; - CurDescrW:=nil; - -//tag:=meta; - case TagType of - BASS_TAG_WMA_META: begin - pc:=StrPos(meta,'data='); - if pc=meta then - begin - pc:=StrPos(meta,'artist='); - if pc<>nil then - begin - gotartist:=true; - mGetMem(artist,256); - Decode(artist,pc+7); - end; - - pc:=StrPos(meta,'title='); - if pc<>nil then - begin - gottitle:=true; - mGetMem(title,256); - Decode(title,pc+6); - end; - - pc:=StrPos(meta,'album='); - if pc<>nil then - begin - end; - - pc:=StrPos(meta,'duration='); - if pc<>nil then - begin - end; - - if not gotartist then - begin - if not gottitle then - begin - pc:=StrPos(meta,'caption='); - if pc<>nil then - begin - gottitle:=true; - mGetMem(title,256); - Decode(title,pc+8); - end; - end; - - // analize title/caption for artist-title - if gottitle then - begin - pc:=StrPos(title,' - '); - if pc=nil then - pc:=StrScan(title,'-'); - if pc<>nil then - begin - artist:=title; - if pc^=' ' then - title:=pc+3 - else - title:=pc+1; - pc^:=#0; - CurDescrW:=pWideChar(artist); - end - else - CurDescrW:=pWideChar(title); - end; - end - else - needtofree:=true; - - // to avoid mem leak and wrong tag process - result:=true; - end; - StatusProc(nil,0,0); // split records here - end; - - BASS_TAG_META: begin -//tag:='SHOUTCAST'; - // SHOUTCAST StreamTitle='xxx';StreamUrl='xxx'; - // "Station=xyz" meta tag="Trackinfo" - pc:=StrPos(meta,'StreamTitle='); - if pc<>nil then - begin - inc(pc,13); - ppc:=StrScan(pc,';'); - if (ppc-pc-1)>0 then - begin - StrCopy(buf,pc,ppc-pc-1); - lcp:=GetTextFormat(@buf,ppc-pc-1); - end; - end; - if buf[0]<>#0 then - begin - case lcp of - CP_UTF8: UTF8ToWide(buf,CurDescrW); - CP_ACP : AnsiToWide(buf,CurDescrW,MirandaCP); - end; - end; - - gottitle:=true; - title:=pAnsiChar(CurDescrW); - pcw:=StrPosW(CurDescrW,' - '); - if pcw=nil then - pcw:=StrScanW(CurDescrW,'-'); - if pcw<>nil then - begin - artist:=pAnsiChar(CurDescrW); - if pcw^=' ' then - title:=pAnsiChar(pcw+3) - else - title:=pAnsiChar(pcw+1); - pcw^:=#0; - end; - - lcp:=CP_UNICODE; - - StatusProc(nil,0,0); // split records here - result:=true; - end; - - BASS_TAG_ID3: begin // not realized, anyway - at the end of track - end; - - BASS_TAG_ID3V2: begin - end; - - BASS_TAG_APE, // not sure, need to check. maybe better process BASS_TAG_APEBINARY - BASS_TAG_WMA, - BASS_TAG_OGG: begin -//tag:='OGG'; - while meta^<>#0 do - begin - CharLowerA(StrCopy(buf,meta,10)); - if StrCmp(buf,'title',5)=0 then - begin - title:=meta+6; - gottitle:=true; - end - else if StrCmp(buf,'artist',6)=0 then - begin - artist:=meta+7; - gotartist:=true; - end; - if gotartist and gottitle then - break; - while meta^<>#0 do inc(meta); inc(meta); - end; - - if (not gotartist) and gottitle then - begin - pc:=StrPos(title,' - '); - if pc=nil then - pc:=StrScan(title,'-'); - if pc<>nil then - begin - needtofree:=true; - StrDup(artist,title,pc-title); - if pc^=' ' then - idx:=3 - else - idx:=1; - StrDup(title,pc+idx); - end; - end; - buf[0]:=#0; - end; - end; - - old:=true; - if gotartist or gottitle then - begin - // check for old - oldartist:=nil; - oldtitle :=nil; - case lcp of - CP_UTF8: begin - if gotartist then - begin - oldartist:=DBReadUTF8(0,PluginName,optArtist); - if StrCmp(artist,oldartist)<>0 then - old:=false; - end; - - if old and gottitle then - begin - oldtitle:=DBReadUTF8(0,PluginName,optTitle); - if StrCmp(title,oldtitle)<>0 then - old:=false; - end; - - if not old then - begin - DBWriteUTF8(0,PluginName,optArtist,artist); - DBWriteUTF8(0,PluginName,optTitle ,title); - end; - end; - - CP_UNICODE:begin - if gotartist then - begin - oldartist:=pAnsiChar(DBReadUnicode(0,PluginName,optArtist)); - if StrCmpW(pWideChar(artist),pWideChar(oldartist))<>0 then - old:=false; - end; - - if old and gottitle then - begin - oldtitle:=pAnsiChar(DBReadUnicode(0,PluginName,optTitle)); - if StrCmpW(pWideChar(title),pWideChar(oldtitle))<>0 then - old:=false; - end; - - if not old then - begin - DBWriteUnicode(0,PluginName,optArtist,pWideChar(artist)); - DBWriteUnicode(0,PluginName,optTitle ,pWideChar(title)); - end; - end; - end; -{$IFDEF Debug} -logmeta(tag,artist,title); -{$ENDIF} - mFreeMem(oldartist); - mFreeMem(oldtitle); - mFreeMem(CurDescrW); - if needtofree then - begin - mFreeMem(artist); - mFreeMem(title ); - end; - end; - - if not old then - CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_NEWTAG); - end; -end; - -procedure MetaSync(handle:HSYNC;channel,data:dword;user:pointer); stdcall; -//var tagtype:Integer; -begin -(* - if handle=syncOGG then tagtype:=BASS_TAG_OGG - else if handle=syncWMA then tagtype:=BASS_TAG_WMA - else if handle=syncWMA1 then tagtype:=BASS_TAG_WMA_META - else {if handle=syncMETA then} tagtype:=BASS_TAG_META; -*) - DoMeta(nil{PAnsiChar(data)},int_ptr(user){tagtype}); -end; - -procedure EndSync(handle:HSYNC;channel,data:dword;user:pointer); stdcall; -var - lContact:cardinal; -begin - if RemoteSong then - begin - lContact:=ActiveContact; - CallService(MS_RADIO_COMMAND,MRC_STOP,0); - CallService(MS_RADIO_COMMAND,MRC_PLAY,lContact) - end - else if plist<>nil then CallService(MS_RADIO_COMMAND,MRC_NEXT,0) - else if doLoop=BST_UNCHECKED then CallService(MS_RADIO_COMMAND,MRC_STOP,0); -end; - -type - tICYField = record - name :PAnsiChar; - branch:PAnsiChar; - option:PAnsiChar; - end; -const - NumICYFields = 4; - ICYFields: array [0..NumICYFields-1] of tICYField = ( - (name:'icy-name:' ; branch:'CList' ; option:'MyHandle'), - (name:'icy-genre:' ; branch:cPluginName ; option:'Genre'), - (name:'icy-br:' ; branch:cPluginName ; option:'Bitrate'), - (name:'icy-description'; branch:cPluginName ; option:'About') - ); - -procedure ProcessStationData; -var - icy:PAnsiChar; - i,len:integer; -begin - // get the broadcast name and bitrate - icy:=BASS_ChannelGetTags(chan,BASS_TAG_ICY); - if icy=nil then - icy:=BASS_ChannelGetTags(chan,BASS_TAG_HTTP); // no ICY tags, try HTTP - if icy<>nil then - begin - while icy^<>#0 do - begin - for i:=0 to NumICYFields-1 do - begin - with ICYFields[i] do - begin - len:=StrLen(name); - if StrCmp(icy,name,len)=0 then - begin - if DBReadStringLength(ActiveContact,branch,option)=0 then - DBWriteString(ActiveContact,branch,option,icy+len); - break; - end; - end; - end; - while icy^<>#0 do inc(icy); inc(icy); - end; - end; -end; - -procedure OpenURL(url:PWideChar); cdecl; -var - len,progress:DWORD; - flags:dword; - i:integer; - EAXUsed:bool; - ansiurl:array [0..511] of AnsiChar; -begin - if plist=nil then - CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_CONNECT); - - EAXUsed:=DBReadByte(0,PluginName,optEAXType,0)<>0; - -{} - for i:=0 to NumTries-1 do - begin - if EAXUsed then - flags:=BASS_STREAM_STATUS or BASS_SAMPLE_3D or BASS_SAMPLE_MONO - else - begin - if ForcedMono<>BST_UNCHECKED then - flags:=BASS_STREAM_STATUS or BASS_SAMPLE_MONO - else - flags:=BASS_STREAM_STATUS; - end; - - flags:=flags or BASS_UNICODE; - if RemoteSong then - begin - SaveHeader:=true; - chan:=BASS_StreamCreateURL(url,0,flags,@StatusProc,nil) - end - else - begin - if (plist=nil) and (doLoop<>BST_UNCHECKED) then - flags:=flags or BASS_SAMPLE_LOOP; - chan:=BASS_StreamCreateFile(FALSE,url,0,0,flags); - end; - - if (chan=0) and EAXUsed then - begin - flags:=flags and not (BASS_SAMPLE_3D or BASS_SAMPLE_MONO); - if ForcedMono<>BST_UNCHECKED then - flags:=flags or BASS_SAMPLE_MONO; - - if RemoteSong then - chan:=BASS_StreamCreateURL({ansi}url,0,flags,@StatusProc,nil) - else - chan:=BASS_StreamCreateFile(FALSE,url,0,0,flags); - end; - - if (chan=0) and RemoteSong then - begin - if BASS_ErrorGetCode=BASS_ERROR_FILEOPEN then - begin - flags:=flags and not BASS_UNICODE; - chan:=BASS_StreamCreateURL(FastWideToAnsiBuf(url,ansiurl),0,flags,@StatusProc,nil) - end; - end; - - if chan<>0 then break; - end; -{} - - if chan=0 then - begin - if (CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET)=RD_STATUS_ABORT) or - (plist=nil) then - begin - CallService(MS_RADIO_COMMAND,MRC_STOP,1); - end - else if plist<>nil then - CallService(MS_RADIO_COMMAND,MRC_NEXT,0); - end - else - begin - - CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_NEWTRACK); - - if RemoteSong then - begin - if isEQ_OFF=BST_UNCHECKED then - EQ_ON; - -{$IFDEF CHANGE_NAME_BUFFERED} - icy:=DBReadString(ActiveContact,strCList,optMyHandle); - mGetMem(url,StrLen(icy)+6); - StrCopy(url+6,icy); - mFreeMem(icy); - url[0]:='['; - url[1]:=#0; - url[4]:=']'; - url[5]:=' '; -{$ENDIF} - progress:=0; - repeat - if CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET)=RD_STATUS_ABORT then - begin - CallService(MS_RADIO_COMMAND,MRC_STOP,1); - exit; - end; - len:=BASS_StreamGetFilePosition(chan,BASS_FILEPOS_END); - if len=DW_ERROR then - break; - progress:=BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD); - if progress=dword(-1) then - break; - progress:=(progress- - BASS_StreamGetFilePosition(chan,BASS_FILEPOS_CURRENT))*100 div len; - // percentage of buffer filled -{$IFDEF CHANGE_NAME_BUFFERED} - IntToStr(url+1,progress,2); - url[3]:='%'; - DBWriteString(ActiveContact,strCList,optMyHandle,url); -{$ENDIF} - until progress>sPreBuf; -{$IFDEF CHANGE_NAME_BUFFERED} - if url[1]<>#0 then - DBWriteString(ActiveContact,strCList,optMyHandle,url+6); - mFreeMem(url); -{$ENDIF} - - ProcessStationData; // process ICY-headers - - // get the stream title and set sync for subsequent titles - DoMeta(nil,BASS_TAG_META); - - syncMETA:=BASS_ChannelSetSync(chan,BASS_SYNC_META ,0,@MetaSync,pointer(BASS_TAG_META)); - syncOGG :=BASS_ChannelSetSync(chan,BASS_SYNC_OGG_CHANGE,0,@MetaSync,pointer(BASS_TAG_OGG)); - syncWMA :=BASS_ChannelSetSync(chan,BASS_SYNC_WMA_CHANGE,0,@MetaSync,pointer(BASS_TAG_WMA)); - syncWMA1:=BASS_ChannelSetSync(chan,BASS_SYNC_WMA_META ,0,@MetaSync,pointer(BASS_TAG_WMA_META)); - end - else - begin - if not DoMeta(nil,BASS_TAG_OGG) then - if not DoMeta(nil,BASS_TAG_ID3V2) then - if not DoMeta(nil,BASS_TAG_ID3) then - if not DoMeta(nil,BASS_TAG_APE) then - ; - - end; - - syncEND:=BASS_ChannelSetSync(chan,BASS_SYNC_END,0,@EndSync,nil); - - SetSndVol(-1); - // play it! - BASS_ChannelPlay(chan,FALSE); - end; -end; diff --git a/plugins/mRadio/i_cc.inc b/plugins/mRadio/i_cc.inc deleted file mode 100644 index c9364d1e8a..0000000000 --- a/plugins/mRadio/i_cc.inc +++ /dev/null @@ -1,433 +0,0 @@ -{} - -function GetStatusText(status:integer;toCList:boolean=false):PWideChar; -begin - case status of - RD_STATUS_PAUSED : result:='paused'; - RD_STATUS_STOPPED: if toCList then result:=nil else result:='stopped'; - RD_STATUS_CONNECT: result:='connecting'; - RD_STATUS_ABORT : result:='aborting'; - RD_STATUS_PLAYING: if toCList then result:=nil else result:='playing'; - else - result:=nil; - end; -end; - -procedure ConstructMsg(artist,title:PWideChar;status:integer=-1); -var - buf:PWideChar; - tstrlen,astrlen,statuslen:integer; - sstatus:PWideChar; - p:pWideChar; -begin - astrlen:=StrLenW(artist); - - tstrlen:=0; - // if need to remove duplicate - if (title<>nil) and (title^<>#0) then - begin - if (astrlen=0) or (StrCmpW(artist,title)<>0) then - tstrlen:=StrLenW(title); - end; - if (astrlen>0) and (tstrlen>0) then - inc(tstrlen,3); - - statuslen:=0; - if status>=0 then - begin - sstatus:=TranslateW(GetStatusText(status,true)); - if sstatus<>nil then - statuslen:=StrLenW(sstatus)+3; - end - else - sstatus:=nil; - - if (astrlen+tstrlen+statuslen)>0 then - begin - mGetMem(buf,(astrlen+tstrlen+statuslen+1)*SizeOf(WideChar)); - p:=buf; - if astrlen>0 then - p:=StrCopyEW(p,artist); - - if tstrlen>0 then - begin - if astrlen>0 then - begin - p^:=' '; inc(p); - p^:='-'; inc(p); - p^:=' '; inc(p); - end; - p:=StrCopyEW(p,title); - end; - - if statuslen>0 then - begin - p^:=' '; inc(p); - p^:='('; inc(p); - p:=StrCopyEW(p,sstatus); - p^:=')'; inc(p); - p^:=#0; - end; - - DBWriteUnicode(ActiveContact,strCList,optStatusMsg,buf); - mFreeMem(buf); - end - else - DBDeleteSetting(ActiveContact,strCList,optStatusMsg); -end; - -{$IFDEF Debug} -procedure log(a,b:lparam); -var - f:thandle; - buf:array [0..31] of ansichar; - p:pansichar; -begin - f:=Append(pansichar('mradio.log')); - p:=IntToStr(buf,a); BlockWrite(f,p^,StrLen(p)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - p:=IntToStr(buf,b); BlockWrite(f,p^,StrLen(p)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - p:=#13#10; BlockWrite(f,p^,StrLen(p)); - CloseHandle(f); -end; -{$ENDIF} - -function ControlCenter(code:WPARAM;arg:LPARAM):int_ptr; cdecl; -const - PlayStatus:int_ptr=RD_STATUS_NOSTATION; - doRecord:boolean=false; -var - tmpbuf,buf1:array [0..MAX_PATH-1] of WideChar; - plFile:pWideChar; - plLocal:boolean; - artist,title:pWideChar; -begin - result:=0; -{$IFDEF Debug} - log(code,arg); -{$ENDIF} - case code of - MRC_PLAY : begin - // play new station? - if arg<>0 then - begin - ActiveURLw:=DBReadUnicode(arg,PluginName,optStationURL); - // no URL for this contact - if (ActiveURLw=nil) or (ActiveURLw^=#0) then exit; - - ActiveContact:=arg; - RemoteSong:=StrPosW(ActiveURLw,'://')<>nil; - - if isPlaylist(ActiveURLw)<>0 then - begin - - if RemoteSong then - begin - GetTempPathW(MAX_PATH,tmpbuf); - GetTempFileNameW(tmpbuf,'mr',GetCurrentTime,buf1); - if not GetFile(ActiveURLw,buf1,hNetLib) then - begin - exit; - end; - plFile:=@buf1; - plLocal:=false; - end - else - begin - plFile:=ActiveURLw; - plLocal:=true; - end; - - plist:=CreatePlaylist(plFile); - if not plLocal then - DeleteFileW(plFile); - - if plist<>nil then - begin - if plist.GetCount=0 then - begin - plist.Free; - plist:=nil; - ActiveContact:=0; - exit; - end; - plist.Shuffle:=doShuffle<>BST_UNCHECKED; - - if not plist.Shuffle then - begin - if PlayFirst=BST_UNCHECKED then - plist.Track:=DBReadWord(ActiveContact,PluginName,optCurElement); - end; - - mFreeMem(ActiveURLw); - ActiveURLw:=plist.GetSong; - end; - RemoteSong:=StrPosW(ActiveURLw,'://')<>nil; // coz activeuRLw can be changed - end - else - plist:=nil; - - if (ActiveURLw<>nil) and (ActiveURLw^<>#0) then - begin - if RemoteSong then - begin - if GetWorkOfflineStatus<>0 then - begin - BassError('Can''t connect to net. Please, clear ''Work offline'' option in Internet settings'); - ControlCenter(MRC_STATUS,RD_STATUS_NOSTATION); - exit; - end; - end; - ControlCenter(MRC_STATUS,RD_STATUS_NEWSTATION); - if Assigned(plist) then - ControlCenter(MRC_STATUS,RD_STATUS_CONNECT); - mir_forkthread(@OpenURL,ActiveURLw); - end; - end - // play current from start - else if chan<>0 then - begin - BASS_ChannelPlay(chan,true); - code:=MRC_STATUS; - arg :=RD_STATUS_PLAYING; - end - // play playlist entry? - else if Assigned(plist) and (ActiveURLw<>nil) and (ActiveURLw^<>#0) then - begin - mir_forkthread(@OpenURL,ActiveURLw); - end; - end; - - MRC_RECORD: begin - if arg=LPARAM(-1) then - result:=ord(doRecord) - else - begin - case arg of - 1: doRecord:=true; // force start - 2: doRecord:=false; // force stop - else - doRecord:=not doRecord; - end; - result:=ord(doRecord); - - code:=MRC_STATUS; - arg :=RD_STATUS_RECORD+(result shl 16); - end; - end; - - MRC_PAUSE: begin - if chan<>0 then - begin - case ControlCenter(MRC_STATUS,RD_STATUS_GET) of - RD_STATUS_PLAYING: begin - BASS_ChannelPause(chan); - arg:=1; - end; - RD_STATUS_PAUSED: begin - BASS_ChannelPlay(chan,false); - arg:=0; - end; - end; - code:=MRC_STATUS; - arg :=RD_STATUS_PAUSED+(arg shl 16); - end - else - begin - ActiveContact:=LoadContact(PluginName,optLastStn); - if ActiveContact<>0 then - ControlCenter(MRC_PLAY,ActiveContact); - end; - end; - - MRC_STOP: begin - ControlCenter(MRC_RECORD,2); - - code:=MRC_STATUS; - // stop playlist track but not station - if Assigned(plist) and (arg=0) then - begin - if chan<>0 then - BASS_ChannelStop(chan); - - arg:=RD_STATUS_STOPPED; - end - else // forced or "normal" stop - begin - if Assigned(plist) then - begin - DBWriteWord(ActiveContact,PluginName,optCurElement,plist.Track); - plist.Free; - plist:=nil; - end; - ControlCenter(MRC_STATUS,RD_STATUS_STOPPED); - // Save station for next autoplay - SaveContact(ActiveContact,PluginName,optLastStn); - StopStation; - - arg:=RD_STATUS_NOSTATION; - end; - end; - - MRC_MUTE: begin - CallService(MS_RADIO_MUTE,0,arg); - code:=MRC_STATUS; - arg :=RD_STATUS_MUTED; - end; - - MRC_NEXT: begin - if Assigned(plist) then - begin - StopStation; - ActiveURLw:=plist.Next; - ControlCenter(MRC_PLAY,0); - end; - end; - - MRC_PREV: begin - if Assigned(plist) then - begin - StopStation; - ActiveURLw:=plist.Previous; - ControlCenter(MRC_PLAY,0) - end; - end; - - MRC_SEEK: begin - if not RemoteSong and (chan<>0) then - begin - if integer(arg)=-1 then // get position - begin - result:=trunc(BASS_ChannelBytes2Seconds(chan,BASS_ChannelGetPosition(chan,BASS_POS_BYTE))); - if result<0 then - result:=0; - end - else - begin - BASS_ChannelSetPosition(chan,BASS_ChannelSeconds2Bytes(chan,arg),BASS_POS_BYTE); - - code:=MRC_STATUS; - arg :=RD_STATUS_POSITION+(arg shl 16); - end; - end; - end; - end; - - if code=MRC_STATUS then - begin - if arg=RD_STATUS_GET then - result:=PlayStatus - else - begin - - code:=(arg and $FFFF); - arg :=hiword(arg); - // this is just events - case code of - RD_STATUS_MUTED: begin - end; - - RD_STATUS_RECORD: begin - end; - - RD_STATUS_POSITION: begin - end; - - else - // these statuses are for events and some tasks - artist:=nil; - title :=nil; - case code of - RD_STATUS_NOSTATION: begin - SetStatus(ActiveContact,ID_STATUS_OFFLINE); - ActiveContact:=0; - - DBDeleteSetting(0,PluginName,optActiveURL); - - PlayStatus:=RD_STATUS_NOSTATION; - // empty message - end; - - RD_STATUS_STOPPED: begin - if ActiveContact<>0 then //!! fools proof - DBDeleteSetting(ActiveContact,strCList,optStatusMsg); - - DBDeleteSetting(0,PluginName,optTitle); - DBDeleteSetting(0,PluginName,optArtist); - - PlayStatus:=RD_STATUS_STOPPED; - // empty message - end; - - RD_STATUS_ABORT: begin - PlayStatus:=RD_STATUS_ABORT; - // status as message - end; - - RD_STATUS_CONNECT: begin - SetStatus(ActiveContact,ID_STATUS_AWAY); - PlayStatus:=RD_STATUS_CONNECT; - // status as message - end; - - RD_STATUS_NEWSTATION: begin - arg:=ActiveContact; - PlayStatus:=RD_STATUS_PLAYING; - end; - - RD_STATUS_NEWTRACK: begin - SetStatus(ActiveContact,ID_STATUS_ONLINE); - DBWriteUnicode(0,PluginName,optActiveURL,ActiveURLw); - - DBWriteString(0,PluginName,optActiveCodec,GetMusicFormat); - arg :=lparam(ActiveURLw); - - // for case when tags was in meta - artist:=DBReadUnicode(0,PluginName,optArtist); - title :=DBReadUnicode(0,PluginName,optTitle); - PlayStatus:=RD_STATUS_PLAYING; - // status as message - end; - - RD_STATUS_NEWTAG: begin - // must be updated tags - artist:=DBReadUnicode(0,PluginName,optArtist); - title :=DBReadUnicode(0,PluginName,optTitle); - - PlayStatus:=RD_STATUS_PLAYING; // maybe keep RD_STATUS_NEWTAG? - end; - - RD_STATUS_PLAYING: begin - SetStatus(ActiveContact,ID_STATUS_ONLINE); - PlayStatus:=RD_STATUS_PLAYING; - // status as message - end; - - RD_STATUS_PAUSED: begin - if arg=0 then - begin - PlayStatus:=RD_STATUS_PLAYING; - if StrPosW(ActiveURLw,'://')=nil then //local only - begin - artist:=DBReadUnicode(0,PluginName,optArtist); - title :=DBReadUnicode(0,PluginName,optTitle); - end; - end - else - PlayStatus:=RD_STATUS_PAUSED; - // status as message - end; - else - exit; - end; - ConstructMsg(artist,title,PlayStatus); - mFreeMem(artist); - mFreeMem(title); - end; - - NotifyEventHooks(hhRadioStatus,code,arg); - end; - - end; -end; diff --git a/plugins/mRadio/i_frameapi.inc b/plugins/mRadio/i_frameapi.inc deleted file mode 100644 index 8f70edbf7a..0000000000 --- a/plugins/mRadio/i_frameapi.inc +++ /dev/null @@ -1,238 +0,0 @@ -{mRadio frame} -const - frm_back:pAnsiChar = 'Frame background'; -const - FrameWnd:HWND = 0; - FrameId:integer = -1; -var - colorhook:THANDLE; - hbr:HBRUSH; - frm_bkg:TCOLORREF; - OldSliderWndProc:pointer; - -function QSDlgResizer(Dialog:HWND;lParam:LPARAM;urc:PUTILRESIZECONTROL):int; cdecl; -begin - case urc^.wId of - IDC_RADIO_MUTE: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_CENTRE; - IDC_RADIO_VOL : result:=RD_ANCHORX_WIDTH or RD_ANCHORY_CENTRE; - else - result:=0; - end; -end; - -function SliderWndProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; -begin - if hMessage=WM_ERASEBKGND then - result:=1 - else - result:=CallWindowProc(OldSliderWndProc, Dialog, hMessage, wParam, lParam); -end; - -function RadioFrameProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; -var - urd:TUTILRESIZEDIALOG; - rc:TRECT; - ti:TTOOLINFOW; - hwndTooltip:HWND; - tmp:pAnsiChar; -begin - result:=0; - case hMessage of - WM_DESTROY: begin - hVolFrmCtrl :=0; - hMuteFrmCtrl:=0; - DeleteObject(hbr); - end; - - WM_INITDIALOG: begin - hMuteFrmCtrl:=GetDlgItem(Dialog,IDC_RADIO_MUTE); - SendMessage(hMuteFrmCtrl, BUTTONSETASFLATBTN,0,0); -// SetButtonIcon(hMuteFrmCtrl,IcoBtnOn); - - hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, - integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), - integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), - Dialog,0,hInstance,nil); - - FillChar(ti,SizeOf(ti),0); - ti.cbSize :=sizeof(TOOLINFO); - ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; - ti.hwnd :=Dialog; - ti.hinst :=hInstance; - ti.uId :=hMuteFrmCtrl; - ti.lpszText:=pWideChar(TranslateW('Mute')); - SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); - - hVolFrmCtrl:=GetDlgItem(Dialog,IDC_RADIO_VOL); - SendMessage(hVolFrmCtrl,TBM_SETRANGE,0,MAKELONG(0,100)); - SendMessage(hVolFrmCtrl,TBM_SETPAGESIZE,0,20); - SendMessage(hVolFrmCtrl,TBM_SETPOS,1,gVolume); - - OldSliderWndProc:=pointer(SetWindowLongPtrW(hVolFrmCtrl,GWL_WNDPROC,LONG_PTR(@SliderWndProc))); - end; - - WM_SIZE: begin - FillChar(urd,SizeOf(TUTILRESIZEDIALOG),0); - urd.cbSize :=SizeOf(urd); - urd.hwndDlg :=Dialog; - urd.hInstance :=hInstance; - urd.lpTemplate:=MAKEINTRESOURCEA(IDD_FRAME); - urd.lParam :=0; - urd.pfnResizer:=@QSDlgResizer; - CallService(MS_UTILS_RESIZEDIALOG,0,tlparam(@urd)); - end; - - WM_ERASEBKGND: begin - GetClientRect(Dialog,rc); - FillRect(wParam,rc,hbr); - result:=1; - end; - - WM_DRAWITEM: begin - if wParam=IDC_RADIO_MUTE then - begin - result:=1; - if gVolume<0 then - tmp:=IcoBtnOff - else - tmp:=IcoBtnOn; - DrawIconEx(PDRAWITEMSTRUCT(lParam)^.hDC,0,0, - CallService(MS_SKIN2_GETICON,0,TLPARAM(tmp)), - 16,16,0,hbr,DI_NORMAL); - end; - end; - - WM_CTLCOLORBTN: begin - if THANDLE(lParam)=hMuteFrmCtrl then - begin - SetBkColor(wParam, frm_bkg); - result:=hbr; - end; - end; - - WM_CTLCOLORSTATIC: begin - if THANDLE(lParam)=hVolFrmCtrl then - begin - SetBkColor(wParam, frm_bkg); - result:=hbr; - end; - end; - - WM_CONTEXTMENU: begin - CallService(cPluginName + '/Settings',0,0); - end; - - WM_COMMAND: begin - case wParam shr 16 of - - BN_CLICKED: begin - case loword(wParam) of - IDC_RADIO_MUTE: begin - Service_RadioMute(0,1); - end; - end; - end; - end; - end; - - WM_HSCROLL: begin -// gVolume:=SendMessage(lParam,TBM_GETPOS,0,0); - Service_RadioSetVolume(SendMessage(lParam,TBM_GETPOS,0,0){gVolume},2) - end; - - else - result:=DefWindowProc(Dialog,hMessage,wParam,lParam); - end; -end; - -function ColorReload(wParam:WPARAM;lParam:LPARAM):int;cdecl; -var - cid:TColourID; - wnd:HWND; -begin - result:=0; - cid.cbSize:=SizeOf(cid); - StrCopy(cid.group,cPluginName); - StrCopy(cid.name ,frm_back); - frm_bkg:=CallService(MS_COLOUR_GETA,twparam(@cid),0); - if hbr<>0 then DeleteObject(hbr); - hbr:=CreateSolidBrush(frm_bkg); - - wnd:=GetFocus(); - InvalidateRect(hVolFrmCtrl,nil,true); - SetFocus(hVolFrmCtrl); - RedrawWindow(FrameWnd,nil,0,RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_ERASE); - SetFocus(wnd); -end; - -procedure CreateFrame(parent:HWND); -var - Frame:TCLISTFrame; - wnd:HWND; - tmp:cardinal; - tr:TRECT; - cid:TColourID; -begin - if ServiceExists(MS_CLIST_FRAMES_ADDFRAME)=0 then - exit; - if parent=0 then - parent:=CallService(MS_CLUI_GETHWND,0,0); - - if FrameWnd=0 then - FrameWnd:=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_FRAME),parent,@RadioFrameProc); - - if FrameWnd<>0 then - begin - GetWindowRect(FrameWnd,tr); - FillChar(Frame,SizeOf(Frame),0); - with Frame do - begin - cbSize :=SizeOf(Frame); - hWnd :=FrameWnd; - hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnSettings)); - align :=alTop; - height :=tr.bottom-tr.top+2; - Flags :=F_VISIBLE or F_NOBORDER or F_UNICODE; - name.w :=cPluginName; - TBName.w:=cPluginName + ' volume control'; - end; - - FrameId:=CallService(MS_CLIST_FRAMES_ADDFRAME,wparam(@Frame),0); - if FrameId>=0 then - begin - CallService(MS_CLIST_FRAMES_UPDATEFRAME,FrameId, FU_FMPOS); - - wnd:=CallService(MS_CLUI_GETHWND{MS_CLUI_GETHWNDTREE},0,0); - tmp:=SendMessage(wnd,CLM_GETEXSTYLE,0,0); - SendMessage(wnd,CLM_SETEXSTYLE,tmp or CLS_EX_SHOWSELALWAYS,0); - - cid.cbSize:=SizeOf(cid); - cid.flags :=0; - StrCopy(cid.group,cPluginName); - StrCopy(cid.dbSettingsGroup,cPluginName); - - StrCopy(cid.name ,frm_back); - StrCopy(cid.setting,'frame_back'); - cid.defcolour:=COLOR_3DFACE; - cid.order :=0; - ColourRegister(@cid); - - hbr:=0; - colorhook:=HookEvent(ME_COLOUR_RELOAD,@ColorReload); - ColorReload(0,0); - Service_RadioSetVolume(gVolume,0); - end; - end; -end; - -procedure DestroyFrame; -begin - if FrameId>=0 then - begin - UnhookEvent(colorhook); - CallService(MS_CLIST_FRAMES_REMOVEFRAME,FrameId,0); - FrameId:=-1; - end; - DestroyWindow(FrameWnd); - FrameWnd:=0; -end; diff --git a/plugins/mRadio/i_hotkey.inc b/plugins/mRadio/i_hotkey.inc index 380c714623..9fb613fe5f 100644 --- a/plugins/mRadio/i_hotkey.inc +++ b/plugins/mRadio/i_hotkey.inc @@ -52,7 +52,6 @@ begin hkrec.lParam := MRC_MUTE; CallService(MS_HOTKEY_REGISTER,0,lparam(@hkrec)); - //?? hkrec.DefHotKey := DefRadioKeyRecord; hkrec.pszName := HKN_RECORD; hkrec.pszDescription.a:= 'Start/Stop Record'; diff --git a/plugins/mRadio/i_myservice.inc b/plugins/mRadio/i_myservice.inc index d938a08d92..4f50cf573c 100644 --- a/plugins/mRadio/i_myservice.inc +++ b/plugins/mRadio/i_myservice.inc @@ -137,8 +137,147 @@ begin else EQ_OFF; end; - if eq[0].wnd<>0 then // if options opened + if eq[0].wnd<>0 then // if options opened (can use hVolCtrl) begin CheckDlgButton(GetParent(eq[0].wnd),IDC_EQOFF,isEQ_OFF); end; end; + +//----- Import-export ----- + +function ImportOneStation(group:PAnsiChar;section:pointer):int; +var + p:pWideChar; + pc:pAnsiChar; +begin + result:=0; + pc:=GetParamSectionStr(section,'URL'); + if pc<>nil then + begin + result:=CallService(MS_DB_CONTACT_ADD,0,0); + if result<>0 then + begin + CallService(MS_PROTO_ADDTOCONTACT,result,lparam(PluginName)); + DBWriteString(result,PluginName,optStationURL,pc); + DBWriteString(result,PluginName,optFirstName ,pc); + + pc:=GetParamSectionStr(section,optBitrate,'0'); + DBWriteString(result,PluginName,optBitrate,pc); + DBWriteWord (result,PluginName,optAge ,StrToInt(pc)); + + pc:=GetParamSectionStr(section,'Name',GetSectionName(section)); + DBWriteString(result,strCList ,optMyHandle,pc); + DBWriteString(result,PluginName,optNick ,pc); + + pc:=GetParamSectionStr(section,optGenre,'unknown'); + DBWriteString(result,PluginName,optGenre ,pc); + DBWriteString(result,PluginName,optLastName,pc); + + SetStatus(result,ID_STATUS_OFFLINE); + + if group=nil then + group:=GetParamSectionStr(section,optGroup); + + AnsiToWide(group,p,MirandaCP); + CreateGroupW(p,result); + mFreeMem(p); + CallService(MS_IGNORE_IGNORE,result,IGNOREEVENT_ALL); + end; + end; +end; + +function ImportAll(wParam:WPARAM;lParam:LPARAM):int; cdecl; +var + dst:array [0..MAX_PATH-1] of AnsiChar; + pc:pAnsiChar; + lstorage,section,list:pointer; +begin + result:=0; + if lParam<>0 then + StrCopy(dst,PAnsiChar(lParam)); + if (lParam<>0) or ShowDlg(dst,'radio.ini',nil,true) then + begin + lstorage:=OpenStorage(dst); + if lstorage<>nil then + begin + list:=GetSectionList(lstorage); + + pc:=list; + while pc^<>#0 do + begin + section:=SearchSection(lstorage,pc); + if ImportOneStation(pAnsiChar(wParam),section)<>0 then inc(result); + while pc^<>#0 do inc(pc); + inc(pc); + end; + + FreeSectionList(list); + + CloseStorage(lstorage); + end; + end; +end; + +procedure ExportRadioContact(num:integer;fname:PAnsiChar;hContact:THANDLE); +var + pc:pAnsiChar; + section:array [0..15] of AnsiChar; +begin + IntToStr(section,num); + pc:=DBReadString(hContact,strCList,optMyHandle); + WritePrivateProfileStringA(section,'Name',pc,fname); + mFreeMem(pc); + + pc:=DBReadString(hContact,PluginName,optStationURL); + WritePrivateProfileStringA(section,'URL',pc,fname); + mFreeMem(pc); + + pc:=DBReadString(hContact,PluginName,optGenre); + if pc<>nil then + begin + WritePrivateProfileStringA(section,optGenre,pc,fname); + mFreeMem(pc); + end; + + pc:=DBReadString(hContact,PluginName,optBitrate); + if pc<>nil then + begin + WritePrivateProfileStringA(section,optBitrate,pc,fname); + mFreeMem(pc); + end; + + pc:=DBReadString(hContact,strCList,optGroup); + if pc<>nil then + begin + WritePrivateProfileStringA(section,optGroup,pc,fname); + mFreeMem(pc); + end; +end; + +function ExportAll(wParam:WPARAM;lParam:LPARAM):int; cdecl; +var + dst:array [0..MAX_PATH-1] of AnsiChar; + hContact:THANDLE; +begin + result:=0; + if lParam<>0 then + StrCopy(dst,PAnsiChar(lParam)); + if (lParam<>0) or ShowDlg(dst,'radio.ini',nil,false) then + begin + if (wParam<>0) and (CallService(MS_DB_CONTACT_IS,wParam,0)<>0) then + begin + result:=1; + ExportRadioContact(result,dst,wParam) + end + else + begin + hContact:=db_find_first(PluginName); + while hContact<>0 do + begin + inc(result); + ExportRadioContact(result,dst,hContact); + hContact:=db_find_next(hContact,PluginName); + end; + end; + end; +end; diff --git a/plugins/mRadio/i_optdlg.inc b/plugins/mRadio/i_optdlg.inc index 7f1ec138cd..f807d65a22 100644 --- a/plugins/mRadio/i_optdlg.inc +++ b/plugins/mRadio/i_optdlg.inc @@ -1,142 +1,5 @@ {Options dialog} -function ImportOneStation(group:PAnsiChar;section:pointer):int; -var - p:pWideChar; - pc:pAnsiChar; -begin - result:=0; - pc:=GetParamSectionStr(section,'URL'); - if pc<>nil then - begin - result:=CallService(MS_DB_CONTACT_ADD,0,0); - if result<>0 then - begin - CallService(MS_PROTO_ADDTOCONTACT,result,lparam(PluginName)); - DBWriteString(result,PluginName,optStationURL,pc); - DBWriteString(result,PluginName,optFirstName ,pc); - - pc:=GetParamSectionStr(section,optBitrate,'0'); - DBWriteString(result,PluginName,optBitrate,pc); - DBWriteWord (result,PluginName,optAge ,StrToInt(pc)); - - pc:=GetParamSectionStr(section,'Name',GetSectionName(section)); - DBWriteString(result,strCList ,optMyHandle,pc); - DBWriteString(result,PluginName,optNick ,pc); - - pc:=GetParamSectionStr(section,optGenre,'unknown'); - DBWriteString(result,PluginName,optGenre ,pc); - DBWriteString(result,PluginName,optLastName,pc); - - SetStatus(result,ID_STATUS_OFFLINE); - - if group=nil then - group:=GetParamSectionStr(section,optGroup); - - AnsiToWide(group,p,MirandaCP); - CreateGroupW(p,result); - mFreeMem(p); - CallService(MS_IGNORE_IGNORE,result,IGNOREEVENT_ALL); - end; - end; -end; - -function ImportAll(wParam:WPARAM;lParam:LPARAM):int; cdecl; -var - dst:array [0..MAX_PATH-1] of AnsiChar; - pc:pAnsiChar; - lstorage,section,list:pointer; -begin - result:=0; - if lParam<>0 then - StrCopy(dst,PAnsiChar(lParam)); - if (lParam<>0) or ShowDlg(dst,'radio.ini',nil,true) then - begin - lstorage:=OpenStorage(dst); - if lstorage<>nil then - begin - list:=GetSectionList(lstorage); - - pc:=list; - while pc^<>#0 do - begin - section:=SearchSection(lstorage,pc); - if ImportOneStation(pAnsiChar(wParam),section)<>0 then inc(result); - while pc^<>#0 do inc(pc); - inc(pc); - end; - - FreeSectionList(list); - - CloseStorage(lstorage); - end; - end; -end; - -procedure ExportRadioContact(num:integer;fname:PAnsiChar;hContact:THANDLE); -var - pc:pAnsiChar; - section:array [0..15] of AnsiChar; -begin - IntToStr(section,num); - pc:=DBReadString(hContact,strCList,optMyHandle); - WritePrivateProfileStringA(section,'Name',pc,fname); - mFreeMem(pc); - - pc:=DBReadString(hContact,PluginName,optStationURL); - WritePrivateProfileStringA(section,'URL',pc,fname); - mFreeMem(pc); - - pc:=DBReadString(hContact,PluginName,optGenre); - if pc<>nil then - begin - WritePrivateProfileStringA(section,optGenre,pc,fname); - mFreeMem(pc); - end; - - pc:=DBReadString(hContact,PluginName,optBitrate); - if pc<>nil then - begin - WritePrivateProfileStringA(section,optBitrate,pc,fname); - mFreeMem(pc); - end; - - pc:=DBReadString(hContact,strCList,optGroup); - if pc<>nil then - begin - WritePrivateProfileStringA(section,optGroup,pc,fname); - mFreeMem(pc); - end; -end; - -function ExportAll(wParam:WPARAM;lParam:LPARAM):int; cdecl; -var - dst:array [0..MAX_PATH-1] of AnsiChar; - hContact:THANDLE; -begin - result:=0; - if lParam<>0 then - StrCopy(dst,PAnsiChar(lParam)); - if (lParam<>0) or ShowDlg(dst,'radio.ini',nil,false) then - begin - if (wParam<>0) and (CallService(MS_DB_CONTACT_IS,wParam,0)<>0) then - begin - result:=1; - ExportRadioContact(result,dst,wParam) - end - else - begin - hContact:=db_find_first(PluginName); - while hContact<>0 do - begin - inc(result); - ExportRadioContact(result,dst,hContact); - hContact:=db_find_next(hContact,PluginName); - end; - end; - end; -end; - function MakeFilter(dst,descr,full,filter:PWideChar;show:bool=true):pWideChar; var p:PWideChar; @@ -179,19 +42,25 @@ begin pc:=MakeFilter(pc,'Playlist files',full,'*.pls;*.m3u;*.m3u8;*.asx'); pc:=MakeFilter(pc,'BASS built-in' ,full,'*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif'); - ph:=pointer(BASS_PluginGetInfo(0)); - if ph<>nil then + if BassStatus=rbs_null then + MyLoadBass; + + if BassStatus<>rbs_null then begin - while ph^<>0 do + ph:=pointer(BASS_PluginGetInfo(0)); + if ph<>nil then begin - Info:=BASS_PluginGetInfo(ph^); - for i:=0 to Info^.formatc-1 do -//!! need to translate Ansi -> wide - with Info^.Formats[i] do - begin - pc:=MakeFilter(pc,FastAnsiToWideBuf(name,tmpbuf1),full,FastAnsiToWideBuf(exts,tmpbuf2)); - end; - inc(ph); + while ph^<>0 do + begin + Info:=BASS_PluginGetInfo(ph^); + for i:=0 to Info^.formatc-1 do + //!! need to translate Ansi -> wide + with Info^.Formats[i] do + begin + pc:=MakeFilter(pc,FastAnsiToWideBuf(name,tmpbuf1),full,FastAnsiToWideBuf(exts,tmpbuf2)); + end; + inc(ph); + end; end; end; pc:=MakeFilter(pc,'All supported formats',nil,full,false); @@ -241,17 +110,6 @@ var begin result:=0; case hMessage of - WM_DESTROY: begin - DBWriteByte(0,PluginName,optLoop ,doLoop); - DBWriteByte(0,PluginName,optShuffle ,doShuffle); - DBWriteByte(0,PluginName,optContRec ,doContRec); - DBWriteByte(0,PluginName,optPlayFirst,PlayFirst); - DBWriteByte(0,PluginName,optConnect ,AuConnect); - DBWriteByte(0,PluginName,optAutoMute ,AuMute); - DBWriteByte(0,PluginName,optOffline ,AsOffline); - - DBWriteUnicode(0,PluginName,optStatusTmpl,StatusTmpl); - end; WM_INITDIALOG: begin DlgInit:=1; @@ -383,7 +241,7 @@ begin DBWriteUnicode(i,strCList,optGroup,dst) else DBDeleteSetting(i,strCList,optGroup); - + end else if loword(wParam)=IDC_ADD_INI then begin @@ -451,13 +309,6 @@ begin doLoop:=IsDlgButtonChecked(Dialog,IDC_LOOP); if chan<>0 then begin -{ - BASS_ChannelGetInfo(chan,info); - if doLoop<>BST_UNCHECKED then - info.flags:=info.flags or BASS_SAMPLE_LOOP - else - info.flags:=info.flags and not BASS_SAMPLE_LOOP; -} BASS_ChannelFlags(chan,ord(doLoop<>BST_UNCHECKED),BASS_SAMPLE_LOOP); end; @@ -472,7 +323,8 @@ begin end else recpath:=GetDefaultRecPath; - DBWriteUnicode(0,PluginName,optRecPath,recpath); + + SaveCommonSettings; end; end; @@ -483,171 +335,71 @@ end; //----- Tech tab ----- -const - OldEQPreset:integer=-1; -const - optOldPreset:pAnsiChar='oldpreset'; - optPresets :pAnsiChar='numpreset'; - optPreset :pAnsiChar='preset_'; - optPreDescr :pAnsiChar='predescr_'; - -const - PresetMax = 17; - -procedure InitPresets; -type - tP = array [0..9] of AnsiChar; -begin - StrDupW(Presets[00].name,'Acoustic' ); tP(Presets[00].preset):=#$01#$02#$00#$00#$00#$00#$00#$01#$01#$03; - StrDupW(Presets[01].name,'Blues' ); tP(Presets[01].preset):=#$01#$02#$01#$00#$00#$00#$00#$00#$00#$FE; - StrDupW(Presets[02].name,'Classical'); tP(Presets[02].preset):=#$01#$04#$01#$00#$00#$00#$00#$00#$01#$01; - StrDupW(Presets[03].name,'Country' ); tP(Presets[03].preset):=#$00#$00#$01#$01#$00#$00#$01#$01#$01#$01; - StrDupW(Presets[04].name,'Dance' ); tP(Presets[04].preset):=#$04#$03#$02#$01#$FF#$FF#$02#$04#$05#$05; - StrDupW(Presets[05].name,'Folk' ); tP(Presets[05].preset):=#$FF#$00#$00#$01#$01#$00#$01#$01#$01#$00; - StrDupW(Presets[06].name,'Grunge' ); tP(Presets[06].preset):=#$01#$00#$FF#$00#$00#$02#$01#$FF#$FE#$FD; - StrDupW(Presets[07].name,'Jazz' ); tP(Presets[07].preset):=#$00#$01#$02#$03#$03#$01#$01#$03#$04#$05; - StrDupW(Presets[08].name,'Metall' ); tP(Presets[08].preset):=#$FE#$00#$00#$00#$00#$03#$02#$04#$06#$05; - StrDupW(Presets[09].name,'New Age' ); tP(Presets[09].preset):=#$03#$03#$00#$00#$00#$00#$00#$00#$02#$02; - StrDupW(Presets[10].name,'Opera' ); tP(Presets[10].preset):=#$00#$01#$02#$04#$01#$02#$00#$00#$00#$00; - StrDupW(Presets[11].name,'Rap' ); tP(Presets[11].preset):=#$00#$04#$04#$00#$00#$00#$01#$04#$05#$07; - StrDupW(Presets[12].name,'Reggae' ); tP(Presets[12].preset):=#$03#$00#$FD#$00#$05#$00#$02#$03#$04#$05; - StrDupW(Presets[13].name,'Rock' ); tP(Presets[13].preset):=#$00#$02#$04#$00#$00#$00#$02#$04#$05#$06; - StrDupW(Presets[14].name,'Speech' ); tP(Presets[14].preset):=#$FE#$02#$00#$00#$00#$00#$FF#$FE#$FD#$FC; - StrDupW(Presets[15].name,'Swing' ); tP(Presets[15].preset):=#$FF#$00#$00#$02#$02#$00#$02#$02#$03#$03; - StrDupW(Presets[16].name,'Techno' ); tP(Presets[16].preset):=#$05#$08#$FF#$FE#$FD#$FF#$04#$06#$06#$06; -end; - -procedure LoadPresets; -var - num,preset,descr:array [0..63] of AnsiChar; - i:integer; - p,pd:pAnsiChar; -begin - p :=StrCopyE(preset,optPreset); - pd:=StrCopyE(descr ,optPreDescr); - - i:=DBReadByte(0,PluginName,optPresets); - if i=0 then - begin - SetLength(Presets,PresetMax); - InitPresets; - end - else - begin - OldEQPreset:=integer(DBReadByte(0,PluginName,optOldPreset,byte(-1))); - SetLength(Presets,i); - for i:=0 to HIGH(Presets) do - begin - StrCopy(p ,IntToStr(num,i)); DBReadStruct (0,PluginName,preset,@Presets[i].preset,10); - StrCopy(pd,num); Presets[i].name:=DBReadUnicode(0,PluginName,descr); - end; - end; -end; - -procedure SavePresets; -var - num,preset,descr:array [0..63] of AnsiChar; - i,j:integer; - p,pd:pAnsiChar; -begin - p :=StrCopyE(preset,optPreset); - pd:=StrCopyE(descr ,optPreDescr); - j:=DBReadByte(0,PluginName,optPresets); - for i:=0 to HIGH(Presets) do - begin - StrCopy(p ,IntToStr(num,i)); DBWriteStruct (0,PluginName,preset,@Presets[i].preset,10); - StrCopy(pd,num); DBWriteUnicode(0,PluginName,descr ,Presets[i].name); - end; - while j>Length(Presets) do - begin - dec(j); - StrCopy(p ,IntToStr(num,j)); DBDeleteSetting(0,PluginName,preset); - StrCopy(pd,num); DBDeleteSetting(0,PluginName,descr); - end; - DBWriteByte(0,PluginName,optOldPreset,OldEQPreset); - DBWriteByte(0,PluginName,optPresets ,Length(Presets)); -end; - -procedure FreePresets; -var - i:integer; -begin - for i:=0 to HIGH(Presets) do - mFreeMem(Presets[i].name); -end; - procedure FillDeviceCombo(wnd:HWND;choose:pAnsiChar); var i,select,def:integer; info:BASS_DEVICEINFO; buf: array [0..255] of AnsiChar; begin - SendMessage(wnd,CB_RESETCONTENT,0,0); - i:=0; - select:=-1; def:=0; - repeat - if not BASS_GetDeviceInfo(i+1,info) then - break; - if (info.flags and BASS_DEVICE_ENABLED)<>0 then - begin - if (info.flags and BASS_DEVICE_INIT)<>0 then - begin - select:=i; - buf[0]:='>'; - end - else if (info.flags and BASS_DEVICE_DEFAULT)<>0 then - begin - def:=i; - buf[0]:='*'; - end - else buf[0]:=' '; - if select<0 then + SendMessage(wnd,CB_RESETCONTENT,0,0); + if BassStatus<>rbs_null then + begin + i:=0; + select:=-1; + repeat + if not BASS_GetDeviceInfo(i+1,info) then + break; + if (info.flags and BASS_DEVICE_ENABLED)<>0 then begin - if StrCmp(info.name,choose)=0 then + if (info.flags and BASS_DEVICE_INIT)<>0 then + begin select:=i; + buf[0]:='>'; + end + else if (info.flags and BASS_DEVICE_DEFAULT)<>0 then + begin + def:=i; + buf[0]:='*'; + end + else buf[0]:=' '; + if select<0 then + begin + if StrCmp(info.name,choose)=0 then + select:=i; + end; + StrCopy(@buf[1],info.name); + SendMessageA(wnd,CB_ADDSTRING,0,lparam(@buf)); end; - StrCopy(@buf[1],info.name); - SendMessageA(wnd,CB_ADDSTRING,0,lparam(@buf)); - end; - inc(i); - until false; - if select>=0 then - def:=select; + inc(i); + until false; + if select>=0 then + def:=select; + end; SendMessage(wnd,CB_SETCURSEL,def,0); -// not acceptable coz we added 1st char -// SendMessageW(wnd,CB_SELECTSTRING,twparam(-1),tlparam(choose)) end; function DlgProcOptTech(Dialog:HWnd;hMessage:uint;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; const DlgInit:integer=1; var - i:integer; hEAXCombo:THANDLE; ltmp:longbool; -// info:BASS_CHANNELINFO; - buf1:array [0..4] of AnsiChar; wnd:HWND; buf:array [0..MAX_PATH-1] of WideChar; - dst:pWideChar; + dst,old:pWideChar; + device:pAnsiChar; + i,level:integer; begin result:=0; case hMessage of WM_DESTROY: begin hVolCtrl:=0; - buf1[0]:='E'; - buf1[1]:='Q'; - buf1[2]:='_'; - buf1[4]:=#0; for i:=0 to 9 do begin - buf1[3]:=AnsiChar(ORD('0')+i); - DBWriteByte(0,PluginName,buf1,trunc(eq[i].param.fGain)+15); eq[i].wnd:=0; end; - DBWriteByte(0,PluginName,optEQ_OFF ,isEQ_OFF); end; WM_INITDIALOG: begin @@ -672,11 +424,14 @@ begin SendMessageW(hEAXCombo,CB_ADDSTRING,0,tlparam(TranslateW(EAXItems[i].name))); SendMessage(hEAXCombo,CB_SETCURSEL,DBReadByte(0,PluginName,optEAXType,0),0); + if BassStatus=rbs_null then + MyLoadBass; // Fill combo with devices FillDeviceCombo(GetDlgItem(Dialog,IDC_DEVICE),usedevice); // Add preset to combo wnd:=GetDlgItem(Dialog,IDC_PRESET); + for i:=0 to HIGH(Presets) do SendMessageW(wnd,CB_ADDSTRING,0,tlparam(Presets[i].name)); SendMessage(wnd,CB_SETCURSEL,OldEQPreset,0); @@ -709,6 +464,11 @@ begin end; BN_CLICKED: begin + case loword(wParam) of + IDC_EQOFF, IDC_ZERO: + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + case loword(wParam) of IDC_BASSPTHBTN: begin @@ -814,6 +574,7 @@ begin break; end; end; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); end; WM_HSCROLL: begin @@ -824,58 +585,96 @@ begin if integer(PNMHdr(lParam)^.code)=PSN_APPLY then begin SavePresets; + level:=0; - mFreeMem(usedevice); - usedevice:=GetDlgText(Dialog,IDC_DEVICE,true); - StrCopy(usedevice,usedevice+1); - DBWriteString(0,PluginName,optDevice,usedevice); + device:=GetDlgText(Dialog,IDC_DEVICE,true); + StrCopy(device,device+1); + if StrCmp(usedevice,device)<>0 then + begin + level:=1; + mFreeMem(usedevice); + usedevice:=device; + end + else + mFreeMem(device); //!! bass path saving here + old:=DBReadUnicode(0,PluginName,optBASSPath,nil); dst:=GetDlgText(Dialog,IDC_BASSPATH); - DBWriteUnicode(0,PluginName,optBASSPath,dst); + if lstrcmpiw(dst,old)<>0 then + begin + level:=2; + DBWriteUnicode(0,PluginName,optBASSPath,dst); + end; mFreeMem(dst); - - ForcedMono:=IsDlgButtonChecked(Dialog,IDC_MONO); - DBWriteByte(0,PluginName,optForcedMono,ForcedMono); + mFreeMem(old); i:=SendDlgItemMessage(Dialog,IDC_EAXTYPE,CB_GETCURSEL,0,0); DBWriteByte(0,PluginName,optEAXType,i); - if i=0 then - BASS_SetEAXParameters(-1,0,-1,-1) - else - BASS_SetEAXPreset(EAXItems[i].code); - - NumTries:=GetDlgItemInt(Dialog,IDC_TRIES,ltmp,false); - if NumTries<1 then NumTries:=1; - DBWriteByte(0,PluginName,optNumTries,NumTries); - i:=GetDlgItemInt(Dialog,IDC_PREBUF,ltmp,false); - if i>100 then i:=100; - if cardinal(i)<>sPreBuf then +{ + level>0 - need to change + ActiveContact<>0 - need to restart + BassStatus<>rbs_null - need to stop (free, unload) + really, if ActiveContact<>0 then BassStatus<>rbs_null +} + //!!really, need to do it if only active atm + // need to reload dll or change outpout device + // don't change proxy + if level>0 then begin - sPreBuf:=i; - BASS_SetConfig(BASS_CONFIG_NET_PREBUF,i); - DBWriteWord(0,PluginName,optPreBuf,sPreBuf); - end; + ltmp:=ActiveContact<>0; + if ltmp then + CallService(MS_RADIO_COMMAND,MRC_STOP,1); + // save current, stop, bass free - i:=GetDlgItemInt(Dialog,IDC_BUFFER,ltmp,false); - if i>20000 then i:=20000; - if cardinal(i)<>sBuffer then + MyFreeBass; + if level=2 then + begin + MyUnloadBass; + // load dll + if ltmp then + MyLoadBass; + end; + // init device, restore current + if ltmp and (BassStatus=rbs_load) then + begin + MyInitBass; + end; + if ltmp and (BassStatus=rbs_init) then + begin + CallService(MS_RADIO_COMMAND,MRC_PAUSE,0); + end; + end + // if device re-init, EAX settings applied there + else if BassStatus=rbs_init then begin - sBuffer:=i; - BASS_SetConfig(BASS_CONFIG_NET_BUFFER,i); - DBWriteWord(0,PluginName,optBuffer,sBuffer); + if i=0 then + BASS_SetEAXParameters(-1,0,-1,-1) + else + BASS_SetEAXPreset(EAXItems[i].code); end; - i:=GetDlgItemInt(Dialog,IDC_TIMEOUT,ltmp,false); - if i>30000 then i:=30000; - if cardinal(i)<>sTimeout then - begin - sTimeout:=i; - BASS_SetConfig(BASS_CONFIG_NET_TIMEOUT,i); - DBWriteWord(0,PluginName,optTimeout,sTimeout); - end; + ForcedMono:=IsDlgButtonChecked(Dialog,IDC_MONO); + + NumTries:=GetDlgItemInt(Dialog,IDC_TRIES,ltmp,false); + if NumTries<1 then NumTries:=1; + + // Bass config settings + + sPreBuf:=GetDlgItemInt(Dialog,IDC_PREBUF,ltmp,false); + if sPreBuf>100 then sPreBuf:=100; + + sBuffer:=GetDlgItemInt(Dialog,IDC_BUFFER,ltmp,false); + if sBuffer>20000 then sBuffer:=20000; + + sTimeout:=GetDlgItemInt(Dialog,IDC_TIMEOUT,ltmp,false); + if sTimeout>30000 then sTimeout:=30000; + + SetBassConfig; + + SaveTechSettings; end; end; diff --git a/plugins/mRadio/i_service.inc b/plugins/mRadio/i_service.inc index 05072dfd94..fbc644711e 100644 --- a/plugins/mRadio/i_service.inc +++ b/plugins/mRadio/i_service.inc @@ -13,8 +13,8 @@ begin result:=PF4_NOCUSTOMAUTH or PF4_AVATARS; PFLAG_UNIQUEIDTEXT: result:=int_ptr(Translate('Radio station URL')); -// PFLAG_UNIQUEIDSETTING: -// result:=int_ptr(optStationURL) + PFLAG_UNIQUEIDSETTING: + result:=int_ptr(optStationURL) else result:=0; end @@ -53,7 +53,7 @@ begin end; if StrPosW(buf,'%radio_active%')<>nil then begin - StrReplaceW(buf,'%radio_active%',ActiveURLw); + StrReplaceW(buf,'%radio_active%',ActiveURL); end; if StrPosW(buf,'%radio_genre%')<>nil then // saved as String begin @@ -99,7 +99,7 @@ begin if (ccs^.hContact<>0) and (PluginStatus=ID_STATUS_ONLINE) and (DBReadWord(ccs^.hContact,PluginName,optStatus,ID_STATUS_OFFLINE)=ID_STATUS_ONLINE) then begin - mir_forkthread(@GetAwayMsgProc,pointer(ccs^.hContact)); + {CloseHandle}(mir_forkthread(@GetAwayMsgProc,pointer(ccs^.hContact))); result:=AckHandle; end else @@ -134,18 +134,14 @@ begin if wParam=PluginStatus then exit; - mFreeMem(proxy); PluginStatus:=ID_STATUS_OFFLINE; if wParam<>ID_STATUS_OFFLINE then begin - if MyInitBASS<>0 then +// if MyInitBASS then begin PluginStatus:=ID_STATUS_ONLINE; - proxy:=GetProxy(hNetLib); - BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); - if (ActiveContact<>0) and (AuConnect<>0) then CallService(MS_RADIO_COMMAND,MRC_PLAY,ActiveContact); end; @@ -153,13 +149,13 @@ begin else //offline begin CallService(MS_RADIO_COMMAND,MRC_STOP,0); -// StopStation; end; SetStatus(0,ID_STATUS_OFFLINE); ProtoBroadcastAck(PluginName,0,ACKTYPE_STATUS,ACKRESULT_SUCCESS,OldStatus,PluginStatus); end; +// really, can be replaced by helper function. this one more effective function CreateProtoService(serviceName:PAnsiChar;pFunc:pointer):THANDLE; var temp:array [0..MAXMODULELABELLENGTH-1] of AnsiChar; diff --git a/plugins/mRadio/i_tray.inc b/plugins/mRadio/i_tray.inc index f0a463c5de..ab0a04e41d 100644 --- a/plugins/mRadio/i_tray.inc +++ b/plugins/mRadio/i_tray.inc @@ -1,6 +1,9 @@ {} +var + doTray:bool; var trayradioparent:THANDLE; + trayprotoh:THANDLE; trayparent:THANDLE; traymute :THANDLE; trayplay :THANDLE; @@ -79,7 +82,10 @@ begin begin mFreeMem(tmp.name); DestroyServiceFunction(tmp.service); - CallService(MS_CLIST_REMOVETRAYMENUITEM,tmp.menuitem,0); + if doTray then + CallService(MS_CLIST_REMOVETRAYMENUITEM,tmp.menuitem,0) + else + CallService(MS_CLIST_REMOVEMAINMENUITEM,tmp.menuitem,0); mFreeMem(tmp); List_Remove(@trayStations,i); end; @@ -101,7 +107,10 @@ begin mi.position :=i; mi.pszService:=@buf; mi.szName.w :=tmp.name; - tmp.menuitem:=Menu_AddTrayMenuItem(@mi); + if doTray then + tmp.menuitem:=Menu_AddTrayMenuItem(@mi) + else + tmp.menuitem:=Menu_AddMainMenuItem(@mi); end; end; end; @@ -116,6 +125,15 @@ begin result:=CallService(MS_RADIO_COMMAND,MRC_STOP,0); end; +function TrayProto(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl; +begin + if PluginStatus=ID_STATUS_ONLINE then + wParam:=ID_STATUS_OFFLINE + else + wParam:=ID_STATUS_ONLINE; + result:=Service_SetStatus(wParam,lParam); +end; + procedure CreateTrayMenu(); var mi:TCListMenuItem; @@ -126,12 +144,28 @@ begin mi.flags :=CMIF_UNICODE; mi.szName.w:=cPluginName; mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnSettings)); - trayradioparent:=Menu_AddTrayMenuItem(@mi); + if doTray then + trayradioparent:=Menu_AddTrayMenuItem(@mi) + else + trayradioparent:=Menu_AddMainMenuItem(@mi); FillChar(mi, sizeof(mi), 0); mi.cbSize :=sizeof(mi); mi.szPopupName:=TChar(trayradioparent); + if PluginStatus=ID_STATUS_ONLINE then + mi.szName.w :='mRadio off' + else + mi.szName.w :='mRadio on'; + mi.flags:=CMIF_UNICODE or CMIF_ROOTHANDLE; + mi.position :=0; + srvtraystop:=CreateServiceFunction('mRadio/TrayProto',@TrayProto); + mi.pszService:='mRadio/TrayProto'; + if doTray then + trayprotoh:=Menu_AddTrayMenuItem(@mi) + else + trayprotoh:=Menu_AddMainMenuItem(@mi); + if gVolume<0 then mi.flags:=CMIF_UNICODE or CMIF_ROOTHANDLE or CMIF_CHECKED else @@ -139,7 +173,10 @@ begin mi.szName.w :='Mute'; mi.pszService:=MS_RADIO_MUTE; mi.position :=1; - traymute:=Menu_AddTrayMenuItem(@mi); + if doTray then + traymute:=Menu_AddTrayMenuItem(@mi) + else + traymute:=Menu_AddMainMenuItem(@mi); mi.flags:=CMIF_UNICODE or CMIF_ROOTHANDLE; if CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET)<>RD_STATUS_PLAYING then @@ -150,18 +187,27 @@ begin mi.position :=2; srvtrayplaypause:=CreateServiceFunction('mRadio/TrayPlayPause',@TrayPlayPause); mi.pszService:='mRadio/TrayPlayPause'; - trayplay:=Menu_AddTrayMenuItem(@mi); + if doTray then + trayplay:=Menu_AddTrayMenuItem(@mi) + else + trayplay:=Menu_AddTrayMenuItem(@mi); mi.szName.w :='Stop'; mi.position :=3; srvtraystop:=CreateServiceFunction('mRadio/TrayStop',@TrayStop); mi.pszService:='mRadio/TrayStop'; - Menu_AddTrayMenuItem(@mi); + if doTray then + Menu_AddTrayMenuItem(@mi) + else + Menu_AddMainMenuItem(@mi); mi.szName.w :='Play Station'; mi.position :=1000; mi.pszService:=nil; - trayparent:=Menu_AddTrayMenuItem(@mi); + if doTray then + trayparent:=Menu_AddTrayMenuItem(@mi) + else + trayparent:=Menu_AddMainMenuItem(@mi); end; function TrayPrebuild(wParam:WPARAM;lParam:LPARAM):int; cdecl; @@ -171,6 +217,15 @@ var begin FillChar(mi,sizeof(mi),0); mi.cbSize:=sizeof(mi); + + mi.flags:=CMIM_NAME or CMIF_UNICODE; + if PluginStatus=ID_STATUS_ONLINE then + playstr:='mRadio off' + else + playstr:='mRadio on'; + mi.szName.w:=playstr; + CallService(MS_CLIST_MODIFYMENUITEM,trayprotoh,tlparam(@mi)); + if gVolume<0 then mi.flags:=CMIM_FLAGS or CMIF_CHECKED else @@ -191,13 +246,14 @@ end; procedure CreateMIMTrayMenu; begin - if ServiceExists(MS_CLIST_ADDTRAYMENUITEM)<>0 then -// if hiddenwindow<>0 then - begin - CreateTrayMenu(); - MakeStationsMenu(); - HookEvent(ME_CLIST_PREBUILDTRAYMENU,@TrayPrebuild); - end; + doTray:=ServiceExists(MS_CLIST_ADDTRAYMENUITEM)<>0; + + CreateTrayMenu(); + MakeStationsMenu(); + if doTray then + HookEvent(ME_CLIST_PREBUILDTRAYMENU,@TrayPrebuild) + else + HookEvent(ME_CLIST_PREBUILDMAINMENU,@TrayPrebuild) end; procedure RemoveTrayItems; @@ -218,7 +274,8 @@ begin DestroyServiceFunction(srvtrayplaypause); DestroyServiceFunction(srvtraystop); - if ServiceExists(MS_CLIST_REMOVETRAYMENUITEM)<>0 then - CallService(MS_CLIST_REMOVETRAYMENUITEM,trayradioparent,0); - + if doTray then + CallService(MS_CLIST_REMOVETRAYMENUITEM,trayradioparent,0) + else + CallService(MS_CLIST_REMOVEMAINMENUITEM,trayradioparent,0); end; diff --git a/plugins/mRadio/i_variables.inc b/plugins/mRadio/i_variables.inc index fead4afad8..8420510193 100644 --- a/plugins/mRadio/i_variables.inc +++ b/plugins/mRadio/i_variables.inc @@ -35,7 +35,7 @@ begin case i of 0: res:=DBReadUnicode(ActiveContact,strCList ,optMyHandle); 1: res:=DBReadUnicode(ActiveContact,PluginName,optStationURL); - 2: StrDupW(res,ActiveURLw); + 2: StrDupW(res,ActiveURL); 3: res:=DBReadUnicode(ActiveContact,PluginName,optGenre); 4: res:=DBReadUnicode(ActiveContact,PluginName,optBitrate); 5: res:=MakeMessage; diff --git a/plugins/mRadio/i_vars.inc b/plugins/mRadio/i_vars.inc deleted file mode 100644 index 086279d522..0000000000 --- a/plugins/mRadio/i_vars.inc +++ /dev/null @@ -1,162 +0,0 @@ -{used variables} - -{$include m_radio.inc} - -const - optActiveCodec:PAnsiChar = 'ActiveCodec'; - optLastStn :PAnsiChar = 'LastStation'; - optConnect :PAnsiChar = 'AutoConnect'; - optAutoMute :PAnsiChar = 'AutoMute'; - optDevice :PAnsichar = 'Device'; - optEQ_OFF :PAnsiChar = 'eqoff'; - optStatusMsg :PAnsiChar = 'StatusMsg'; - optCurElement :PAnsiChar = 'LastPlayed'; - optPlayFirst :PAnsiChar = 'PlayFromFirst'; - optActiveURL :PAnsiChar = 'ActiveURL'; - optContRec :PAnsiChar = 'ContRec'; - optLoop :PAnsiChar = 'Loop'; - optShuffle :PAnsiChar = 'Shuffle'; - optRecPath :PAnsiChar = 'RecordPath'; - optStatus :PAnsiChar = 'Status'; - optVolume :PAnsiChar = 'Volume'; - optBuffer :PAnsiChar = 'Buffer'; - optPreBuf :PAnsiChar = 'PreBuf'; - optTimeout :PAnsiChar = 'Timeout'; - optVersion :PAnsiChar = 'version'; - optStatusTmpl :PAnsiChar = 'StatusTmpl'; - optNumTries :PAnsiChar = 'NumTries'; - optOffline :PAnsiChar = 'asOffline'; - // mRadio compatibility - optStationURL :PAnsiChar = 'StationURL'; - optMyHandle :PAnsiChar = 'MyHandle'; - optGenre :PAnsiChar = 'Genre'; - optBitrate :PAnsiChar = 'Bitrate'; - // UserInfo compatibility - optFirstName :PAnsiChar = 'FirstName'; - optNick :PAnsiChar = 'Nick'; - optLastName :PAnsiChar = 'LastName'; - optAge :PAnsiChar = 'Age'; - // 3D sound support - optEAXType :PAnsiChar = 'EAXtype'; - optForcedMono :PAnsiChar = 'ForcedMono'; - - optGroup :PAnsiChar = 'Group'; - optBASSPath :PAnsiChar = 'BASSpath'; - optTitle :PAnsiChar = 'Title'; - optArtist :PAnsiChar = 'Artist'; - -var - hhRadioStatus, - hCMenuItemRec, - hCMenuItemPlay, - hNetLib:THANDLE; - hiddenwindow:HWND; -var - plist:tPlaylist; -// plFile:pWideChar; // playlist file name (for delete after using?) -// plLocal:boolean; // true - no need to delete playlist -var - RemoteSong:bool; - gVolume:integer; - NumTries:cardinal; - doLoop:cardinal; - PlayFirst:cardinal; - doShuffle:cardinal; - ForcedMono:cardinal; - doContRec:cardinal; - AuConnect:cardinal; - AuMute:cardinal; - AsOffline:cardinal; - isEQ_OFF:cardinal; - PluginStatus:integer; - storagep,storage:PAnsiChar; - recpath:pWideChar; - sBuffer, - sTimeout, - sPreBuf:cardinal; - usedevice:PAnsiChar; -const - hVolCtrl :HWND=0; - hVolFrmCtrl :HWND=0; -const - hMuteFrmCtrl:HWND=0; -const - Inited:boolean=false; -const - StatusTmpl:pWideChar = nil; - proxy:pAnsiChar = nil; -type - tEQRec = record - fx :HFX; - wnd :HWND; - param :BASS_DX8_PARAMEQ; - text :PAnsiChar; - end; -var - eq:array [0..9] of tEQRec = ( - (fx:0;wnd:0;param:(fCenter:80 ;fBandwidth:18;fGain:0);text:'80'), - (fx:0;wnd:0;param:(fCenter:170 ;fBandwidth:18;fGain:0);text:'170'), - (fx:0;wnd:0;param:(fCenter:310 ;fBandwidth:18;fGain:0);text:'310'), - (fx:0;wnd:0;param:(fCenter:600 ;fBandwidth:18;fGain:0);text:'600'), - (fx:0;wnd:0;param:(fCenter:1000 ;fBandwidth:18;fGain:0);text:'1k'), - (fx:0;wnd:0;param:(fCenter:3000 ;fBandwidth:18;fGain:0);text:'3k'), - (fx:0;wnd:0;param:(fCenter:6000 ;fBandwidth:18;fGain:0);text:'6k'), - (fx:0;wnd:0;param:(fCenter:12000;fBandwidth:18;fGain:0);text:'12k'), - (fx:0;wnd:0;param:(fCenter:14000;fBandwidth:18;fGain:0);text:'14k'), - (fx:0;wnd:0;param:(fCenter:16000;fBandwidth:18;fGain:0);text:'16k')); -const - IcoBtnSettings:PAnsiChar = 'Radio_Setting'; - IcoBtnOn :PAnsiChar = 'Radio_On'; - IcoBtnOff :PAnsiChar = 'Radio_Off'; - IcoBtnRecUp :PAnsiChar = 'Radio_RecUp'; - IcoBtnRecDn :PAnsiChar = 'Radio_RecDn'; - IcoBtnAdd :PAnsiChar = 'Radio_Add'; - IcoBtnDel :PAnsiChar = 'Radio_Del'; -const - hRecord :THANDLE = 0; - chan :HSTREAM = 0; - ActiveContact:THANDLE = 0; - ActiveURLw :PWideChar = nil; - -type - TEAXItem = record - name:PWideChar; - code:dword; - end; -const - EAXItems:array [0..EAX_ENVIRONMENT_COUNT] of TEAXItem=( - (name:'Off' ; code:0), - (name:'Generic' ; code:EAX_ENVIRONMENT_GENERIC), - (name:'Padded Cell' ; code:EAX_ENVIRONMENT_PADDEDCELL), - (name:'Room' ; code:EAX_ENVIRONMENT_ROOM), - (name:'Bathroom' ; code:EAX_ENVIRONMENT_BATHROOM), - (name:'Living Room' ; code:EAX_ENVIRONMENT_LIVINGROOM), - (name:'Stone Room' ; code:EAX_ENVIRONMENT_STONEROOM), - (name:'Auditorium' ; code:EAX_ENVIRONMENT_AUDITORIUM), - (name:'Concert Hall' ; code:EAX_ENVIRONMENT_CONCERTHALL), - (name:'Cave' ; code:EAX_ENVIRONMENT_CAVE), - (name:'Arena' ; code:EAX_ENVIRONMENT_ARENA), - (name:'Hangar' ; code:EAX_ENVIRONMENT_HANGAR), - (name:'Carpeted Hallway'; code:EAX_ENVIRONMENT_CARPETEDHALLWAY), - (name:'Hallway' ; code:EAX_ENVIRONMENT_HALLWAY), - (name:'Stone Corridor' ; code:EAX_ENVIRONMENT_STONECORRIDOR), - (name:'Alley' ; code:EAX_ENVIRONMENT_ALLEY), - (name:'Forrest' ; code:EAX_ENVIRONMENT_FOREST), - (name:'City' ; code:EAX_ENVIRONMENT_CITY), - (name:'Mountains' ; code:EAX_ENVIRONMENT_MOUNTAINS), - (name:'Quarry' ; code:EAX_ENVIRONMENT_QUARRY), - (name:'Plain' ; code:EAX_ENVIRONMENT_PLAIN), - (name:'Parking Lot' ; code:EAX_ENVIRONMENT_PARKINGLOT), - (name:'Sewer Pipe' ; code:EAX_ENVIRONMENT_SEWERPIPE), - (name:'Under Water' ; code:EAX_ENVIRONMENT_UNDERWATER), - (name:'Drugged' ; code:EAX_ENVIRONMENT_DRUGGED), - (name:'Dizzy' ; code:EAX_ENVIRONMENT_DIZZY), - (name:'Psychotic' ; code:EAX_ENVIRONMENT_PSYCHOTIC)); - -type - tPreset = record - name :PWideChar; - preset:array [0..9] of shortint; - end; -var - Presets: array of tPreset; diff --git a/plugins/mRadio/i_visual.inc b/plugins/mRadio/i_visual.inc index 77012b55f2..3c0b56ebb2 100644 --- a/plugins/mRadio/i_visual.inc +++ b/plugins/mRadio/i_visual.inc @@ -1,4 +1,8 @@ {Visual part} +var + hCMenuItemRec, + hCMenuItemPlay:THANDLE; + function OnContactMenu(hContact:WPARAM;lParam:LPARAM):int;cdecl; var mi:TCListMenuItem; diff --git a/plugins/mRadio/mradio.dpr b/plugins/mRadio/mradio.dpr index 4cf4aa75b5..9600988e0d 100644 --- a/plugins/mRadio/mradio.dpr +++ b/plugins/mRadio/mradio.dpr @@ -11,100 +11,18 @@ uses // FastMM4, Windows,messages,commctrl ,common,io,wrapper,wrapdlgs,syswin - ,Dynamic_Bass,dynbasswma - ,m_api,dbsettings,mirutils,playlist,memini; + ,Dynamic_Bass + ,m_api,dbsettings,mirutils,memini, + rbass,rglobal,rccenter,rframeapi,roptions; {$include mr_rc.inc} {$r mradio.res} -{$include i_vars.inc} - -const - cPluginName = 'mRadio'; -const - PluginName:PAnsiChar = cPluginName; - -function MakeMessage:pWideChar; -var - p,artist,title:pWideChar; - len:cardinal; -begin - artist:=DBReadUnicode(0,PluginName,optArtist); - title :=DBReadUnicode(0,PluginName,optTitle); - len:=StrLenW(artist); - if (artist<>nil) and (title<>nil) then - inc(len,3); - inc(len,StrLenW(title)); - - if len>0 then - begin - mGetMem(result,(len+1)*SizeOf(WideChar)); - p:=result; - if artist<>nil then - begin - p:=StrCopyEW(p,artist); - if title<>nil then - p:=StrCopyEW(p,' - '); - mFreeMem(artist); - end; - if title<>nil then - begin - StrCopyW(p,title); - mFreeMem(title); - end; - end - else - result:=nil; -end; - -procedure SetStatus(hContact:THANDLE;status:integer); -begin -// if Status=ID_STATUS_OFFLINE then -// MyStopBass; - - if status=ID_STATUS_OFFLINE then - begin - if (AsOffline=BST_UNCHECKED) or (PluginStatus<>ID_STATUS_OFFLINE) then - status:=ID_STATUS_INVISIBLE; - end; - - if hContact=0 then - begin - hContact:=db_find_first(PluginName); - while hContact<>0 do - begin - DBWriteWord(hContact,PluginName,optStatus,status); - hContact:=db_find_next(hContact,PluginName); - end; - end - else - DBWriteWord(hContact,PluginName,optStatus,status); -end; - -function GetDefaultRecPath:pWideChar; -var - dat:TREPLACEVARSDATA; - mstr,szData:pWideChar; - buf:array [0..MAX_PATH-1] of WideChar; -begin - FillChar(dat,SizeOf(dat),0); - dat.cbSize :=SizeOf(TREPLACEVARSDATA); - dat.dwFlags:=RVF_UNICODE; - szData:='%miranda_userdata%'+'\'+cPluginName; - mstr:=pWideChar(CallService(MS_UTILS_REPLACEVARS, WPARAM(szData), LPARAM(@dat))); - PathToRelativeW(mstr,buf); - StrDupW(result,buf); - mir_free(mstr); -end; - {$include i_search.inc} -{$include i_bass.inc} -{$include i_cc.inc} {$include i_variables.inc} {$include i_service.inc} {$include i_myservice.inc} {$include i_hotkey.inc} -{$include i_frameapi.inc} {$include i_tray.inc} {$include i_visual.inc} {$include i_optdlg.inc} @@ -114,12 +32,12 @@ begin result:=@PluginInfo; PluginInfo.cbSize :=SizeOf(TPLUGININFOEX); PluginInfo.shortName :='mRadio Mod'; - PluginInfo.version :=$00000203; + PluginInfo.version :=$00000204; PluginInfo.description:='This plugin plays and records Internet radio streams.'+ ' Also local media files can be played.'; PluginInfo.author :='Awkward'; PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru'; - PluginInfo.copyright :='(c) 2007-2013 Awkward'; + PluginInfo.copyright :='(c) 2007-2014 Awkward'; PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/'; PluginInfo.flags :=UNICODE_AWARE; PluginInfo.uuid :=MIID_MRADIO; @@ -128,26 +46,35 @@ end; function OnModulesLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; var nlu:TNETLIBUSER; - szTemp:array [0..255] of AnsiChar; - i:integer; + buf:array [0..MAX_PATH-1] of WideChar; + szTemp:array [0..255] of AnsiChar absolute buf; + pc:pWideChar; begin - DBWriteDWord(0,PluginName,optVersion,PluginInfo.version); + // buf = miranda directory + // must be same as %miranda_path% of MS_UTILS_REPLACEVARS - szTemp[0]:='E'; - szTemp[1]:='Q'; - szTemp[2]:='_'; - szTemp[4]:=#0; - for i:=0 to 9 do - begin - szTemp[3]:=AnsiChar(ORD('0')+i); - eq[i].param.fGain:=DBReadByte(0,PluginName,szTemp,15)-15; - end; - LoadPresets; + GetModuleFileNameW(0,buf,MAX_PATH-1); + pc:=StrEndW(buf); + repeat + dec(pc); + until pc^='\'; + inc(pc); + pc^:=#0; + + // INI file path + StrCopyW(pc,'plugins\mradio.ini'); + FastWideToAnsi(buf,storage); + mGetMem(storagep,MAX_PATH+32); + CallService(MS_DB_GETPROFILEPATH,MAX_PATH-1,tlparam(storagep)); + StrCat(storagep,'\mradio.ini'); + + DBWriteDWord(0,PluginName,optVersion,PluginInfo.version); //?? RegisterIcons; CreateMenu; CreateMIMTrayMenu; + //-- network (for proxy) FillChar(nlu,SizeOf(nlu),0); StrCopy(szTemp,Translate('%s server connection')); StrReplace(szTemp,'%s',PluginName); @@ -159,51 +86,17 @@ begin // CallService(MS_RADIO_COMMAND,MRC_RECORD,2); record off - not so necessary - recpath:=DBReadUnicode(0,PluginName,optRecPath); - if (recpath=nil) or (recpath^=#0) then - begin - recpath:=GetDefaultRecPath; - end; - - usedevice:=DBReadString(0,PluginName,optDevice); - - sPreBuf:=DBReadWord(0,PluginName,optPreBuf,75); - BASS_SetConfig(BASS_CONFIG_NET_PREBUF,sPreBuf); - - sBuffer:=DBReadWord(0,PluginName,optBuffer,5000); - BASS_SetConfig(BASS_CONFIG_NET_BUFFER,sBuffer); - - sTimeout:=DBReadWord(0,PluginName,optTimeout,5000); - BASS_SetConfig(BASS_CONFIG_NET_TIMEOUT,sTimeout); - - doLoop :=DBReadByte(0,PluginName,optLoop); - doShuffle :=DBReadByte(0,PluginName,optShuffle); - doContRec :=DBReadByte(0,PluginName,optContRec); - PlayFirst :=DBReadByte(0,PluginName,optPlayFirst); - isEQ_OFF :=DBReadByte(0,PluginName,optEQ_OFF); - AuConnect :=DBReadByte(0,PluginName,optConnect); - AuMute :=DBReadByte(0,PluginName,optAutoMute); - AsOffline :=DBReadByte(0,PluginName,optOffline); - gVolume :=DBReadByte(0,PluginName,optVolume,50); - NumTries :=DBReadByte(0,PluginName,optNumTries,1); - ForcedMono:=DBReadByte(0,PluginName,optForcedMono); - if NumTries<1 then NumTries:=1; + LoadPresets; + LoadSettings; SetStatus(0,ID_STATUS_OFFLINE); - StatusTmpl:=DBReadUnicode(0,PluginName,optStatusTmpl,'%radio_title%'); - CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_NOSTATION); IsMultiThread:=true; RegisterVariables; - if AuConnect<>BST_UNCHECKED then - ActiveContact:=LoadContact(PluginName,optLastStn) - else - ActiveContact:=0; - HookEvent(ME_DB_CONTACT_SETTINGCHANGED,@OnSettingsChanged); HookEvent(ME_DB_CONTACT_DELETED ,@OnContactDeleted); randomize; @@ -229,22 +122,21 @@ begin UnregisterHotKey; DestroyProtoServices; - DestroyWindow(hiddenwindow); DestroyFrame(); - MyFreeBASS; + + MyUnloadBass; + DBWriteByte(0,PluginName,optVolume,gVolume); DestroyHookableEvent(hhRadioStatus); - CallService(MS_NETLIB_CLOSEHANDLE,hNetLib,0); + mFreeMem(storage); mFreeMem(storagep); - mFreeMem(recpath); - mFreeMem(usedevice); - mFreeMem(StatusTmpl); - mFreeMem(basspath); + FreePresets; + FreeSettings; { //delete cover files buf[0]:=#0; @@ -268,71 +160,49 @@ end; function Load(): int; cdecl; var desc:TPROTOCOLDESCRIPTOR; - szTemp:array [0..MAX_PATH-1] of WideChar; - pc:pWideChar; - custom:pWideChar; begin Langpack_register; - GetModuleFileNameW(0,szTemp,MAX_PATH-1); - pc:=StrEndW(szTemp); - repeat - dec(pc); - until pc^='\'; - inc(pc); - pc^:=#0; + // register protocol + FillChar(desc,SizeOf(desc),0); + desc.cbSize:=PROTOCOLDESCRIPTOR_V3_SIZE;//SizeOf(desc); + desc.szName:=PluginName; + desc._type :=PROTOTYPE_VIRTUAL; + CallService(MS_PROTO_REGISTERMODULE,0,lparam(@desc)); - custom:=DBReadUnicode(0,PluginName,optBASSPath,nil); + // hooks and services + hhRadioStatus:=CreateHookableEvent(ME_RADIO_STATUS); + + CreateServiceFunction(MS_RADIO_PLAYSTOP,@Service_RadioPlayStop); + CreateServiceFunction(MS_RADIO_RECORD ,@Service_RadioRecord); + CreateServiceFunction(MS_RADIO_SETTINGS,@Service_RadioSettings); + CreateServiceFunction(MS_RADIO_SETVOL ,@Service_RadioSetVolume); + CreateServiceFunction(MS_RADIO_GETVOL ,@Service_RadioGetVolume); + CreateServiceFunction(MS_RADIO_MUTE ,@Service_RadioMute); + CreateServiceFunction(MS_RADIO_COMMAND ,@ControlCenter); + CreateServiceFunction(MS_RADIO_EQONOFF ,@Service_EqOnOff); + + CreateServiceFunction(MS_RADIO_TRAYMENU,@CreateTrayMenu); + + CreateServiceFunction(MS_RADIO_EXPORT ,@ExportAll); + CreateServiceFunction(MS_RADIO_IMPORT ,@ImportAll); + + + CreateProtoServices; + + HookEvent(ME_SYSTEM_MODULESLOADED ,@OnModulesLoaded); + HookEvent(ME_SYSTEM_OKTOEXIT ,@PreShutdown); + HookEvent(ME_CLIST_DOUBLECLICKED ,@Service_RadioPlayStop{@DblClickProc}); + HookEvent(ME_OPT_INITIALISE ,@OnOptInitialise); + HookEvent(ME_CLIST_PREBUILDCONTACTMENU,@OnContactMenu); + + PluginStatus:=ID_STATUS_OFFLINE; - if MyLoadBASS(szTemp,custom) then - begin - StrCopyW(pc,'plugins\mradio.ini'); -// StrDup(storage,szTemp); - FastWideToAnsi(szTemp,storage); - mGetMem(storagep,MAX_PATH+32); - CallService(MS_DB_GETPROFILEPATH,MAX_PATH-1,lparam(storagep)); - StrCat(storagep,'\mradio.ini'); - - FillChar(desc,SizeOf(desc),0); - desc.cbSize:=PROTOCOLDESCRIPTOR_V3_SIZE;//SizeOf(desc); - desc.szName:=PluginName; - desc._type :=PROTOTYPE_VIRTUAL; - CallService(MS_PROTO_REGISTERMODULE,0,lparam(@desc)); - - hhRadioStatus:=CreateHookableEvent(ME_RADIO_STATUS); - - CreateServiceFunction(MS_RADIO_PLAYSTOP,@Service_RadioPlayStop); - CreateServiceFunction(MS_RADIO_RECORD ,@Service_RadioRecord); - CreateServiceFunction(MS_RADIO_SETTINGS,@Service_RadioSettings); - CreateServiceFunction(MS_RADIO_SETVOL ,@Service_RadioSetVolume); - CreateServiceFunction(MS_RADIO_GETVOL ,@Service_RadioGetVolume); - CreateServiceFunction(MS_RADIO_MUTE ,@Service_RadioMute); - CreateServiceFunction(MS_RADIO_COMMAND ,@ControlCenter); - CreateServiceFunction(MS_RADIO_EQONOFF ,@Service_EqOnOff); - - hiddenwindow:=CreateHiddenWindow; - CreateServiceFunction(MS_RADIO_TRAYMENU,@CreateTrayMenu); - - CreateServiceFunction(MS_RADIO_EXPORT ,@ExportAll); - CreateServiceFunction(MS_RADIO_IMPORT ,@ImportAll); - - - CreateProtoServices; - HookEvent(ME_SYSTEM_MODULESLOADED ,@OnModulesLoaded); - HookEvent(ME_SYSTEM_OKTOEXIT ,@PreShutdown); - HookEvent(ME_CLIST_DOUBLECLICKED ,@Service_RadioPlayStop{@DblClickProc}); - HookEvent(ME_OPT_INITIALISE ,@OnOptInitialise); - HookEvent(ME_CLIST_PREBUILDCONTACTMENU,@OnContactMenu); - - PluginStatus:=ID_STATUS_OFFLINE; - end; - mFreeMem(custom); Result:=0; end; function Unload: int; cdecl; begin - Unload_BASSDLL; Result:=0; end; diff --git a/plugins/mRadio/rbass.pas b/plugins/mRadio/rbass.pas new file mode 100644 index 0000000000..91728b4d32 --- /dev/null +++ b/plugins/mRadio/rbass.pas @@ -0,0 +1,1106 @@ +{BASS dll code} +unit rbass; + +interface + +uses + windows; + +procedure BassError(text:PWideChar); +procedure OpenURL(url:PWideChar); cdecl; +procedure StopStation; +function GetMusicFormat:PAnsiChar; + +procedure EQ_ON; +procedure EQ_OFF; +procedure SetSndVol(arg:integer); +procedure SetBassConfig; + +procedure MyFreeBASS; +function MyInitBASS:bool; +procedure MyUnloadBass; +function MyLoadBASS:bool; +function CheckBassStatus:bool; + +implementation + +uses + common, m_api, io + ,dbsettings, mirutils, wrapdlgs + ,Dynamic_Bass,dynbasswma + ,rglobal + ; + +const + signMP3 = $FBFF; + signID3 = $00334449; + signOGG = $5367674F; + OGGHdrSize = 26; // +1=NumSegments +const + BASSName = 'bass.dll'; + StationHeader:PByte=nil; +var + hdrlen:integer; + syncMETA, + syncOGG, + syncWMA, + syncWMA1, + syncEND:HSYNC; + SaveHeader:bool; + +const + hRecord:THANDLE = 0; + +procedure BassError(text:PWideChar); +begin + MessageboxW(0,TranslateW(text),TranslateW('Sorry!'),MB_ICONERROR) +end; + +// now called from BASS_Init only, so no dll load check +procedure ErrorCustom(text:pWideChar=nil); +var + buf:array [0..255] of WideChar; + pcw:pWideChar; + idx:integer; +begin + idx:=BASS_ErrorGetCode(); + if (idx<0) or (idx>BASS_ERROR_MAXNUMBER) then + begin + if text=nil then + pcw:='Unknown error' + else + pcw:=text; + end + else + pcw:=FastAnsiToWideBuf(BASS_ERRORS[idx],@buf); + + MessageBoxW(0,TranslateW(pcw), + TranslateW('Oops! BASS error'),MB_ICONERROR) +end; + + + +procedure SetBassConfig; +begin + if BassStatus=rbs_null then exit; + + BASS_SetConfig(BASS_CONFIG_NET_PREBUF ,sPreBuf); + BASS_SetConfig(BASS_CONFIG_NET_BUFFER ,sBuffer); + BASS_SetConfig(BASS_CONFIG_NET_TIMEOUT,sTimeout); +end; + +procedure SetSndVol(arg:integer); +begin + if arg<0 then + arg:=gVolume + else + gVolume:=arg; + + // no BASS dll - no channel + if chan<>0 then + begin + if arg<0 then arg:=0; + BASS_ChannelSetAttribute(chan,BASS_ATTRIB_VOL,arg/100); + end; +end; + +procedure EQ_OFF; +var + i:cardinal; +begin + // no BASS dll - no channel + if chan<>0 then + for i:=0 to 9 do + BASS_ChannelRemoveFX(chan,eq[i].fx); + isEQ_OFF:=BST_CHECKED; +end; + +procedure EQ_ON; +var + i:cardinal; +begin + // no BASS dll - no channel + if chan<>0 then + begin + for i:=0 to 9 do + eq[i].fx:=BASS_ChannelSetFX(chan,BASS_FX_DX8_PARAMEQ,1); + for i:=0 to 9 do + BASS_FXSetParameters(eq[i].fx,@eq[i].param); + isEQ_OFF:=BST_UNCHECKED; + end; +end; + + + +procedure MyStopBASS; +begin + if BassStatus=rbs_null then exit; + + if ActiveContact<>0 then + begin + if syncMETA<>0 then + begin + BASS_ChannelRemoveSync(chan,syncMETA); + syncMETA:=0 + end; + if syncEND<>0 then + begin + BASS_ChannelRemoveSync(chan,syncEND); + syncEND:=0 + end; + if syncWMA<>0 then + begin + BASS_ChannelRemoveSync(chan,syncWMA); + syncWMA:=0 + end; + if syncOGG<>0 then + begin + BASS_ChannelRemoveSync(chan,syncOGG); + syncOGG:=0 + end; + if syncWMA1<>0 then + begin + BASS_ChannelRemoveSync(chan,syncWMA1); + syncWMA1:=0 + end; + end; +end; + +procedure MyFreeBASS; +begin + if BassStatus=rbs_init then + begin + MyStopBASS; + BASS_Free; + + BassStatus:=rbs_load; + end; +end; + +procedure StopStation; +begin + if chan<>0 then + BASS_StreamFree(chan); // close old stream + chan:=0; + mFreeMem(StationHeader); + mFreeMem(ActiveURL); + DBDeleteSetting(ActiveContact,strCList,optStatusMsg); + MyStopBASS; +end; + +function GetDeviceNumber:integer; +var + i:integer; + info:BASS_DEVICEINFO; +begin + // default device + result:=-1; + i:=1; // 0 is always the "no sound" device + repeat + if not BASS_GetDeviceInfo(i,info) then + break; + if (info.flags and BASS_DEVICE_ENABLED)<>0 then + if StrCmp(info.name,usedevice)=0 then + begin + // not default device + if (info.flags and BASS_DEVICE_DEFAULT)=0 then + result:=i; + break; + end; + inc(i); + until false; +end; + +function MyInitBASS:bool; +var + num:integer; +begin + if BassSTatus=rbs_null then + begin + result:=false; + exit; + // or can do this: + MyLoadBass; + if BassSTatus=rbs_null then + begin + result:=false; + exit; + end; + end; + + if BassStatus=rbs_init then + begin + result:=true; + exit; + end; + + num:=GetDeviceNumber; + result:=BASS_Init(num,44100,BASS_DEVICE_3D,0,nil); + if not result then + result:=BASS_Init(num,44100,0,0,nil); + // not default device choosed - check default now + if (not result) and (num>=0) then + begin + result:=BASS_Init(-1,44100,BASS_DEVICE_3D,0,nil); + if not result then + result:=BASS_Init(-1,44100,0,0,nil); + end; + + if not result then + begin + ErrorCustom('Can''t initialize device'); + end + else + begin + num:=DBReadByte(0,PluginName,optEAXType,0); + if num=0 then + BASS_SetEAXParameters(-1,0,-1,-1) + else + BASS_SetEAXPreset(EAXItems[num].code); + end; + + if result then + BassStatus:=rbs_init; +end; + +procedure MyUnloadBass; +begin + MyFreeBASS; + if BassStatus=rbs_load then + begin + BASS_PluginFree(0); + Unload_BASSDLL; + + BassStatus:=rbs_null; + end; +end; + +function MyLoadBASS:bool; +var + pc,custom:PWideChar; + basspath:PWideChar; + buf:array [0..MAX_PATH-1] of WideChar; + fh:THANDLE; + fd:TWin32FindDataW; +begin + if BassStatus<>rbs_null then + begin + result:=true; + exit; + end; + + mGetMem(basspath,1024); + + // trying to load Bass.dll from custom + custom:=DBReadUnicode(0,PluginName,optBASSPath,nil); + if custom<>nil then + begin + pc:=StrCopyEW(basspath,custom); + if (pc-1)^<>'\' then + begin + pc^:='\'; + inc(pc); + end; + StrCopyW(pc,BASSName); + + result:=Load_BASSDLL(basspath); + end + else + result:=false; + + if not result then + begin + GetModuleFileNameW(0,buf,MAX_PATH-1); + pc:=StrEndW(buf); + repeat + dec(pc); + until pc^='\'; + inc(pc); + pc^:=#0; + + pc:=StrCopyW(StrCopyEW(basspath,buf),BASSName); // %miranda_path%\ + result:=Load_BASSDLL(basspath); + if not result then + begin + pc:=StrCopyW(StrCopyEW(pc,'plugins\'),BASSName); // %miranda_path%\plugins\ + result:=Load_BASSDLL(basspath); + if not result then + begin + pc:=StrCopyW(StrCopyEW(pc,'bass\'),BASSName); // %miranda_path%\plugins\bass\ + result:=Load_BASSDLL(basspath); + end; + end; + end; + + // not found but custom path is empty + if (not result) and (custom=nil) then + begin + if MessageboxW(0,TranslateW('BASS.DLL not found! Choose BASS.dll path manually'), + cPluginName,MB_YESNO)=IDYES then + begin + pc:=nil; + if SelectDirectory(TranslateW('Choose BASS.dll path'),pc,0) then + begin + //!! if options page opened, need to change edit field + + PathToRelativeW(pc,buf); + pc:=StrCopyEW(basspath,buf); + if (pc-1)^<>'\' then + begin + pc^:='\'; + inc(pc); + end; + pc^:=#0; + DBWriteUnicode(0,PluginName,optBASSPath,basspath); + StrCopyW(pc,BASSName); + + result:=Load_BASSDLL(basspath); + end; + end; + end; + + // check Bass.dll version + if result then + begin + if (BASS_GetVersion shr 16)THANDLE(INVALID_HANDLE_VALUE) then + begin + repeat + StrCopyW(pc,fd.cFileName); + if BASS_PluginLoad(pAnsiChar(basspath),BASS_UNICODE)=0 then + until not FindNextFileW(fh,fd); + FindClose(fh); + end; + + // enable ASX processing (if WMA loaded) + BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST, 2); // 2 - enable internet and local playlists + end; + end + else + begin + BassError('BASS.DLL not found!'); + end; + + mFreeMem(custom); + mFreeMem(basspath); + + if result then + BassStatus:=rbs_load; +end; + +function CheckBassStatus:bool; +var + proxy:pAnsiChar; +begin + if BassStatus=rbs_null then + MyLoadBass; + + if BassStatus<>rbs_null then + begin + SetBassConfig; + + proxy:=GetProxy(hNetLib); + BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); + mFreeMem(proxy); + end; + + if BassStatus=rbs_load then + MyInitBass; + + result:=BassStatus<>rbs_null; +end; + +function GetMusicFormat:PAnsiChar; +var + bci:BASS_CHANNELINFO; +begin + BASS_ChannelGetInfo(chan,bci); + case bci.ctype of + BASS_CTYPE_STREAM_OGG: result:='OGG'; + BASS_CTYPE_STREAM_MP1, + BASS_CTYPE_STREAM_MP2, + BASS_CTYPE_STREAM_MP3: result:='MP3'; + BASS_CTYPE_STREAM_WMA, + BASS_CTYPE_STREAM_WMA_MP3: result:='WMA'; + {BASS_CTYPE_STREAM_AAC,}$10b00: result:='AAC'; + {BASS_CTYPE_STREAM_MP4:}$10b01: result:='MP4'; + {BASS_CTYPE_STREAM_AC3:}$11000: result:='AC3'; + else + result:=nil; + end; +end; + +function GetFileExt(buf:pWideChar;sign:pointer):pWideChar; +var + pc:pAnsiChar; +begin + result:=buf; + pc:=GetMusicFormat; + if pc=nil then + begin + StrCopyW(buf,'sav'); + if sign<>nil then + begin + if pdword(sign)^=signOGG then + StrCopyW(buf,'ogg') + else if ((pdword(sign)^ and $00FFFFFF)=signID3) or (pword(sign)^=signMP3) then + StrCopyW(buf,'mp3'); + end; + end + else + begin + FastAnsiToWideBuf(pc,buf); + LowerCase(buf); + end; +end; + +function MakeFileName(sign:pointer):pWideChar; +var + p,pcw:PWideChar; + buf:pWideChar; +begin +// allocate buffer + mGetMem(buf,MAX_PATH*SizeOf(WideChar)); +// path + if recpath<>nil then + begin + ConvertFileName(recpath,buf,ActiveContact); +// pcw:=ParseVarString(recpath,ActiveContact); +// CallService(MS_UTILS_PATHTOABSOLUTEW,WPARAM(pcw),LPARAM(buf)); +// mFreeMem(pcw); + if not ForceDirectories(buf) then + begin + result:=nil; + exit; + end; + pcw:=StrEndW(buf); + if (pcw-1)^<>'\' then + begin + pcw^:='\'; + inc(pcw); + end; + end + else + pcw:=buf; +// name +//!! + p:=MakeMessage; + pcw:=StrCopyEW(pcw,p); + mFreeMem(p); + if (pcw=buf) or ((pcw-1)^='\') then + pcw:=StrEndW(IntToHex(pcw,GetCurrentTime)); +// ext + pcw^:='.'; inc(pcw); + GetFileExt(pcw,sign); + + result:=buf; +end; + + + +procedure StatusProc(buffer:Pointer;len,user:DWORD); stdcall; +var + pc:pWideChar; + pb:PByte; + i,sum:integer; + flag:bool; + doRecord:bool; +begin + flag:=true; + doRecord:=CallService(MS_RADIO_COMMAND,MRC_RECORD,LPARAM(-1))<>0; + if (buffer<>nil) and (len<>0) and SaveHeader then + begin + SaveHeader:=false; + if pdword(buffer)^=signOGG then // if header ALL in buffer + begin + pb:=buffer; + flag:=false; + repeat + inc(pb,OGGHdrSize); + i:=pb^; //patterns + sum:=0; + inc(pb); + while i>0 do + begin + inc(sum,pb^); + inc(pb); + dec(i); + end; + inc(pb,sum); //here must be next sign + flag:=not flag; + until not flag; + hdrlen:=PAnsiChar(pb)-PAnsiChar(buffer); + mGetMem(StationHeader,hdrlen); + move(buffer^,StationHeader^,hdrlen); + end; + end; + if (buffer=nil) or not doRecord then // end of stream or stop record + begin + if not doRecord or (doContRec=BST_UNCHECKED) then + if hRecord<>0 then + begin + if buffer<>nil then // write tail + BlockWrite(hRecord,buffer^,len); + CloseHandle(hRecord); + hRecord:=0; + end; + end + else + begin + if len=0 then // HTTP or ICY tags + begin +{ +while PAnsiChar(buffer)^<>#0 do +begin +messagebox(0,PAnsiChar(buffer),'ICY-HTTP',0); +while PAnsiChar(buffer)^<>#0 do inc(PAnsiChar(buffer)); inc(PAnsiChar(buffer)); +end; +} + end + else + begin + if doRecord then + begin + if hRecord=0 then + begin + pc:=MakeFileName(StationHeader); + if pc<>nil then + hRecord:=Rewrite(pc) + else + hRecord:=THANDLE(INVALID_HANDLE_VALUE); + if hRecord=THANDLE(INVALID_HANDLE_VALUE) then + hRecord:=0 + else if flag and (StationHeader<>nil) then + begin + BlockWrite(hRecord,StationHeader^,hdrlen); +// permissible to skip to the next Page (OggS) but this is not necessary + end; + mFreeMem(pc); + end; + if hRecord<>0 then + BlockWrite(hRecord,buffer^,len); + end; + end; + end; +end; + +{$IFDEF Debug} +procedure logmeta(tag,a,b:pansiChar); +var + f:thandle; + p:pansichar; +begin + f:=Append(pansichar('mradio.log')); + BlockWrite(f,tag^,StrLen(tag)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + BlockWrite(f,a^,StrLen(a)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + BlockWrite(f,b^,StrLen(b)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + CloseHandle(f); +end; +{$ENDIF} + +function DoMeta(meta:PAnsiChar;TagType:int_ptr):Boolean; +var + pcw:pWideChar; + buf:array [0..511] of AnsiChar; + artist,title:PAnsiChar; + oldartist,oldtitle:pAnsiChar; + ppc,pc:pAnsiChar; + idx,lcp:integer; + needtofree:Boolean; + CurDescrW:PWideChar; + old:boolean; + +// tag:PAnsiChar; + gotartist,gottitle:boolean; // indicate what we got artist/title +begin + result:=false; + + if meta=nil then + meta:=BASS_ChannelGetTags(chan,TagType); + if meta<>nil then + begin + // for cases when artist or title presents but empty + gotartist:=false; + gottitle :=false; + needtofree:=false; + lcp:=CP_UTF8; + buf[0]:=#0; + artist:=nil; + title :=nil; + CurDescrW:=nil; + +//tag:=meta; + case TagType of + BASS_TAG_WMA_META: begin + pc:=StrPos(meta,'data='); + if pc=meta then + begin + pc:=StrPos(meta,'artist='); + if pc<>nil then + begin + gotartist:=true; + mGetMem(artist,256); + Decode(artist,pc+7); + end; + + pc:=StrPos(meta,'title='); + if pc<>nil then + begin + gottitle:=true; + mGetMem(title,256); + Decode(title,pc+6); + end; + + pc:=StrPos(meta,'album='); + if pc<>nil then + begin + end; + + pc:=StrPos(meta,'duration='); + if pc<>nil then + begin + end; + + if not gotartist then + begin + if not gottitle then + begin + pc:=StrPos(meta,'caption='); + if pc<>nil then + begin + gottitle:=true; + mGetMem(title,256); + Decode(title,pc+8); + end; + end; + + // analize title/caption for artist-title + if gottitle then + begin + pc:=StrPos(title,' - '); + if pc=nil then + pc:=StrScan(title,'-'); + if pc<>nil then + begin + artist:=title; + if pc^=' ' then + title:=pc+3 + else + title:=pc+1; + pc^:=#0; + CurDescrW:=pWideChar(artist); + end + else + CurDescrW:=pWideChar(title); + end; + end + else + needtofree:=true; + + // to avoid mem leak and wrong tag process + result:=true; + end; + StatusProc(nil,0,0); // split records here + end; + + BASS_TAG_META: begin +//tag:='SHOUTCAST'; + // SHOUTCAST StreamTitle='xxx';StreamUrl='xxx'; + // "Station=xyz" meta tag="Trackinfo" + pc:=StrPos(meta,'StreamTitle='); + if pc<>nil then + begin + inc(pc,13); + ppc:=StrScan(pc,';'); + if (ppc-pc-1)>0 then + begin + StrCopy(buf,pc,ppc-pc-1); + lcp:=GetTextFormat(@buf,ppc-pc-1); + end; + end; + if buf[0]<>#0 then + begin + case lcp of + CP_UTF8: UTF8ToWide(buf,CurDescrW); + CP_ACP : AnsiToWide(buf,CurDescrW,MirandaCP); + end; + end; + + gottitle:=true; + title:=pAnsiChar(CurDescrW); + pcw:=StrPosW(CurDescrW,' - '); + if pcw=nil then + pcw:=StrScanW(CurDescrW,'-'); + if pcw<>nil then + begin + artist:=pAnsiChar(CurDescrW); + if pcw^=' ' then + title:=pAnsiChar(pcw+3) + else + title:=pAnsiChar(pcw+1); + pcw^:=#0; + end; + + lcp:=CP_UNICODE; + + StatusProc(nil,0,0); // split records here + result:=true; + end; + + BASS_TAG_ID3: begin // not realized, anyway - at the end of track + end; + + BASS_TAG_ID3V2: begin + end; + + BASS_TAG_APE, // not sure, need to check. maybe better process BASS_TAG_APEBINARY + BASS_TAG_WMA, + BASS_TAG_OGG: begin +//tag:='OGG'; + while meta^<>#0 do + begin + CharLowerA(StrCopy(buf,meta,10)); + if StrCmp(buf,'title',5)=0 then + begin + title:=meta+6; + gottitle:=true; + end + else if StrCmp(buf,'artist',6)=0 then + begin + artist:=meta+7; + gotartist:=true; + end; + if gotartist and gottitle then + break; + while meta^<>#0 do inc(meta); inc(meta); + end; + + if (not gotartist) and gottitle then + begin + pc:=StrPos(title,' - '); + if pc=nil then + pc:=StrScan(title,'-'); + if pc<>nil then + begin + needtofree:=true; + StrDup(artist,title,pc-title); + if pc^=' ' then + idx:=3 + else + idx:=1; + StrDup(title,pc+idx); + end; + end; + buf[0]:=#0; + end; + end; + + old:=true; + if gotartist or gottitle then + begin + // check for old + oldartist:=nil; + oldtitle :=nil; + case lcp of + CP_UTF8: begin + if gotartist then + begin + oldartist:=DBReadUTF8(0,PluginName,optArtist); + if StrCmp(artist,oldartist)<>0 then + old:=false; + end; + + if old and gottitle then + begin + oldtitle:=DBReadUTF8(0,PluginName,optTitle); + if StrCmp(title,oldtitle)<>0 then + old:=false; + end; + + if not old then + begin + DBWriteUTF8(0,PluginName,optArtist,artist); + DBWriteUTF8(0,PluginName,optTitle ,title); + end; + end; + + CP_UNICODE:begin + if gotartist then + begin + oldartist:=pAnsiChar(DBReadUnicode(0,PluginName,optArtist)); + if StrCmpW(pWideChar(artist),pWideChar(oldartist))<>0 then + old:=false; + end; + + if old and gottitle then + begin + oldtitle:=pAnsiChar(DBReadUnicode(0,PluginName,optTitle)); + if StrCmpW(pWideChar(title),pWideChar(oldtitle))<>0 then + old:=false; + end; + + if not old then + begin + DBWriteUnicode(0,PluginName,optArtist,pWideChar(artist)); + DBWriteUnicode(0,PluginName,optTitle ,pWideChar(title)); + end; + end; + end; +{$IFDEF Debug} +//logmeta(tag,artist,title); +{$ENDIF} + mFreeMem(oldartist); + mFreeMem(oldtitle); + mFreeMem(CurDescrW); + if needtofree then + begin + mFreeMem(artist); + mFreeMem(title ); + end; + end; + + if not old then + CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_NEWTAG); + end; +end; + +procedure MetaSync(handle:HSYNC;channel,data:dword;user:pointer); stdcall; +//var tagtype:Integer; +begin +(* + if handle=syncOGG then tagtype:=BASS_TAG_OGG + else if handle=syncWMA then tagtype:=BASS_TAG_WMA + else if handle=syncWMA1 then tagtype:=BASS_TAG_WMA_META + else {if handle=syncMETA then} tagtype:=BASS_TAG_META; +*) + DoMeta(nil{PAnsiChar(data)},int_ptr(user){tagtype}); +end; + +procedure EndSync(handle:HSYNC;channel,data:dword;user:pointer); stdcall; +var + lContact:cardinal; +begin + if RemoteSong then + begin + lContact:=ActiveContact; + CallService(MS_RADIO_COMMAND,MRC_STOP,0); + CallService(MS_RADIO_COMMAND,MRC_PLAY,lContact) + end + else if plist<>nil then CallService(MS_RADIO_COMMAND,MRC_NEXT,0) + else if doLoop=BST_UNCHECKED then CallService(MS_RADIO_COMMAND,MRC_STOP,0); +end; + +type + tICYField = record + name :PAnsiChar; + branch:PAnsiChar; + option:PAnsiChar; + end; +const + NumICYFields = 4; + ICYFields: array [0..NumICYFields-1] of tICYField = ( + (name:'icy-name:' ; branch:'CList' ; option:'MyHandle'), + (name:'icy-genre:' ; branch:cPluginName ; option:'Genre'), + (name:'icy-br:' ; branch:cPluginName ; option:'Bitrate'), + (name:'icy-description'; branch:cPluginName ; option:'About') + ); + +procedure ProcessStationData; +var + icy:PAnsiChar; + i,len:integer; +begin + // get the broadcast name and bitrate + icy:=BASS_ChannelGetTags(chan,BASS_TAG_ICY); + if icy=nil then + icy:=BASS_ChannelGetTags(chan,BASS_TAG_HTTP); // no ICY tags, try HTTP + if icy<>nil then + begin + while icy^<>#0 do + begin + for i:=0 to NumICYFields-1 do + begin + with ICYFields[i] do + begin + len:=StrLen(name); + if StrCmp(icy,name,len)=0 then + begin + if DBReadStringLength(ActiveContact,branch,option)=0 then + DBWriteString(ActiveContact,branch,option,icy+len); + break; + end; + end; + end; + while icy^<>#0 do inc(icy); inc(icy); + end; + end; +end; + +procedure OpenURL(url:PWideChar); cdecl; +var + len,progress:DWORD; + flags:dword; + i:integer; + EAXUsed:bool; + ansiurl:array [0..511] of AnsiChar; +begin + if not CheckBassStatus then exit; + if BassStatus<>rbs_init then exit; //!! check for record + + if plist=nil then + CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_CONNECT); + + EAXUsed:=DBReadByte(0,PluginName,optEAXType,0)<>0; + +{} + for i:=0 to NumTries-1 do + begin + if EAXUsed then + flags:=BASS_STREAM_STATUS or BASS_SAMPLE_3D or BASS_SAMPLE_MONO + else + begin + if ForcedMono<>BST_UNCHECKED then + flags:=BASS_STREAM_STATUS or BASS_SAMPLE_MONO + else + flags:=BASS_STREAM_STATUS; + end; + + flags:=flags or BASS_UNICODE; + if RemoteSong then + begin + SaveHeader:=true; + chan:=BASS_StreamCreateURL(url,0,flags,@StatusProc,nil) + end + else + begin + if (plist=nil) and (doLoop<>BST_UNCHECKED) then + flags:=flags or BASS_SAMPLE_LOOP; + chan:=BASS_StreamCreateFile(FALSE,url,0,0,flags); + end; + + if (chan=0) and EAXUsed then + begin + flags:=flags and not (BASS_SAMPLE_3D or BASS_SAMPLE_MONO); + if ForcedMono<>BST_UNCHECKED then + flags:=flags or BASS_SAMPLE_MONO; + + if RemoteSong then + chan:=BASS_StreamCreateURL({ansi}url,0,flags,@StatusProc,nil) + else + chan:=BASS_StreamCreateFile(FALSE,url,0,0,flags); + end; + + if (chan=0) and RemoteSong then + begin + if BASS_ErrorGetCode=BASS_ERROR_FILEOPEN then + begin + flags:=flags and not BASS_UNICODE; + chan:=BASS_StreamCreateURL(FastWideToAnsiBuf(url,ansiurl),0,flags,@StatusProc,nil) + end; + end; + + if chan<>0 then break; + end; +{} + + if chan=0 then + begin + if (CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET)=RD_STATUS_ABORT) or + (plist=nil) then + begin + CallService(MS_RADIO_COMMAND,MRC_STOP,1); + end + else if plist<>nil then + CallService(MS_RADIO_COMMAND,MRC_NEXT,0); + end + else + begin + + CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_NEWTRACK); + + if RemoteSong then + begin + if isEQ_OFF=BST_UNCHECKED then + EQ_ON; + +{$IFDEF CHANGE_NAME_BUFFERED} + icy:=DBReadString(ActiveContact,strCList,optMyHandle); + mGetMem(url,StrLen(icy)+6); + StrCopy(url+6,icy); + mFreeMem(icy); + url[0]:='['; + url[1]:=#0; + url[4]:=']'; + url[5]:=' '; +{$ENDIF} + progress:=0; + repeat + if CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET)=RD_STATUS_ABORT then + begin + CallService(MS_RADIO_COMMAND,MRC_STOP,1); + exit; + end; + len:=BASS_StreamGetFilePosition(chan,BASS_FILEPOS_END); + if len=DW_ERROR then + break; + progress:=BASS_StreamGetFilePosition(chan, BASS_FILEPOS_DOWNLOAD); + if progress=dword(-1) then + break; + progress:=(progress- + BASS_StreamGetFilePosition(chan,BASS_FILEPOS_CURRENT))*100 div len; + // percentage of buffer filled +{$IFDEF CHANGE_NAME_BUFFERED} + IntToStr(url+1,progress,2); + url[3]:='%'; + DBWriteString(ActiveContact,strCList,optMyHandle,url); +{$ENDIF} + until progress>sPreBuf; +{$IFDEF CHANGE_NAME_BUFFERED} + if url[1]<>#0 then + DBWriteString(ActiveContact,strCList,optMyHandle,url+6); + mFreeMem(url); +{$ENDIF} + + ProcessStationData; // process ICY-headers + + // get the stream title and set sync for subsequent titles + DoMeta(nil,BASS_TAG_META); + + syncMETA:=BASS_ChannelSetSync(chan,BASS_SYNC_META ,0,@MetaSync,pointer(BASS_TAG_META)); + syncOGG :=BASS_ChannelSetSync(chan,BASS_SYNC_OGG_CHANGE,0,@MetaSync,pointer(BASS_TAG_OGG)); + syncWMA :=BASS_ChannelSetSync(chan,BASS_SYNC_WMA_CHANGE,0,@MetaSync,pointer(BASS_TAG_WMA)); + syncWMA1:=BASS_ChannelSetSync(chan,BASS_SYNC_WMA_META ,0,@MetaSync,pointer(BASS_TAG_WMA_META)); + end + else + begin + if not DoMeta(nil,BASS_TAG_OGG) then + if not DoMeta(nil,BASS_TAG_ID3V2) then + if not DoMeta(nil,BASS_TAG_ID3) then + if not DoMeta(nil,BASS_TAG_APE) then + ; + + end; + + syncEND:=BASS_ChannelSetSync(chan,BASS_SYNC_END,0,@EndSync,nil); + + SetSndVol(-1); + // play it! + BASS_ChannelPlay(chan,FALSE); + end; +end; + +end. diff --git a/plugins/mRadio/rccenter.pas b/plugins/mRadio/rccenter.pas new file mode 100644 index 0000000000..6f75ef48ae --- /dev/null +++ b/plugins/mRadio/rccenter.pas @@ -0,0 +1,443 @@ +{} +unit rccenter; + +interface + +uses + windows; + +function ControlCenter(code:WPARAM;arg:LPARAM):int_ptr; cdecl; + +implementation + +uses + common, m_api, + dbsettings, playlist, mirutils, + rglobal, rbass, + Dynamic_Bass, + syswin; + +const + optCurElement :PAnsiChar = 'LastPlayed'; + optActiveURL :PAnsiChar = 'ActiveURL'; // center + +procedure ConstructMsg(artist,title:PWideChar;status:integer=-1); +var + buf:PWideChar; + tstrlen,astrlen,statuslen:integer; + sstatus:PWideChar; + p:pWideChar; +begin + astrlen:=StrLenW(artist); + + tstrlen:=0; + // if need to remove duplicate + if (title<>nil) and (title^<>#0) then + begin + if (astrlen=0) or (StrCmpW(artist,title)<>0) then + tstrlen:=StrLenW(title); + end; + if (astrlen>0) and (tstrlen>0) then + inc(tstrlen,3); + + statuslen:=0; + if status>=0 then + begin + sstatus:=TranslateW(GetStatusText(status,true)); + if sstatus<>nil then + statuslen:=StrLenW(sstatus)+3; + end + else + sstatus:=nil; + + if (astrlen+tstrlen+statuslen)>0 then + begin + mGetMem(buf,(astrlen+tstrlen+statuslen+1)*SizeOf(WideChar)); + p:=buf; + if astrlen>0 then + p:=StrCopyEW(p,artist); + + if tstrlen>0 then + begin + if astrlen>0 then + begin + p^:=' '; inc(p); + p^:='-'; inc(p); + p^:=' '; inc(p); + end; + p:=StrCopyEW(p,title); + end; + + if statuslen>0 then + begin + p^:=' '; inc(p); + p^:='('; inc(p); + p:=StrCopyEW(p,sstatus); + p^:=')'; inc(p); + p^:=#0; + end; + + DBWriteUnicode(ActiveContact,strCList,optStatusMsg,buf); + mFreeMem(buf); + end + else + DBDeleteSetting(ActiveContact,strCList,optStatusMsg); +end; + +{$IFDEF Debug} +procedure log(a,b:lparam); +var + f:thandle; + buf:array [0..31] of ansichar; + p:pansichar; +begin + f:=Append(pansichar('mradio.log')); + p:=IntToStr(buf,a); BlockWrite(f,p^,StrLen(p)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + p:=IntToStr(buf,b); BlockWrite(f,p^,StrLen(p)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + p:=#13#10; BlockWrite(f,p^,StrLen(p)); + CloseHandle(f); +end; +{$ENDIF} + +function ControlCenter(code:WPARAM;arg:LPARAM):int_ptr; cdecl; +const + PlayStatus:int_ptr=RD_STATUS_NOSTATION; + doRecord:boolean=false; +var + tmpbuf,buf1:array [0..MAX_PATH-1] of WideChar; + plFile:pWideChar; + plLocal:boolean; + artist,title:pWideChar; +begin + result:=0; +{$IFDEF Debug} + log(code,arg); +{$ENDIF} + case code of + MRC_PLAY : begin + // play new station? + if arg<>0 then + begin + ActiveURL:=DBReadUnicode(arg,PluginName,optStationURL); + // no URL for this contact + if (ActiveURL=nil) or (ActiveURL^=#0) then exit; + + ActiveContact:=arg; + RemoteSong:=StrPosW(ActiveURL,'://')<>nil; + + if isPlaylist(ActiveURL)<>0 then + begin + + if RemoteSong then + begin + GetTempPathW(MAX_PATH,tmpbuf); + GetTempFileNameW(tmpbuf,'mr',GetCurrentTime,buf1); + if not GetFile(ActiveURL,buf1,hNetLib) then + begin + exit; + end; + plFile:=@buf1; + plLocal:=false; + end + else + begin + plFile:=ActiveURL; + plLocal:=true; + end; + + plist:=CreatePlaylist(plFile); + if not plLocal then + DeleteFileW(plFile); + + if plist<>nil then + begin + if plist.GetCount=0 then + begin + plist.Free; + plist:=nil; + ActiveContact:=0; + exit; + end; + plist.Shuffle:=doShuffle<>BST_UNCHECKED; + + if not plist.Shuffle then + begin + if PlayFirst=BST_UNCHECKED then + plist.Track:=DBReadWord(ActiveContact,PluginName,optCurElement); + end; + + mFreeMem(ActiveURL); + ActiveURL:=plist.GetSong; + end; + RemoteSong:=StrPosW(ActiveURL,'://')<>nil; // coz ActiveURL can be changed + end + else + plist:=nil; + + if (ActiveURL<>nil) and (ActiveURL^<>#0) then + begin + if RemoteSong then + begin + if GetWorkOfflineStatus<>0 then + begin + BassError('Can''t connect to net. Please, clear ''Work offline'' option in Internet settings'); + ControlCenter(MRC_STATUS,RD_STATUS_NOSTATION); + exit; + end; + end; + ControlCenter(MRC_STATUS,RD_STATUS_NEWSTATION); + if Assigned(plist) then + ControlCenter(MRC_STATUS,RD_STATUS_CONNECT); + {CloseHandle}(mir_forkthread(@OpenURL,ActiveURL)); + end; + end + // play current from start + else if chan<>0 then + begin + BASS_ChannelPlay(chan,true); + code:=MRC_STATUS; + arg :=RD_STATUS_PLAYING; + end + // play playlist entry? + else if Assigned(plist) and (ActiveURL<>nil) and (ActiveURL^<>#0) then + begin + {CloseHandle}(mir_forkthread(@OpenURL,ActiveURL)); + end; + end; + + MRC_RECORD: begin + if arg=LPARAM(-1) then + result:=ord(doRecord) + else + begin + case arg of + 1: doRecord:=true; // force start + 2: doRecord:=false; // force stop + else + doRecord:=not doRecord; + end; + result:=ord(doRecord); + + code:=MRC_STATUS; + arg :=RD_STATUS_RECORD+(result shl 16); + end; + end; + + MRC_PAUSE: begin + if chan<>0 then + begin + case ControlCenter(MRC_STATUS,RD_STATUS_GET) of + RD_STATUS_PLAYING: begin + BASS_ChannelPause(chan); + arg:=1; + end; + RD_STATUS_PAUSED: begin + BASS_ChannelPlay(chan,false); + arg:=0; + end; + end; + code:=MRC_STATUS; + arg :=RD_STATUS_PAUSED+(arg shl 16); + end + else + begin + ActiveContact:=LoadContact(PluginName,optLastStn); + if ActiveContact<>0 then + ControlCenter(MRC_PLAY,ActiveContact); + end; + end; + + MRC_STOP: begin + ControlCenter(MRC_RECORD,2); + + code:=MRC_STATUS; + // stop playlist track but not station + if Assigned(plist) and (arg=0) then + begin + if chan<>0 then + BASS_ChannelStop(chan); + + arg:=RD_STATUS_STOPPED; + end + else // forced or "normal" stop + begin + if Assigned(plist) then + begin + DBWriteWord(ActiveContact,PluginName,optCurElement,plist.Track); + plist.Free; + plist:=nil; + end; + ControlCenter(MRC_STATUS,RD_STATUS_STOPPED); + // Save station for next autoplay + SaveContact(ActiveContact,PluginName,optLastStn); + StopStation; + + arg:=RD_STATUS_NOSTATION; + end; + end; + + MRC_MUTE: begin + CallService(MS_RADIO_MUTE,0,arg); + code:=MRC_STATUS; + arg :=RD_STATUS_MUTED; + end; + + MRC_NEXT: begin + if Assigned(plist) then + begin + StopStation; + ActiveURL:=plist.Next; + ControlCenter(MRC_PLAY,0); + end; + end; + + MRC_PREV: begin + if Assigned(plist) then + begin + StopStation; + ActiveURL:=plist.Previous; + ControlCenter(MRC_PLAY,0) + end; + end; + + MRC_SEEK: begin + if not RemoteSong and (chan<>0) then + begin + if integer(arg)=-1 then // get position + begin + result:=trunc(BASS_ChannelBytes2Seconds(chan,BASS_ChannelGetPosition(chan,BASS_POS_BYTE))); + if result<0 then + result:=0; + end + else + begin + BASS_ChannelSetPosition(chan,BASS_ChannelSeconds2Bytes(chan,arg),BASS_POS_BYTE); + + code:=MRC_STATUS; + arg :=RD_STATUS_POSITION+(arg shl 16); + end; + end; + end; + end; + + if code=MRC_STATUS then + begin + if arg=RD_STATUS_GET then + result:=PlayStatus + else + begin + + code:=(arg and $FFFF); + arg :=hiword(arg); + // this is just events + case code of + RD_STATUS_MUTED: begin + end; + + RD_STATUS_RECORD: begin + end; + + RD_STATUS_POSITION: begin + end; + + else + // these statuses are for events and some tasks + artist:=nil; + title :=nil; + case code of + RD_STATUS_NOSTATION: begin + SetStatus(ActiveContact,ID_STATUS_OFFLINE); + ActiveContact:=0; + + DBDeleteSetting(0,PluginName,optActiveURL); + + PlayStatus:=RD_STATUS_NOSTATION; + // empty message + end; + + RD_STATUS_STOPPED: begin + if ActiveContact<>0 then //!! fools proof + DBDeleteSetting(ActiveContact,strCList,optStatusMsg); + + DBDeleteSetting(0,PluginName,optTitle); + DBDeleteSetting(0,PluginName,optArtist); + + PlayStatus:=RD_STATUS_STOPPED; + // empty message + end; + + RD_STATUS_ABORT: begin + PlayStatus:=RD_STATUS_ABORT; + // status as message + end; + + RD_STATUS_CONNECT: begin + SetStatus(ActiveContact,ID_STATUS_AWAY); + PlayStatus:=RD_STATUS_CONNECT; + // status as message + end; + + RD_STATUS_NEWSTATION: begin + arg:=ActiveContact; + PlayStatus:=RD_STATUS_PLAYING; + end; + + RD_STATUS_NEWTRACK: begin + SetStatus(ActiveContact,ID_STATUS_ONLINE); + DBWriteUnicode(0,PluginName,optActiveURL,ActiveURL); + + DBWriteString(0,PluginName,optActiveCodec,GetMusicFormat); + arg :=lparam(ActiveURL); + + // for case when tags was in meta + artist:=DBReadUnicode(0,PluginName,optArtist); + title :=DBReadUnicode(0,PluginName,optTitle); + PlayStatus:=RD_STATUS_PLAYING; + // status as message + end; + + RD_STATUS_NEWTAG: begin + // must be updated tags + artist:=DBReadUnicode(0,PluginName,optArtist); + title :=DBReadUnicode(0,PluginName,optTitle); + + PlayStatus:=RD_STATUS_PLAYING; // maybe keep RD_STATUS_NEWTAG? + end; + + RD_STATUS_PLAYING: begin + SetStatus(ActiveContact,ID_STATUS_ONLINE); + PlayStatus:=RD_STATUS_PLAYING; + // status as message + end; + + RD_STATUS_PAUSED: begin + if arg=0 then + begin + PlayStatus:=RD_STATUS_PLAYING; + if StrPosW(ActiveURL,'://')=nil then //local only + begin + artist:=DBReadUnicode(0,PluginName,optArtist); + title :=DBReadUnicode(0,PluginName,optTitle); + end; + end + else + PlayStatus:=RD_STATUS_PAUSED; + // status as message + end; + else + exit; + end; + ConstructMsg(artist,title,PlayStatus); + mFreeMem(artist); + mFreeMem(title); + end; + + NotifyEventHooks(hhRadioStatus,code,arg); + end; + + end; +end; + +end. diff --git a/plugins/mRadio/rframeapi.pas b/plugins/mRadio/rframeapi.pas new file mode 100644 index 0000000000..0aba02c517 --- /dev/null +++ b/plugins/mRadio/rframeapi.pas @@ -0,0 +1,266 @@ +{mRadio frame} +unit rframeapi; + +interface + +uses + windows; + +const + hVolFrmCtrl:HWND=0; + +procedure CreateFrame(parent:HWND); +procedure DestroyFrame; + +implementation + +uses + messages,commctrl, + m_api,common, + rglobal; + +{$include mr_rc.inc} + +const + frm_back:pAnsiChar = 'Frame background'; +const + FrameWnd:HWND = 0; + FrameId:integer = -1; +var + colorhook:THANDLE; + hbr:HBRUSH; + frm_bkg:TCOLORREF; + OldSliderWndProc:pointer; + +function QSDlgResizer(Dialog:HWND;lParam:LPARAM;urc:PUTILRESIZECONTROL):int; cdecl; +begin + case urc^.wId of + IDC_RADIO_MUTE: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_CENTRE; + IDC_RADIO_VOL : result:=RD_ANCHORX_WIDTH or RD_ANCHORY_CENTRE; + else + result:=0; + end; +end; + +function SliderWndProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +begin + if hMessage=WM_ERASEBKGND then + result:=1 + else + result:=CallWindowProc(OldSliderWndProc, Dialog, hMessage, wParam, lParam); +end; + +procedure MakeTooltip(Dialog:HWND); +var + hwndTooltip:HWND; + ti:TTOOLINFOW; +begin + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + Dialog,0,hInstance,nil); + + FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TOOLINFO); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=Dialog; + ti.hinst :=hInstance; + ti.uId :=GetDlgItem(Dialog,IDC_RADIO_MUTE); + ti.lpszText:=pWideChar(TranslateW('Mute')); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); +end; + +function RadioFrameProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + urd:TUTILRESIZEDIALOG; + rc:TRECT; + tmp:pAnsiChar; +begin + result:=0; + case hMessage of + WM_DESTROY: begin + hVolFrmCtrl :=0; + DeleteObject(hbr); + end; + + WM_INITDIALOG: begin + SendDlgItemMessage(Dialog,IDC_RADIO_MUTE, BUTTONSETASFLATBTN,0,0); +// SetButtonIcon(hMuteFrmCtrl,IcoBtnOn); + + MakeTooltip(Dialog); + + hVolFrmCtrl:=GetDlgItem(Dialog,IDC_RADIO_VOL); + SendMessage(hVolFrmCtrl,TBM_SETRANGE,0,MAKELONG(0,100)); + SendMessage(hVolFrmCtrl,TBM_SETPAGESIZE,0,20); + SendMessage(hVolFrmCtrl,TBM_SETPOS,1,gVolume); + + OldSliderWndProc:=pointer(SetWindowLongPtrW(hVolFrmCtrl,GWL_WNDPROC,LONG_PTR(@SliderWndProc))); + end; + + WM_SIZE: begin + FillChar(urd,SizeOf(TUTILRESIZEDIALOG),0); + urd.cbSize :=SizeOf(urd); + urd.hwndDlg :=Dialog; + urd.hInstance :=hInstance; + urd.lpTemplate:=MAKEINTRESOURCEA(IDD_FRAME); + urd.lParam :=0; + urd.pfnResizer:=@QSDlgResizer; + CallService(MS_UTILS_RESIZEDIALOG,0,tlparam(@urd)); + end; + + WM_ERASEBKGND: begin + GetClientRect(Dialog,rc); + FillRect(wParam,rc,hbr); + result:=1; + end; + + WM_DRAWITEM: begin + if wParam=IDC_RADIO_MUTE then + begin + result:=1; + if gVolume<0 then + tmp:=IcoBtnOff + else + tmp:=IcoBtnOn; + DrawIconEx(PDRAWITEMSTRUCT(lParam)^.hDC,0,0, + CallService(MS_SKIN2_GETICON,0,TLPARAM(tmp)), + 16,16,0,hbr,DI_NORMAL); + end; + end; + + WM_CTLCOLORBTN: begin + if THANDLE(lParam)=GetDlgItem(Dialog,IDC_RADIO_MUTE) then + begin + SetBkColor(wParam, frm_bkg); + result:=hbr; + end; + end; + + WM_CTLCOLORSTATIC: begin + if THANDLE(lParam)=hVolFrmCtrl then + begin + SetBkColor(wParam, frm_bkg); + result:=hbr; + end; + end; + + WM_CONTEXTMENU: begin + CallService(cPluginName + '/Settings',0,0); + end; + + WM_COMMAND: begin + case wParam shr 16 of + + BN_CLICKED: begin + case loword(wParam) of + IDC_RADIO_MUTE: begin + CallService(MS_RADIO_MUTE,0,1); + end; + end; + end; + end; + end; + + WM_HSCROLL: begin +// gVolume:=SendMessage(lParam,TBM_GETPOS,0,0); + CallService(MS_RADIO_SETVOL,SendMessage(lParam,TBM_GETPOS,0,0){gVolume},2) + end; + + else + result:=DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; + +function ColorReload(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + cid:TColourID; + wnd:HWND; +begin + result:=0; + cid.cbSize:=SizeOf(cid); + StrCopy(cid.group,cPluginName); + StrCopy(cid.name ,frm_back); + frm_bkg:=CallService(MS_COLOUR_GETA,twparam(@cid),0); + if hbr<>0 then DeleteObject(hbr); + hbr:=CreateSolidBrush(frm_bkg); + + wnd:=GetFocus(); + InvalidateRect(hVolFrmCtrl,nil,true); + SetFocus(hVolFrmCtrl); + RedrawWindow(FrameWnd,nil,0,RDW_INVALIDATE or RDW_ALLCHILDREN or RDW_ERASE); + SetFocus(wnd); +end; + +procedure CreateFrame(parent:HWND); +var + Frame:TCLISTFrame; + wnd:HWND; + tmp:cardinal; + tr:TRECT; + cid:TColourID; +begin + if ServiceExists(MS_CLIST_FRAMES_ADDFRAME)=0 then + exit; + if parent=0 then + parent:=CallService(MS_CLUI_GETHWND,0,0); + + if FrameWnd=0 then + FrameWnd:=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_FRAME),parent,@RadioFrameProc); + + if FrameWnd<>0 then + begin + GetWindowRect(FrameWnd,tr); + FillChar(Frame,SizeOf(Frame),0); + with Frame do + begin + cbSize :=SizeOf(Frame); + hWnd :=FrameWnd; + hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnSettings)); + align :=alTop; + height :=tr.bottom-tr.top+2; + Flags :=F_VISIBLE or F_NOBORDER or F_UNICODE; + name.w :=cPluginName; + TBName.w:=cPluginName + ' volume control'; + end; + + FrameId:=CallService(MS_CLIST_FRAMES_ADDFRAME,wparam(@Frame),0); + if FrameId>=0 then + begin + CallService(MS_CLIST_FRAMES_UPDATEFRAME,FrameId, FU_FMPOS); + + wnd:=CallService(MS_CLUI_GETHWND{MS_CLUI_GETHWNDTREE},0,0); + tmp:=SendMessage(wnd,CLM_GETEXSTYLE,0,0); + SendMessage(wnd,CLM_SETEXSTYLE,tmp or CLS_EX_SHOWSELALWAYS,0); + + cid.cbSize:=SizeOf(cid); + cid.flags :=0; + StrCopy(cid.group,cPluginName); + StrCopy(cid.dbSettingsGroup,cPluginName); + + StrCopy(cid.name ,frm_back); + StrCopy(cid.setting,'frame_back'); + cid.defcolour:=COLOR_3DFACE; + cid.order :=0; + ColourRegister(@cid); + + hbr:=0; + colorhook:=HookEvent(ME_COLOUR_RELOAD,@ColorReload); + ColorReload(0,0); + CallService(MS_RADIO_SETVOL,gVolume,0); + end; + end; +end; + +procedure DestroyFrame; +begin + if FrameId>=0 then + begin + UnhookEvent(colorhook); + CallService(MS_CLIST_FRAMES_REMOVEFRAME,FrameId,0); + FrameId:=-1; + end; + DestroyWindow(FrameWnd); + FrameWnd:=0; +end; + +end. diff --git a/plugins/mRadio/rglobal.pas b/plugins/mRadio/rglobal.pas new file mode 100644 index 0000000000..283daae17c --- /dev/null +++ b/plugins/mRadio/rglobal.pas @@ -0,0 +1,257 @@ +{used variables} +unit rglobal; + +interface + +uses + windows, + Dynamic_Bass, + playlist; + +{$include m_radio.inc} + +const + cPluginName = 'mRadio'; +const + PluginName:PAnsiChar = cPluginName; + +const + BassStatus:(rbs_null,rbs_load,rbs_init) = rbs_null; + +const + chan :HSTREAM = 0; + ActiveContact:THANDLE = 0; + ActiveURL :PWideChar = nil; + +const + optVolume :PAnsiChar = 'Volume'; + + optVersion :PAnsiChar = 'version'; //?? + + // mRadio compatibility +//optStationurl << + optMyHandle :PAnsiChar = 'MyHandle'; + optGenre :PAnsiChar = 'Genre'; + optBitrate :PAnsiChar = 'Bitrate'; + // UserInfo compatibility + optFirstName :PAnsiChar = 'FirstName'; + optNick :PAnsiChar = 'Nick'; + optLastName :PAnsiChar = 'LastName'; + optAge :PAnsiChar = 'Age'; + + optGroup :PAnsiChar = 'Group'; + +const + optEAXType :PAnsiChar = 'EAXtype'; + optStatusMsg :PAnsiChar = 'StatusMsg'; + optBASSPath :PAnsiChar = 'BASSpath'; + + optLastStn :PAnsiChar = 'LastStation'; + optActiveCodec:PAnsiChar = 'ActiveCodec'; + optStationURL :PAnsiChar = 'StationURL'; // mRadio compatibility +const + optTitle :PAnsiChar = 'Title'; + optArtist :PAnsiChar = 'Artist'; + optStatus :PAnsiChar = 'Status'; + +var + hhRadioStatus, + hNetLib:THANDLE; +var + plist:tPlaylist; +// plFile:pWideChar; // playlist file name (for delete after using?) +// plLocal:boolean; // true - no need to delete playlist +var + RemoteSong:bool; + gVolume:integer; + NumTries:cardinal; + doLoop:cardinal; + PlayFirst:cardinal; + doShuffle:cardinal; + ForcedMono:cardinal; + doContRec:cardinal; + AuConnect:cardinal; + AuMute:cardinal; + AsOffline:cardinal; + isEQ_OFF:cardinal; + PluginStatus:integer; + storagep,storage:PAnsiChar; + recpath:pWideChar; + StatusTmpl:pWideChar; + sBuffer, + sTimeout, + sPreBuf:cardinal; + usedevice:PAnsiChar; + +const // inside INC files only + hVolCtrl:HWND=0; + +//----- Equalizer ----- + +type + tEQRec = record + fx :HFX; + wnd :HWND; + param :BASS_DX8_PARAMEQ; + text :PAnsiChar; + end; +var + eq:array [0..9] of tEQRec = ( + (fx:0;wnd:0;param:(fCenter:80 ;fBandwidth:18;fGain:0);text:'80'), + (fx:0;wnd:0;param:(fCenter:170 ;fBandwidth:18;fGain:0);text:'170'), + (fx:0;wnd:0;param:(fCenter:310 ;fBandwidth:18;fGain:0);text:'310'), + (fx:0;wnd:0;param:(fCenter:600 ;fBandwidth:18;fGain:0);text:'600'), + (fx:0;wnd:0;param:(fCenter:1000 ;fBandwidth:18;fGain:0);text:'1k'), + (fx:0;wnd:0;param:(fCenter:3000 ;fBandwidth:18;fGain:0);text:'3k'), + (fx:0;wnd:0;param:(fCenter:6000 ;fBandwidth:18;fGain:0);text:'6k'), + (fx:0;wnd:0;param:(fCenter:12000;fBandwidth:18;fGain:0);text:'12k'), + (fx:0;wnd:0;param:(fCenter:14000;fBandwidth:18;fGain:0);text:'14k'), + (fx:0;wnd:0;param:(fCenter:16000;fBandwidth:18;fGain:0);text:'16k')); + +//----- Button icons ----- + +const + IcoBtnSettings:PAnsiChar = 'Radio_Setting'; + IcoBtnOn :PAnsiChar = 'Radio_On'; + IcoBtnOff :PAnsiChar = 'Radio_Off'; + IcoBtnRecUp :PAnsiChar = 'Radio_RecUp'; + IcoBtnRecDn :PAnsiChar = 'Radio_RecDn'; + IcoBtnAdd :PAnsiChar = 'Radio_Add'; + IcoBtnDel :PAnsiChar = 'Radio_Del'; + +//----- EAX ----- + +type + TEAXItem = record + name:PWideChar; + code:dword; + end; +const + EAXItems:array [0..EAX_ENVIRONMENT_COUNT] of TEAXItem=( + (name:'Off' ; code:0), + (name:'Generic' ; code:EAX_ENVIRONMENT_GENERIC), + (name:'Padded Cell' ; code:EAX_ENVIRONMENT_PADDEDCELL), + (name:'Room' ; code:EAX_ENVIRONMENT_ROOM), + (name:'Bathroom' ; code:EAX_ENVIRONMENT_BATHROOM), + (name:'Living Room' ; code:EAX_ENVIRONMENT_LIVINGROOM), + (name:'Stone Room' ; code:EAX_ENVIRONMENT_STONEROOM), + (name:'Auditorium' ; code:EAX_ENVIRONMENT_AUDITORIUM), + (name:'Concert Hall' ; code:EAX_ENVIRONMENT_CONCERTHALL), + (name:'Cave' ; code:EAX_ENVIRONMENT_CAVE), + (name:'Arena' ; code:EAX_ENVIRONMENT_ARENA), + (name:'Hangar' ; code:EAX_ENVIRONMENT_HANGAR), + (name:'Carpeted Hallway'; code:EAX_ENVIRONMENT_CARPETEDHALLWAY), + (name:'Hallway' ; code:EAX_ENVIRONMENT_HALLWAY), + (name:'Stone Corridor' ; code:EAX_ENVIRONMENT_STONECORRIDOR), + (name:'Alley' ; code:EAX_ENVIRONMENT_ALLEY), + (name:'Forrest' ; code:EAX_ENVIRONMENT_FOREST), + (name:'City' ; code:EAX_ENVIRONMENT_CITY), + (name:'Mountains' ; code:EAX_ENVIRONMENT_MOUNTAINS), + (name:'Quarry' ; code:EAX_ENVIRONMENT_QUARRY), + (name:'Plain' ; code:EAX_ENVIRONMENT_PLAIN), + (name:'Parking Lot' ; code:EAX_ENVIRONMENT_PARKINGLOT), + (name:'Sewer Pipe' ; code:EAX_ENVIRONMENT_SEWERPIPE), + (name:'Under Water' ; code:EAX_ENVIRONMENT_UNDERWATER), + (name:'Drugged' ; code:EAX_ENVIRONMENT_DRUGGED), + (name:'Dizzy' ; code:EAX_ENVIRONMENT_DIZZY), + (name:'Psychotic' ; code:EAX_ENVIRONMENT_PSYCHOTIC)); + + +function MakeMessage:pWideChar; +procedure SetStatus(hContact:THANDLE;status:integer); +function GetDefaultRecPath:pWideChar; +function GetStatusText(status:integer;toCList:boolean=false):PWideChar; + + +implementation + +uses + m_api, common, dbsettings; + +procedure SetStatus(hContact:THANDLE;status:integer); +begin +// if Status=ID_STATUS_OFFLINE then +// MyStopBass; + + if status=ID_STATUS_OFFLINE then + begin + if (AsOffline=BST_UNCHECKED) or (PluginStatus<>ID_STATUS_OFFLINE) then + status:=ID_STATUS_INVISIBLE; + end; + + if hContact=0 then + begin + hContact:=db_find_first(PluginName); + while hContact<>0 do + begin + DBWriteWord(hContact,PluginName,optStatus,status); + hContact:=db_find_next(hContact,PluginName); + end; + end + else + DBWriteWord(hContact,PluginName,optStatus,status); +end; + +function MakeMessage:pWideChar; +var + p,artist,title:pWideChar; + len:cardinal; +begin + artist:=DBReadUnicode(0,PluginName,optArtist); + title :=DBReadUnicode(0,PluginName,optTitle); + len:=StrLenW(artist); + if (artist<>nil) and (title<>nil) then + inc(len,3); + inc(len,StrLenW(title)); + + if len>0 then + begin + mGetMem(result,(len+1)*SizeOf(WideChar)); + p:=result; + if artist<>nil then + begin + p:=StrCopyEW(p,artist); + if title<>nil then + p:=StrCopyEW(p,' - '); + mFreeMem(artist); + end; + if title<>nil then + begin + StrCopyW(p,title); + mFreeMem(title); + end; + end + else + result:=nil; +end; + +function GetDefaultRecPath:pWideChar; +var + dat:TREPLACEVARSDATA; + mstr,szData:pWideChar; + buf:array [0..MAX_PATH-1] of WideChar; +begin + FillChar(dat,SizeOf(dat),0); + dat.cbSize :=SizeOf(TREPLACEVARSDATA); + dat.dwFlags:=RVF_UNICODE; + szData:='%miranda_userdata%'+'\'+cPluginName; + mstr:=pWideChar(CallService(MS_UTILS_REPLACEVARS, WPARAM(szData), LPARAM(@dat))); + PathToRelativeW(mstr,buf); + StrDupW(result,buf); + mir_free(mstr); +end; + +function GetStatusText(status:integer;toCList:boolean=false):PWideChar; +begin + case status of + RD_STATUS_PAUSED : result:='paused'; + RD_STATUS_STOPPED: if toCList then result:=nil else result:='stopped'; + RD_STATUS_CONNECT: result:='connecting'; + RD_STATUS_ABORT : result:='aborting'; + RD_STATUS_PLAYING: if toCList then result:=nil else result:='playing'; + else + result:=nil; + end; +end; + +end. diff --git a/plugins/mRadio/roptions.pas b/plugins/mRadio/roptions.pas new file mode 100644 index 0000000000..347747521c --- /dev/null +++ b/plugins/mRadio/roptions.pas @@ -0,0 +1,251 @@ +{Different settings} +unit roptions; + +interface + +//----- Presets ----- + +type + tPreset = record + name :PWideChar; + preset:array [0..9] of shortint; + end; +var + Presets: array of tPreset; + OldEQPreset:integer; + +procedure LoadPresets; +procedure SavePresets; +procedure FreePresets; + +procedure FreeSettings; +procedure LoadSettings; +procedure SaveCommonSettings; +procedure SaveTechSettings; + + +implementation + +uses + windows, + common,dbsettings,mirutils, + rglobal; + +const + optRecPath :PAnsiChar = 'RecordPath'; + optStatusTmpl :PAnsiChar = 'StatusTmpl'; + + optLoop :PAnsiChar = 'Loop'; + optShuffle :PAnsiChar = 'Shuffle'; + optPlayFirst :PAnsiChar = 'PlayFromFirst'; + optContRec :PAnsiChar = 'ContRec'; + optConnect :PAnsiChar = 'AutoConnect'; + optAutoMute :PAnsiChar = 'AutoMute'; + optOffline :PAnsiChar = 'asOffline'; + + optEQ_OFF :PAnsiChar = 'eqoff'; + optForcedMono :PAnsiChar = 'ForcedMono'; + optPreBuf :PAnsiChar = 'PreBuf'; + optBuffer :PAnsiChar = 'Buffer'; + optTimeout :PAnsiChar = 'Timeout'; + optNumTries :PAnsiChar = 'NumTries'; + optDevice :PAnsichar = 'Device'; + +{ +const + optVolume :PAnsiChar = 'Volume'; +} +//----- Presets ----- + +const + optOldPreset:pAnsiChar='oldpreset'; + optPresets :pAnsiChar='numpreset'; + optPreset :pAnsiChar='preset_'; + optPreDescr :pAnsiChar='predescr_'; + +const + PresetMax = 17; + +procedure InitPresets; +type + tP = array [0..9] of AnsiChar; +begin + StrDupW(Presets[00].name,'Acoustic' ); tP(Presets[00].preset):=#$01#$02#$00#$00#$00#$00#$00#$01#$01#$03; + StrDupW(Presets[01].name,'Blues' ); tP(Presets[01].preset):=#$01#$02#$01#$00#$00#$00#$00#$00#$00#$FE; + StrDupW(Presets[02].name,'Classical'); tP(Presets[02].preset):=#$01#$04#$01#$00#$00#$00#$00#$00#$01#$01; + StrDupW(Presets[03].name,'Country' ); tP(Presets[03].preset):=#$00#$00#$01#$01#$00#$00#$01#$01#$01#$01; + StrDupW(Presets[04].name,'Dance' ); tP(Presets[04].preset):=#$04#$03#$02#$01#$FF#$FF#$02#$04#$05#$05; + StrDupW(Presets[05].name,'Folk' ); tP(Presets[05].preset):=#$FF#$00#$00#$01#$01#$00#$01#$01#$01#$00; + StrDupW(Presets[06].name,'Grunge' ); tP(Presets[06].preset):=#$01#$00#$FF#$00#$00#$02#$01#$FF#$FE#$FD; + StrDupW(Presets[07].name,'Jazz' ); tP(Presets[07].preset):=#$00#$01#$02#$03#$03#$01#$01#$03#$04#$05; + StrDupW(Presets[08].name,'Metall' ); tP(Presets[08].preset):=#$FE#$00#$00#$00#$00#$03#$02#$04#$06#$05; + StrDupW(Presets[09].name,'New Age' ); tP(Presets[09].preset):=#$03#$03#$00#$00#$00#$00#$00#$00#$02#$02; + StrDupW(Presets[10].name,'Opera' ); tP(Presets[10].preset):=#$00#$01#$02#$04#$01#$02#$00#$00#$00#$00; + StrDupW(Presets[11].name,'Rap' ); tP(Presets[11].preset):=#$00#$04#$04#$00#$00#$00#$01#$04#$05#$07; + StrDupW(Presets[12].name,'Reggae' ); tP(Presets[12].preset):=#$03#$00#$FD#$00#$05#$00#$02#$03#$04#$05; + StrDupW(Presets[13].name,'Rock' ); tP(Presets[13].preset):=#$00#$02#$04#$00#$00#$00#$02#$04#$05#$06; + StrDupW(Presets[14].name,'Speech' ); tP(Presets[14].preset):=#$FE#$02#$00#$00#$00#$00#$FF#$FE#$FD#$FC; + StrDupW(Presets[15].name,'Swing' ); tP(Presets[15].preset):=#$FF#$00#$00#$02#$02#$00#$02#$02#$03#$03; + StrDupW(Presets[16].name,'Techno' ); tP(Presets[16].preset):=#$05#$08#$FF#$FE#$FD#$FF#$04#$06#$06#$06; +end; + +procedure LoadPresets; +var + num,preset,descr:array [0..63] of AnsiChar; + i:integer; + p,pd:pAnsiChar; +begin + p :=StrCopyE(preset,optPreset); + pd:=StrCopyE(descr ,optPreDescr); + + i:=DBReadByte(0,PluginName,optPresets); + if i=0 then + begin + SetLength(Presets,PresetMax); + InitPresets; + OldEQPreset:=-1; + end + else + begin + OldEQPreset:=integer(DBReadByte(0,PluginName,optOldPreset,byte(-1))); + SetLength(Presets,i); + for i:=0 to HIGH(Presets) do + begin + StrCopy(p ,IntToStr(num,i)); DBReadStruct (0,PluginName,preset,@Presets[i].preset,10); + StrCopy(pd,num); Presets[i].name:=DBReadUnicode(0,PluginName,descr); + end; + end; +end; + +procedure SavePresets; +var + num,preset,descr:array [0..63] of AnsiChar; + i,j:integer; + p,pd:pAnsiChar; +begin + p :=StrCopyE(preset,optPreset); + pd:=StrCopyE(descr ,optPreDescr); + j:=DBReadByte(0,PluginName,optPresets); + for i:=0 to HIGH(Presets) do + begin + StrCopy(p ,IntToStr(num,i)); DBWriteStruct (0,PluginName,preset,@Presets[i].preset,10); + StrCopy(pd,num); DBWriteUnicode(0,PluginName,descr ,Presets[i].name); + end; + while j>Length(Presets) do + begin + dec(j); + StrCopy(p ,IntToStr(num,j)); DBDeleteSetting(0,PluginName,preset); + StrCopy(pd,num); DBDeleteSetting(0,PluginName,descr); + end; + DBWriteByte(0,PluginName,optOldPreset,OldEQPreset); + DBWriteByte(0,PluginName,optPresets ,Length(Presets)); +end; + +procedure FreePresets; +var + i:integer; +begin + for i:=0 to HIGH(Presets) do + mFreeMem(Presets[i].name); +end; + +//----- Common settings ----- + +procedure FreeSettings; +begin + mFreeMem(recpath); + mFreeMem(StatusTmpl); + mFreeMem(usedevice); +end; + +procedure LoadSettings; +var + szTemp:array [0..7] of AnsiChar; + i:integer; +begin + //-- record + recpath:=DBReadUnicode(0,PluginName,optRecPath); + if recpath=nil then + recpath:=GetDefaultRecPath; + + //-- mRadio settings + doLoop :=DBReadByte(0,PluginName,optLoop); + doShuffle :=DBReadByte(0,PluginName,optShuffle); + doContRec :=DBReadByte(0,PluginName,optContRec); + PlayFirst :=DBReadByte(0,PluginName,optPlayFirst); + AuConnect :=DBReadByte(0,PluginName,optConnect); + AuMute :=DBReadByte(0,PluginName,optAutoMute); + AsOffline :=DBReadByte(0,PluginName,optOffline); + StatusTmpl:=DBReadUnicode(0,PluginName,optStatusTmpl,'%radio_title%'); + + //-- Tech settings + usedevice :=DBReadString(0,PluginName,optDevice); + + sPreBuf :=DBReadWord(0,PluginName,optPreBuf ,75); + sBuffer :=DBReadWord(0,PluginName,optBuffer ,5000); + sTimeout :=DBReadWord(0,PluginName,optTimeout,5000); + + isEQ_OFF :=DBReadByte(0,PluginName,optEQ_OFF); + gVolume :=DBReadByte(0,PluginName,optVolume,50); + ForcedMono:=DBReadByte(0,PluginName,optForcedMono); + NumTries :=DBReadByte(0,PluginName,optNumTries,1); + if NumTries<1 then NumTries:=1; + + //-- Equalizer + szTemp[0]:='E'; + szTemp[1]:='Q'; + szTemp[2]:='_'; + szTemp[4]:=#0; + for i:=0 to 9 do + begin + szTemp[3]:=AnsiChar(ORD('0')+i); + eq[i].param.fGain:=DBReadByte(0,PluginName,szTemp,15)-15; + end; + + if AuConnect<>BST_UNCHECKED then + ActiveContact:=LoadContact(PluginName,optLastStn) + else + ActiveContact:=0; +end; + +procedure SaveCommonSettings; +begin + DBWriteByte(0,PluginName,optLoop ,doLoop); + DBWriteByte(0,PluginName,optShuffle ,doShuffle); + DBWriteByte(0,PluginName,optContRec ,doContRec); + DBWriteByte(0,PluginName,optPlayFirst,PlayFirst); + DBWriteByte(0,PluginName,optConnect ,AuConnect); + DBWriteByte(0,PluginName,optAutoMute ,AuMute); + DBWriteByte(0,PluginName,optOffline ,AsOffline); + + DBWriteUnicode(0,PluginName,optStatusTmpl,StatusTmpl); + DBWriteUnicode(0,PluginName,optRecPath ,recpath); +end; + +procedure SaveTechSettings; +var + szTemp:array [0..7] of AnsiChar; + i:integer; +begin + DBWriteWord(0,PluginName,optTimeout,sTimeout); + DBWriteWord(0,PluginName,optBuffer,sBuffer); + DBWriteWord(0,PluginName,optPreBuf,sPreBuf); + + DBWriteByte(0,PluginName,optForcedMono,ForcedMono); + DBWriteByte(0,PluginName,optNumTries,NumTries); + DBWriteByte(0,PluginName,optEQ_OFF ,isEQ_OFF); + + DBWriteString(0,PluginName,optDevice,usedevice); + + szTemp[0]:='E'; + szTemp[1]:='Q'; + szTemp[2]:='_'; + szTemp[4]:=#0; + for i:=0 to 9 do + begin + szTemp[3]:=AnsiChar(ORD('0')+i); + DBWriteByte(0,PluginName,szTemp,trunc(eq[i].param.fGain)+15); + end; +end; + +end. -- cgit v1.2.3