{services}

function Service_GetCaps(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl;
begin
  case wParam of
    PFLAGNUM_1:
      result:=PF1_EXTSEARCH or PF1_MODEMSGRECV or PF1_ADDSEARCHRES or PF1_BASICSEARCH;
    PFLAGNUM_2:
      result:=PF2_ONLINE or PF2_INVISIBLE or PF2_SHORTAWAY;
    PFLAGNUM_3:
      result:=PF2_ONLINE;// or PF2_INVISIBLE or PF2_SHORTAWAY;
    PFLAGNUM_4:
      result:=PF4_NOCUSTOMAUTH or PF4_AVATARS;
    PFLAG_UNIQUEIDTEXT:
      result:=int_ptr(Translate('Radio station URL'));
//    PFLAG_UNIQUEIDSETTING:
//      result:=int_ptr(optStationURL)
    else
      result:=0;
  end
end;

function Service_GetName(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl;
begin
  if lParam<>0 then
    StrCopy(PAnsiChar(lParam),Translate(PluginName),wParam);
  result:=0;
end;

procedure GetAwayMsgProc(hContact:THANDLE); cdecl;
var
  buf,p:PWideChar;
begin
  if isVarsInstalled then
  begin
    buf:=ParseVarString(StatusTmpl,ActiveContact);
  end
  else
  begin
    mGetMem(buf,1024);
    StrCopyW(buf,StatusTmpl);
    if StrPosW(buf,'%radio_name%')<>nil then
    begin
      p:=DBReadUnicode(ActiveContact,strCList,optMyHandle);
      StrReplaceW(buf,'%radio_name%',p);
      mFreeMem(p);
    end;
    if StrPosW(buf,'%radio_url%')<>nil then
    begin
      p:=DBReadUnicode(ActiveContact,PluginName,optStationURL);
      StrReplaceW(buf,'%radio_url%',p);
      mFreeMem(p);
    end;
    if StrPosW(buf,'%radio_active%')<>nil then
    begin
      StrReplaceW(buf,'%radio_active%',ActiveURLw);
    end;
    if StrPosW(buf,'%radio_genre%')<>nil then // saved as String
    begin
      p:=DBReadUnicode(ActiveContact,PluginName,optGenre);
      StrReplaceW(buf,'%radio_genre%',p);
      mFreeMem(p);
    end;
    if StrPosW(buf,'%radio_bitrate%')<>nil then // saved as String
    begin
      p:=DBReadUnicode(ActiveContact,PluginName,optBitrate);
      StrReplaceW(buf,'%radio_bitrate%',p);
      mFreeMem(p);
    end;
    if StrPosW(buf,'%radio_title%')<>nil then
    begin
      p:=MakeMessage;
      StrReplaceW(buf,'%radio_title%',p);
      mFreeMem(p);
    end;
    if StrPosW(buf,'%radio_codec%')<>nil then
    begin
      p:=DBReadUnicode(ActiveContact,PluginName,optActiveCodec);
      StrReplaceW(buf,'%radio_codec%',p);
      mFreeMem(p);
    end;
    if StrPosW(buf,'%radio_status%')<>nil then
    begin
      StrReplaceW(buf,'%radio_status%',
         TranslateW(GetStatusText(
             CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET))));
    end;
  end;

  ProtoBroadcastAck(PluginName,hContact,ACKTYPE_AWAYMSG,ACKRESULT_SUCCESS,AckHandle,lParam(buf));
  mFreeMem(buf);
end;

function Service_GetAwayMsg(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl;
var
  ccs:PCCSDATA;
begin
  ccs:=PCCSDATA(lParam);
  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));
    result:=AckHandle;
  end
  else
    result:=0;
end;

