unit GenPlugServ;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Windows, ActiveX, Classes, ComObj, ExtCtrls,
  CM2GenInterface, CM2EditorSupportInterface, CM2AutoUpdateInterface,
  fisSharedMemory;

type
  TSong = Record
   title: ShortString;
   artist: ShortString;
   album: ShortString;
   year: ShortString;
   genre: ShortString;
   Filename: ShortString;
   bitrate: Word;
   samplingrate: Word;
   channelmode: shortString;
   positionINPercent: byte;
   songlength: shortString;
   Currenttime: shortString;
   Status: shortString;
  end;
  TCM2GEN_WinAMP = class(TComObject, ICM2GenPlug, ICM2EditorSupport10, ICM2AutoUpdate)
  private
   dataTimer: TTimer;
   lastErrorString: PChar;
   firstRun: boolean;
   fisSharedMemory: TfisSharedMemory;
   sharePointer: ^TSong;
   mp3Record: TSong;
   foo: string;
   procedure closeShareMemory;
   procedure clearMP3Record;
   procedure OnTimer(Sender: TObject);
  protected
  // Declare Basics
   Function Name(OUT Name: Pchar): HResult; stdcall;
   Function Version(OUT Version: word): HResult; stdcall; // Using MMRB Notation
   Function RequiredCoreVersion(OUT RCV: Word): HResult; stdcall; // Using MMRB Notation - Please refer to CM2Plugtypes for details
   Function SetParentHandle(Handle: THandle): HResult; stdcall;
  // Declare Error commands
   Function GetLastErrorMsg(out Msg: PChar): HResult; stdcall;
  // Declare Info system
   Function GetInfoCount(OUT InfoCount: Integer): HResult; stdcall;
   Function GetInfo(Index: Integer; OUT InfoName: PChar; OUT InfoVar: PChar): HResult; stdcall;
  // Declare Sensor system
   Function GetSensorCount(OUT SensorCount: Integer): HResult; stdcall;
   Function GetSensorNameOnly(Index: Integer; OUT SensorName: PChar; OUT SensorStyle: Byte): HResult; stdcall; // Designed for speed polling at startup
   Function GetSensor(Index: Integer; Parameters: PChar; OUT SensorName: PChar; OUT SensorStyle: byte; OUT SensorString: PChar; OUT SensorValue: Double): HResult; stdcall;
  // Declare "Event" functions
   Function Init: HResult; stdcall;
   Function Terminating: HResult; stdcall;
   Function Setup: HResult; stdcall;
  // Default (Required)
   Function GetDefaultCount(SensorIndex: Integer; OUT DefaultCount: Integer): HResult; stdcall;
   Function GetDefault(SensorIndex: Integer; Index: Integer; OUT Name: Pchar; OUT Value: PChar; OUT Description: PChar): HResult; stdcall;
  // Optional
   Function GetOptionalCount(SensorIndex: Integer; OUT OptionalCount: Integer): HResult; stdcall;
   Function GetOptional(SensorIndex: Integer; Index: Integer; OUT Name: Pchar; OUT Value: PChar; OUT Description: PChar): HResult; stdcall;
   Function ShowSensor(Index: Integer; OUT ShowAt: Byte): HResult; stdcall;
   Function ObjIns(SensorIndex: Integer; ParameterName: PChar; OUT ValueType: Byte; OUT ValueRange: PChar): HResult; stdcall;
   Function UpdateFileURL(OUT URL: Pchar): HResult; stdcall;
  End;

const
  Class_CM2GEN_WinAMP: TGUID = '{9327FE61-071A-45DA-B8AB-75E0BAF055D0}';
  UpdateURL: PChar = '';
  ReqCoreVersion: word = 0500;
  PlugInVersion: Word = 0101;
{
Change Log:
v 0101
 - fixed the many SM errors
v 0100
 - first test release.
}

implementation

uses ComServ;

{ TCM2GEN_WinAMP }

function TCM2GEN_WinAMP.Name(out Name: Pchar): HResult;
begin
 Result := S_OK;
 Name := PChar('WinAMP Info');
end;

function TCM2GEN_WinAMP.Version(out Version: word): HResult;
begin
 Result := S_OK;
 Version := PlugInVersion;
end;

function TCM2GEN_WinAMP.RequiredCoreVersion(out RCV: Word): HResult;
begin
 Result := S_OK;
 RCV := ReqCoreVersion;
end;

function TCM2GEN_WinAMP.SetParentHandle(Handle: THandle): HResult;
begin
 Result := S_OK;
end;

function TCM2GEN_WinAMP.GetLastErrorMsg(out Msg: PChar): HResult;
begin
 Result := S_OK;
 If lastErrorString = '' then lastErrorString := 'No error';
 Msg := lastErrorString;
end;

function TCM2GEN_WinAMP.GetInfoCount(out InfoCount: Integer): HResult;
begin
 Result := S_OK;
 InfoCount := 3;
end;

function TCM2GEN_WinAMP.GetInfo(Index: Integer; out InfoName,
  InfoVar: PChar): HResult;
begin
 Result := S_OK;
 Case Index of
  0: Begin
      InfoName := PChar('Programmed By');
      InfoVar := PChar('blert');
     End;
  1: Begin
      InfoName := PChar('Created');
      InfoVar := Pchar('July 7th, 2004');
     End;
  2: Begin
      Infoname := PChar('Updated');
      Infovar := PChar('August 28th, 2004');
     End;
  else begin
        Result := E_FAIL;
        lastErrorString := 'Index out of bounds';
       End;
 End;
end;

function TCM2GEN_WinAMP.GetSensorCount(out SensorCount: Integer): HResult;
begin
 Result := S_OK;
 SensorCount := 14;
end;

function TCM2GEN_WinAMP.GetSensorNameOnly(Index: Integer; out SensorName: PChar;
  out SensorStyle: Byte): HResult;
begin
 Result := S_OK;
 SensorStyle := 1;
 case Index of
  0: SensorName := PChar('Title');
  1: SensorName := PChar('Artist');
  2: SensorName := PChar('Album');
  3: SensorName := PChar('Year');
  4: SensorName := PChar('Genre');
  5: SensorName := PChar('Filename');
  6: begin
       SensorName := PChar('Bit Rate');
       SensorStyle := 0;
     end;
  7: begin
       SensorName := PChar('Sampling Rate');
       SensorStyle := 0;
     end;
  8: SensorName := PChar('Channel Mode');
  9: begin
       SensorName := PChar('Position Percent');
       SensorStyle := 0;
     end;
 10: SensorName := PChar('Length');
 11: SensorName := PChar('Current Time');
 12: SensorName := PChar('Status');
 13: SensorName := PChar('Do Show');
  else begin
        result := E_FAIL;
        lastErrorString := 'Index out of bounds';
       end;
 end;
end;

function TCM2GEN_WinAMP.GetSensor(Index: Integer; Parameters: PChar;
  out SensorName: PChar; out Sensorstyle: byte; out SensorString: PChar;
  out SensorValue: Double): HResult;
begin
 Result := S_OK;
 if firstRun then
   begin
     dataTimer := TTimer.Create(nil);
     dataTimer.OnTimer := OnTimer;
     dataTimer.Interval := 1000;
     dataTimer.Enabled := true;
     firstRun := false;
     exit;
   end;
 SensorStyle := 1;
 SensorValue := 0;
 case Index of
  0: begin
       SensorName := Pchar('Title');
       foo := mp3Record.title;
       SensorString := PChar(foo);
     end;
  1: begin
       SensorName := PChar('Artist');
       foo := mp3Record.artist;
       SensorString := PChar(foo);
     end;
  2: begin
       SensorName := PChar('Album');
       foo := mp3Record.album;
       SensorString := PChar(foo);
     end;
  3: begin
       SensorName := PChar('Year');
       foo := mp3Record.year;
       SensorString := PChar(foo);
     end;
  4: begin
       SensorName := PChar('Genre');
       foo := mp3Record.genre;
       SensorString := PChar(foo);
     end;
  5: begin
       SensorName := PChar('Filename');
       foo := mp3Record.Filename;
       SensorString := PChar(foo);
     end;
  6: begin
       SensorName := PChar('Bit Rate');
       SensorStyle := 0;
       SensorString := PChar('');
       SensorValue := mp3Record.bitrate;
     end;
  7: begin
       SensorName := PChar('Sampling Rate');
       SensorStyle := 0;
       SensorString := PChar('');
       SensorValue := mp3Record.samplingrate;
     end;
  8: begin
       SensorName := PChar('Channel Mode');
       foo := mp3Record.channelmode;
       SensorString := PChar(foo);
     end;
  9: begin
       SensorName := PChar('Position Percent');
       SensorStyle := 0;
       SensorString := PChar('');
       SensorValue := mp3Record.positionINPercent;
     end;
 10: begin
       SensorName := PChar('Length');
       foo := mp3Record.songlength;
       SensorString := PChar(foo);
     end;
 11: begin
       SensorName := PChar('Current Time');
       foo := mp3Record.Currenttime;
       SensorString := PChar(foo);
     end;
 12: begin
       SensorName := PChar('Status');
       foo := mp3Record.Status;
       SensorString := PChar(foo);
     end;
 13: begin
       SensorName := PChar('Do Show');
       SensorString := PChar('');
     end;
  else begin
         result := E_FAIL;
         lastErrorString := 'Index out of bounds';
       end;
 end;