function Service_GetStatus(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl;
begin
  result:=PluginStatus;
end;

function Service_LoadIcon(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl;
begin
  case loword(wParam) of
    PLI_PROTOCOL: result:=LoadImage(hInstance,MAKEINTRESOURCE(IDI_MAIN),IMAGE_ICON,16,16,LR_SHARED);
//    PLI_ONLINE  : result:=0;
//    PLI_OFFLINE : result:=0;
  else
    result:=0;
  end;
end;

function Service_SetStatus(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl;
var
  OldStatus:integer;
begin
  result:=0;
  OldStatus:=PluginStatus;
  if wParam<>ID_STATUS_OFFLINE then
    wParam:=ID_STATUS_ONLINE;

  if wParam=PluginStatus then
    exit;

  mFreeMem(proxy);
  PluginStatus:=ID_STATUS_OFFLINE;

  if wParam<>ID_STATUS_OFFLINE then
  begin
    if MyInitBASS<>0 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;
  end
  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;

function CreateProtoService(serviceName:PAnsiChar;pFunc:pointer):THANDLE;
var
  temp:array [0..MAXMODULELABELLENGTH-1] of AnsiChar;
begin
  StrCopy(StrCopyE(temp,PluginName),serviceName);
  result:=CreateServiceFunction(temp,pFunc);
end;

var
  prh0,prh1,prh2,prh3,prh4,prh5,prh6,prh7,prh8,prh9:THANDLE;

procedure DestroyProtoServices;
begin
  DestroyServiceFunction(prh0);
  DestroyServiceFunction(prh1);
  DestroyServiceFunction(prh2);
  DestroyServiceFunction(prh3);
  DestroyServiceFunction(prh4);
  DestroyServiceFunction(prh5);
  DestroyServiceFunction(prh6);
  DestroyServiceFunction(prh7);
  DestroyServiceFunction(prh8);
  DestroyServiceFunction(prh9);
end;

procedure CreateProtoServices;
begin
  prh0:=CreateProtoService(PS_GETCAPS          ,@Service_GetCaps);
  prh1:=CreateProtoService(PS_ADDTOLIST        ,@Service_AddToList);
  prh2:=CreateProtoService(PS_CREATEADVSEARCHUI,@Service_ExtSearchUI);
  prh3:=CreateProtoService(PS_SEARCHBYADVANCED ,@Service_SearchByAdvanced);
  prh4:=CreateProtoService(PS_BASICSEARCH      ,@Service_SearchBasic);
  prh5:=CreateProtoService(PS_GETNAME          ,@Service_GetName);
  prh6:=CreateProtoService(PS_LOADICON         ,@Service_LoadIcon);
  prh7:=CreateProtoService(PS_GETSTATUS        ,@Service_GetStatus);
  prh8:=CreateProtoService(PS_SETSTATUS        ,@Service_SetStatus);
  prh9:=CreateProtoService(PSS_GETAWAYMSG      ,@Service_GetAwayMsg);
(*
{
 Asks protocol for the status message for a status
 wParam=(WORD) 0 for current status or a status id
 lParam=SGMA_xxx
 Returns status msg or NULL if there is none.  The protocol have to handle only the current
 status. Handling messages for other statuses is optional.
 Remember to mir_free the return value
}
  SGMA_UNICODE = 1;        // return Unicode status

  PS_GETMYAWAYMSG = '/GetMyAwayMsg';

*)
(*  {
    wParam : 0
    lParam : Pointer to a null terminated string containing an ID to search for
    Affect : Send a basic search request, see notes
    Returns: A handle to the search request or NULL(0) on failure
    Notes  : All protocols identify users uniquely by a single field
             this service will search by that field.
             -
             All search replies (even protocol-spec extended searches)
             are replied by a series of ack's,-
             -
             Result acks are a series of:
             type=ACKTYPE_SEARCH, result=ACKRESULT_DATA, lParam=Pointer to a TPROTOSEARCHRESULT structure
             -
             ending ack:
             type=ACKTYPE_SEARCH, result=ACKRESULT_SUCCESS, lParam=0
             -
             The pointers in the structure are not guaranteed to be
             valid after the ack is complete.
             -
             The structure to reply with search results can be extended
             per protocol basis (see below)

  }
  PS_BASICSEARCH  = '/BasicSearch';
  PS_BASICSEARCHW = '/BasicSearchW';
*)
end;