end;

function TCM2GEN_WinAMP.Init: HResult;
begin
 Result := S_OK;
 firstRun := true;
 clearMP3Record;
 fisSharedMemory := TfisSharedMemory.Create(nil);
 fisSharedMemory.ShareName := 'CM2_WA_GEN';
 fisSharedMemory.Size := sizeof(TSong);
 fisSharedMemory.Timeout := 1000;
end;

function TCM2GEN_WinAMP.Terminating: HResult;
begin
 Result := S_OK;
 try
   dataTimer.Enabled := false;
   dataTimer.Free
 except
 end;
 closeShareMemory;
 fisSharedMemory.Free;
end;

function TCM2GEN_WinAMP.Setup: HResult;
begin
 Result := E_NOTIMPL;
end;

function TCM2GEN_WinAMP.GetDefaultCount(SensorIndex: Integer;
  out DefaultCount: Integer): HResult;
begin
 Result := S_OK;
 DefaultCount := 0;
end;

function TCM2GEN_WinAMP.GetDefault(SensorIndex, Index: Integer;
  out Name, Value, Description: PChar): HResult;
begin
 Result := S_OK;
end;

function TCM2GEN_WinAMP.GetOptionalCount(SensorIndex: Integer;
  out OptionalCount: Integer): HResult;
begin
 Result := S_OK;
 OptionalCount := 0;
end;

function TCM2GEN_WinAMP.GetOptional(SensorIndex, Index: Integer;
  out Name, Value, Description: PChar): HResult;
begin
 Result := S_OK;
end;

Function TCM2GEN_WinAMP.ShowSensor(Index: Integer; OUT ShowAt: Byte): HResult; stdcall;
begin
 result := S_OK;
end;

Function TCM2GEN_WinAMP.ObjIns(SensorIndex: Integer; ParameterName: PChar; OUT ValueType: Byte; OUT ValueRange: PChar): HResult; stdcall;
begin
 result := S_OK;
end;

Function TCM2GEN_WinAMP.UpdateFileURL(OUT URL: Pchar): HResult; stdcall;
begin
 Result := S_OK;
 URL := UpdateURL;
end;

procedure TCM2GEN_WinAMP.closeShareMemory;
begin
try fisSharedMemory.UnMapMemory(sharePointer); except end;
try fisSharedMemory.CloseMemory; except end;
end;

procedure TCM2GEN_WinAMP.clearMP3Record;
begin
 with mp3Record do
   begin
     title := ' ';
     artist := ' ';
     album := ' ';
     year := ' ';
     genre := ' ';
     Filename := ' ';
     bitrate := 0;
     samplingrate := 0;
     channelmode := ' ';
     positionINPercent := 0;
     songlength := ' ';
     Currenttime := ' ';
     Status := 'Not Available';
   end;
end;

procedure TCM2GEN_WinAMP.OnTimer(Sender: TObject);
begin
 if fisSharedMemory.OpenMemory then
   sharePointer := fisSharedMemory.MapMemory
 else
   begin
     clearMP3Record;
     exit;
   end;
 fisSharedMemory.RequestOwnership;
 mp3Record.title := SharePointer^.title;
 mp3Record.artist := SharePointer^.artist;
 mp3Record.album := SharePointer^.album;
 mp3Record.year := SharePointer^.year;
 mp3Record.genre := SharePointer^.genre;
 mp3Record.Filename := SharePointer^.Filename;
 mp3Record.bitrate := SharePointer^.bitrate;
 mp3Record.samplingrate := SharePointer^.samplingrate;
 mp3Record.channelmode := SharePointer^.channelmode;
 mp3Record.positionINPercent := SharePointer^.positionINPercent;
 mp3Record.songlength := SharePointer^.songlength;
 mp3Record.Currenttime := SharePointer^.Currenttime;
 mp3Record.Status := SharePointer^.Status;
 fisSharedMemory.ReleaseOwnership;
 closeShareMemory;
end;

initialization
  TComObjectFactory.Create(ComServer, TCM2GEN_WinAMP, Class_CM2GEN_WinAMP,
    'CM2GEN_WinAMP', 'CM2 General Plugin - WinAMP', ciMultiInstance, tmApartment);
end.
