MMConect.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:53k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 05.10.98 - 17:53:10 $                                        =}
  24. {========================================================================}
  25. unit MMConect;
  26. {$I COMPILER.INC}
  27. {.$DEFINE _MMDEBUG}
  28. {$C FIXED PRELOAD PERMANENT}
  29. interface
  30. uses
  31. {$IFDEF WIN32}
  32.     Windows,
  33. {$ELSE}
  34.     WinTypes,
  35.     WinProcs,
  36. {$ENDIF}
  37.     SysUtils,
  38.     Messages,
  39.     Classes,
  40.     Controls,
  41.     Forms,
  42.     MMSystem,
  43.     MMObj,
  44.     MMDSPObj,
  45.     MMTimer,
  46.     MMUtils,
  47.     MMString,
  48.     MMMulDiv,
  49.     MMRegs,
  50.     MMPCMSup,
  51.     MMWaveIO,
  52.     MMLevel,
  53. {$IFNDEF LEVEL_ONLY}
  54.     MMMeter,
  55.     MMOscope,
  56.     MMSpectr,
  57.     MMSpGram,
  58.     MMLight,
  59. {$ENDIF}
  60.     MMACMSup
  61.     {$IFDEF _MMDEBUG}
  62.     ,MMDebug
  63.     {$ENDIF};
  64. const
  65.    { set this to true if you have problems with hints or flat buttons }
  66.    ENTER_IDLE_MODE : Boolean = False;
  67.    {$IFDEF CBUILDER3} {$EXTERNALSYM MAXSPEED} {$ENDIF}
  68.    MAXSPEED        = 5000;
  69. type
  70.    TMMTriggerMode    = (tmNone, tmUpFlank, tmDownFlank);
  71.    EMMConnectorError = class(Exception);
  72.    {-- TMMConnector ------------------------------------------------------}
  73.    TMMConnector = class(TMMDSPComponent)
  74.    private
  75.     {$IFDEF WIN32}
  76.     FDataSection   : TRtlCriticalSection;
  77.     {$ENDIF}
  78.     FTimerID       : integer;
  79.     FEnabled       : Boolean;
  80.     FRestoreIdle   : Boolean;
  81.     FAutoTrigger   : Boolean;
  82.     FTriggerMode   : TMMTriggerMode;
  83.     FTriggerLevel  : integer;
  84.     FSynchronize   : Boolean;
  85.     FSilence       : integer;
  86.     FStarted       : Boolean;
  87.     FRunning       : Boolean;
  88.     FPaused        : Boolean;
  89.     FConvert       : PACMConvert;
  90.     FDstWaveFormat : PWaveFormatEx;
  91.     FDstBufferSize : Longint;
  92.     FRealBufferSize: Longint;
  93.     FSrcData       : PChar;
  94.     FDstData       : PChar;
  95.     FAutoConvert   : Boolean;
  96.     FIsPCMFormat   : Boolean;
  97.     FCanConvert    : Boolean;
  98.     FSpeed         : integer;
  99.     FRefresh       : Boolean;
  100.     FInHandler     : integer;
  101.     FRealTime      : Boolean;
  102.     FLevel1        : TMMLevel;
  103.     FLevel2        : TMMLevel;
  104.     {$IFNDEF LEVEL_ONLY}
  105.     FMeter1        : TMMMeter;
  106.     FMeter2        : TMMMeter;
  107.     FOscope1       : TMMOscope;
  108.     FOscope2       : TMMOscope;
  109.     FLight1        : TMMLight;
  110.     FLight2        : TMMLight;
  111.     FSpectrum1     : TMMSpectrum;
  112.     FSpectrum2     : TMMSpectrum;
  113.     FSpectrum3     : TMMSpectrum;
  114.     FSpectrum4     : TMMSpectrum;
  115.     FSpectrogram1  : TMMSpectrogram;
  116.     FSpectrogram2  : TMMSpectrogram;
  117.     {$ENDIF}
  118.     FIndexLevel        : Longint;
  119.     {$IFNDEF LEVEL_ONLY}
  120.     FIndexMeter        : Longint;
  121.     FIndexScope        : Longint;
  122.     FIndexLight        : Longint;
  123.     FIndexSpectrum     : Longint;
  124.     FIndexSpectrogram1 : Longint;
  125.     FIndexSpectrogram2 : Longint;
  126.     {$ENDIF}
  127.     FRefreshLevel      : Boolean;
  128.     {$IFNDEF LEVEL_ONLY}
  129.     FRefreshMeter      : Boolean;
  130.     FRefreshScope      : Boolean;
  131.     FRefreshLight      : Boolean;
  132.     FRefreshSpectrum   : Boolean;
  133.     FRefreshSpectrogram: Boolean;
  134.     {$ENDIF}
  135.     FLevelRefresh      : Longint;
  136.     {$IFNDEF LEVEL_ONLY}
  137.     FMeterRefresh      : Longint;
  138.     FOscopeRefresh     : Longint;
  139.     FLightRefresh      : Longint;
  140.     FSpectrumRefresh   : Longint;
  141.     FSpectrogramRefresh: Longint;
  142.     {$ENDIF}
  143.     FBufTime           : Int64;
  144.     FStepTime          : Int64;
  145.     FOnTrigger         : TNotifyEvent;
  146.     procedure SetEnabled(aValue: Boolean);
  147.     procedure SetAutoTrigger(aValue: Boolean);
  148.     procedure SetSpeed(aValue: integer);
  149.     procedure SetTriggerMode(aValue: TMMTriggerMode);
  150.     procedure SetTriggerLevel(aValue: integer);
  151.     procedure SetRealTime(aValue: Boolean);
  152.     procedure SetLevel(index: integer; aValue: TMMLevel);
  153.     {$IFNDEF LEVEL_ONLY}
  154.     procedure SetMeter(index: integer; aValue: TMMMeter);
  155.     procedure SetOscope(index: integer; aValue: TMMOscope);
  156.     procedure SetLight(index: integer; aValue: TMMLight);
  157.     procedure SetSpectrum(index: integer; aValue: TMMSpectrum);
  158.     procedure SetSpectrogram(index: integer; aValue: TMMSpectrogram);
  159.     {$ENDIF}
  160.     procedure SetEnterIdle(aValue: Boolean);
  161.     function  GetEnterIdle: Boolean;
  162.     procedure SetWaveParams;
  163.     procedure ProcessData;
  164.     procedure UpdateTimer(Enabled: Boolean);
  165.   protected
  166.     procedure ChangeDesigning(aValue: Boolean); override;
  167.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  168.     procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  169.     procedure Started; override;
  170.     procedure Paused; override;
  171.     procedure Restarted; override;
  172.     procedure Stopped; override;
  173.     procedure Reseting; override;
  174.     procedure BufferReady(lpwh: PWaveHdr); override;
  175.     procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
  176.   public
  177.     constructor Create(AOwner: TComponent); override;
  178.     destructor  Destroy; override;
  179.     procedure NewBuffer(lpData: PChar; dwLength: DWORD); virtual;
  180.     property  IsPaused: Boolean read FPaused;
  181.     property  IsStarted: Boolean read FStarted;
  182.     
  183.     procedure Trigger; virtual;
  184.     property  RefreshCountLevel: Longint read FLevelRefresh write FLevelRefresh;
  185.     {$IFNDEF LEVEL_ONLY}
  186.     property  RefreshCountMeter: Longint read FMeterRefresh write FMeterRefresh;
  187.     property  RefreshCountOscope: Longint read FOscopeRefresh write FOscopeRefresh;
  188.     property  RefreshCountLight: Longint read FLightRefresh write FLightRefresh;
  189.     property  RefreshCountSpectrum: Longint read FSpectrumRefresh write FSpectrumRefresh;
  190.     property  RefreshCountSpectrogram: Longint read FSpectrogramRefresh write FSpectrogramRefresh;
  191.     {$ENDIF}
  192.     procedure GetPeak(var PeakL, PeakR: Smallint);
  193.   published
  194.     property OnTrigger: TNotifyEvent read FOnTrigger write FOnTrigger;
  195.     property Enabled: Boolean read FEnabled write SetEnabled default True;
  196.     property AutoConvert: Boolean read FAutoConvert write FAutoConvert default True;
  197.     property AutoTrigger: Boolean read FAutoTrigger write SetAutoTrigger default True;
  198.     property Synchronize: Boolean read FSynchronize  write FSynchronize default True;
  199.     property Speed: integer read FSpeed write SetSpeed default MAXSPEED;
  200.     property TriggerMode: TMMTriggerMode read FTriggerMode write SetTriggerMode default tmNone;
  201.     property TriggerLevel: integer read FTriggerLevel write SetTriggerLevel default 0;
  202.     property RefreshOnStop: Boolean read FRefresh write FRefresh default True;
  203.     property RealTime: Boolean read FRealTime write SetRealTime default True;
  204.     property EnterIdle: Boolean read GetEnterIdle write SetEnterIdle;
  205.     property Input;
  206.     property Output;
  207.     property Level1: TMMLevel index 0 read FLevel1 write SetLevel;
  208.     property Level2: TMMLevel index 1 read FLevel2 write SetLevel;
  209.     {$IFNDEF LEVEL_ONLY}
  210.     property Meter1: TMMMeter index 0 read FMeter1 write SetMeter;
  211.     property Meter2: TMMMeter index 1 read FMeter2 write SetMeter;
  212.     property Oscope1: TMMOscope index 0 read FOscope1 write SetOscope;
  213.     property Oscope2: TMMOscope index 1 read FOscope2 write SetOscope;
  214.     property Light1: TMMLight index 0 read FLight1 write SetLight;
  215.     property Light2: TMMLight index 1 read FLight2 write SetLight;
  216.     property Spectrum1: TMMSpectrum index 0 read FSpectrum1 write SetSpectrum;
  217.     property Spectrum2: TMMSpectrum index 1 read FSpectrum2 write SetSpectrum;
  218.     property Spectrum3: TMMSpectrum index 2 read FSpectrum3 write SetSpectrum;
  219.     property Spectrum4: TMMSpectrum index 3 read FSpectrum4 write SetSpectrum;
  220.     property Spectrogram1: TMMSpectrogram index 0 read FSpectrogram1 write SetSpectrogram;
  221.     property Spectrogram2: TMMSpectrogram index 1 read FSpectrogram2 write SetSpectrogram;
  222.     {$ENDIF}
  223.   end;
  224. implementation
  225. uses Consts;
  226. type
  227.   TIdleHandler = class
  228.     procedure Idle(Sender: TObject; var Done: Boolean);
  229.   end;
  230. const
  231.   CM_CON_START         = CM_BASE + 501;
  232.   CM_CON_TRIGGER       = CM_BASE + 502;
  233.   CM_CON_AUTOTRIGGER   = CM_BASE + 503;
  234. const
  235.   ConnectorWindow: HWND    = 0;
  236.   ConnectorCount : Longint = 0;
  237.   ConnectorList  : TList   = nil;
  238.   LoopStarted    : integer = 0;
  239.   LoopSpeed      : integer = 0;
  240.   RestoreIdle    : Boolean = False;
  241.   IdleHandler    : TIdleHandler = nil;
  242. {-------------------------------------------------------------------------}
  243. procedure DebugStr(s: String);
  244. begin
  245. {$IFDEF _MMDEBUG}
  246.    if (s <> ' ') then s := 'Trigger: '+s;
  247.    DB_WriteStrLn(0,s);
  248. {$ENDIF}
  249. end;
  250. {-- TIdleHandler --------------------------------------------------------}
  251. procedure TIdleHandler.Idle(Sender: TObject; var Done: Boolean);
  252. begin
  253.    Done := False;
  254. end;
  255. {------------------------------------------------------------------------}
  256. procedure ProcessConnectors;
  257. var
  258.    i: integer;
  259. begin
  260.    { let windows have some time }
  261.    for i := 0 to MAXSPEED-LoopSpeed do Application.ProcessMessages;
  262.    { now go trough all connectors in the list }
  263.    if (LoopStarted > 0) and (not Application.Terminated) and
  264.       (ConnectorList.Count > 0) then
  265.    begin
  266.       for i := 0 to ConnectorList.Count-1 do
  267.       with TMMConnector(ConnectorList.Items[i]) do
  268.       begin
  269.          if FAutoTrigger and FEnabled and FRunning then ProcessData;
  270.       end;
  271.    end;
  272. end;
  273. {------------------------------------------------------------------------}
  274. function ConnectorWndProc(Window: HWND; Message, wParam: UINT; lParam: Longint): Longint;
  275. export;{$IFDEF WIN32}stdcall;{$ENDIF}
  276. begin
  277.    if (ConnectorList <> nil) then
  278.    try
  279.       case Message of
  280.         CM_CON_START:
  281.         if (lParam <> 0) then
  282.         with TMMConnector(lParam) do
  283.         begin
  284.            if FStarted then
  285.            begin
  286.               FInHandler := 0;
  287.               FRunning := True;
  288.               if FAutoTrigger then
  289.               begin
  290.                  inc(LoopStarted);
  291.                  PostMessage(ConnectorWindow,CM_CON_AUTOTRIGGER,0,0);
  292.               end;
  293.            end;
  294.            exit;
  295.         end;
  296.         CM_CON_TRIGGER:
  297.         if (lParam <> 0) then
  298.         with TMMConnector(lParam) do
  299.         begin
  300.            if FEnabled and FRunning then
  301.            begin
  302.               { process the controls }
  303.               ProcessData;
  304.               {$IFDEF WIN32}
  305.               InterlockedDecrement(FInHandler);
  306.               {$ENDIF}
  307.            end;
  308.            exit;
  309.         end;
  310.         CM_CON_AUTOTRIGGER:
  311.         begin
  312.            { go trough all connectors }
  313.            ProcessConnectors;
  314.            { decide if we need a new loop }
  315.            if (LoopStarted > 0) and (not Application.Terminated) and
  316.               (ConnectorList.Count > 0) then
  317.            begin
  318.               {$IFDEF WIN32}
  319.               Sleep(1);
  320.               {$ENDIF}
  321.               { give the app a chance }
  322.               if ENTER_IDLE_MODE then
  323.                  Application.HandleMessage;
  324.               PostMessage(ConnectorWindow,CM_CON_AUTOTRIGGER,0,0);
  325.            end;
  326.            exit;
  327.         end;
  328.       end;
  329.    except
  330.       Application.HandleException(nil);
  331.    end;
  332.    Result := DefWindowProc(Window, Message, wParam, lParam);
  333. end;
  334. {------------------------------------------------------------------------}
  335. const
  336.   TMMConnectorWindowClass: TWndClass = (
  337.        style: 0;
  338.        lpfnWndProc: @ConnectorWndProc;
  339.        cbClsExtra: 0;
  340.        cbWndExtra: 0;
  341.        hInstance: 0;
  342.        hIcon: 0;
  343.        hCursor: 0;
  344.        hbrBackground: 0;
  345.        lpszMenuName: nil;
  346.        lpszClassName: 'TMMConnectorWindow');
  347. {------------------------------------------------------------------------}
  348. function AllocateConnectorWindow: HWND;
  349. var
  350.    TempClass: TWndClass;
  351.    ClassRegistered: Boolean;
  352. begin
  353.    TMMConnectorWindowClass.hInstance := HInstance;
  354.    ClassRegistered := GetClassInfo(HInstance,
  355.                       TMMConnectorWindowClass.lpszClassName, TempClass);
  356.     if not ClassRegistered or (TempClass.lpfnWndProc <> @ConnectorWndProc) then
  357.     begin
  358.        {$IFDEF WIN32}
  359.        if ClassRegistered then
  360.           Windows.UnregisterClass(TMMConnectorWindowClass.lpszClassName, HInstance);
  361.        Windows.RegisterClass(TMMConnectorWindowClass);
  362.        {$ELSE}
  363.        if ClassRegistered then
  364.           WinProcs.UnregisterClass(TMMConnectorWindowClass.lpszClassName, HInstance);
  365.        WinProcs.RegisterClass(TMMConnectorWindowClass);
  366.        {$ENDIF}
  367.     end;
  368.     Result := CreateWindow(TMMConnectorWindowClass.lpszClassName, '', 0,
  369.                            0, 0, 0, 0, 0, 0, HInstance, nil);
  370. end;
  371. {------------------------------------------------------------------------}
  372. procedure UpdateSpeed(Connector: TMMConnector);
  373. var
  374.    i: integer;
  375. begin
  376.    LoopSpeed := 0;
  377.    if (ConnectorList <> nil) then
  378.    for i := 0 to ConnectorList.Count-1 do
  379.    with TMMConnector(ConnectorList.Items[i]) do
  380.    begin
  381.       if FSpeed > LoopSpeed then LoopSpeed := FSpeed;
  382.    end;
  383. end;
  384. {------------------------------------------------------------------------}
  385. procedure AddConnector(Connector: TMMConnector);
  386. begin
  387.    inc(ConnectorCount);
  388.    if (ConnectorCount = 1) then
  389.    begin
  390.       ConnectorList := TList.Create;
  391.       ConnectorWindow := AllocateConnectorWindow;
  392.    end;
  393.    ConnectorList.Add(Connector);
  394.    UpdateSpeed(Connector);
  395. end;
  396. {------------------------------------------------------------------------}
  397. procedure RemoveConnector(Connector: TMMConnector);
  398. begin
  399.    if (ConnectorList = nil) or (ConnectorList.indexOf(Connector) = -1) then exit;
  400.    ConnectorList.Remove(Connector);
  401.    ConnectorList.Pack;
  402.    dec(ConnectorCount);
  403.    if (ConnectorCount = 0) then
  404.    begin
  405.       ConnectorList.Free;
  406.       ConnectorList := nil;
  407.       DestroyWindow(ConnectorWindow);
  408.       ConnectorWindow := 0;
  409.    end;
  410. end;
  411. {------------------------------------------------------------------------}
  412. procedure TimeCallBack(uTimerID, dwUser: Longint);
  413. begin
  414.   if (dwUser <> 0) then
  415.   with TMMConnector(dwUser) do
  416.   begin
  417.      if FPaused then
  418.      begin
  419.         FBufTime := TimeGetExactTime;
  420.         if assigned(FLevel1) or assigned(FLevel2) then
  421.         begin
  422.            FRefreshLevel := True;
  423.            FIndexLevel     := 0;
  424.         end;
  425.         {$IFNDEF LEVEL_ONLY}
  426.         if assigned(FMeter1) or assigned(FMeter2) then
  427.         begin
  428.            FRefreshMeter := True;
  429.            FIndexMeter     := 0;
  430.         end;
  431.         if assigned(FOscope1) or assigned(FOscope2) then
  432.         begin
  433.            FRefreshScope := True;
  434.            FIndexScope     := 0;
  435.         end;
  436.         if assigned(FLight1) or assigned(FLight2) then
  437.         begin
  438.            FRefreshLight := True;
  439.            FIndexLight := 0;
  440.         end;
  441.         if assigned(FSpectrum1) or assigned(FSpectrum2) or
  442.            assigned(FSpectrum3) or assigned(FSpectrum4) then
  443.         begin
  444.            FRefreshSpectrum := True;
  445.            FIndexSpectrum  := 0;
  446.         end;
  447.         if assigned(FSpectrogram1) or assigned(FSpectrogram2) then
  448.         begin
  449.            FRefreshSpectrogram := True;
  450.            FIndexSpectrogram1 := 0;
  451.            FIndexSpectrogram2 := 0;
  452.         end;
  453.         {$ENDIF}
  454.      end;
  455.   end;
  456. end;
  457. {== TMMConnector ========================================================}
  458. constructor TMMConnector.Create(AOwner: TComponent);
  459. begin
  460.    inherited Create(AOwner);
  461.    FTimerID    := 0;
  462.    FEnabled    := True;
  463.    FRestoreIdle:= False;
  464.    FAutoConvert:= True;
  465.    FAutoTrigger:= True;
  466.    FTriggerMode:= tmNone;
  467.    FTriggerLevel := 0;
  468.    FSynchronize := True;
  469.    FSpeed      := MAXSPEED;
  470.    FStarted    := False;
  471.    FRunning    := False;
  472.    FPaused     := False;
  473.    FSrcData    := nil;
  474.    FDstData    := nil;
  475.    FDstBufferSize:= 0;
  476.    FRealBufferSize:= 0;
  477.    FIsPCMFormat := False;
  478.    FCanConvert  := False;
  479.    FRefresh     := True;
  480.    FRealTime    := True;
  481.    FLevel1       := nil;
  482.    FLevel2       := nil;
  483.    {$IFNDEF LEVEL_ONLY}
  484.    FMeter1       := nil;
  485.    FMeter2       := nil;
  486.    FOscope1      := nil;
  487.    FOscope2      := nil;
  488.    FLight1       := nil;
  489.    FLight2       := nil;
  490.    FSpectrum1    := nil;
  491.    FSpectrum2    := nil;
  492.    FSpectrum3    := nil;
  493.    FSpectrum4    := nil;
  494.    FSpectrogram1 := nil;
  495.    FSpectrogram2 := nil;
  496.    {$ENDIF}
  497.    FIndexLevel       := 0;
  498.    {$IFNDEF LEVEL_ONLY}
  499.    FIndexMeter       := 0;
  500.    FIndexScope       := 0;
  501.    FIndexLight       := 0;
  502.    FIndexSpectrum    := 0;
  503.    FIndexSpectrogram1:= 0;
  504.    FIndexSpectrogram2:= 0;
  505.    {$ENDIF}
  506.    FRefreshLevel      := False;
  507.    {$IFNDEF LEVEL_ONLY}
  508.    FRefreshMeter      := False;
  509.    FRefreshScope      := False;
  510.    FRefreshSpectrum   := False;
  511.    FRefreshSpectrogram:= False;
  512.    {$ENDIF}
  513.    FLevelRefresh      := 0;
  514.    {$IFNDEF LEVEL_ONLY}
  515.    FMeterRefresh      := 0;
  516.    FOscopeRefresh     := 0;
  517.    FSpectrumRefresh   := 0;
  518.    FSpectrogramRefresh:= 0;
  519.    {$ENDIF}
  520.    if not (csDesigning in ComponentState) then
  521.    begin
  522.       TimeBeginPeriod(1);
  523.       { update the connector list }
  524.       AddConnector(Self);
  525.    end;
  526.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  527.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  528. end;
  529. {-- TMMConnector --------------------------------------------------------}
  530. destructor TMMConnector.Destroy;
  531. var
  532.    Msg: TMsg;
  533. begin
  534.    Stopped;
  535.    if not (csDesigning in ComponentState) then
  536.    begin
  537.       TimeEndPeriod(1);
  538.       { remove pending messages }
  539.       while PeekMessage(Msg, ConnectorWindow, CM_CON_START, CM_CON_AUTOTRIGGER, PM_REMOVE) do;
  540.       { update the connector list }
  541.       RemoveConnector(Self);
  542.    end;
  543.    inherited destroy;
  544. end;
  545. {-- TMMConnector --------------------------------------------------------}
  546. procedure TMMConnector.ChangeDesigning(aValue: Boolean);
  547. begin
  548.    inherited ChangeDesigning(aValue);
  549.    if not (csDesigning in ComponentState) then
  550.    begin
  551.       TimeBeginPeriod(1);
  552.       { update the connector list }
  553.       AddConnector(Self);
  554.    end;
  555. end;
  556. {-- TMMConnector --------------------------------------------------------}
  557. procedure TMMConnector.Notification(aComponent: TComponent; Operation: TOperation);
  558. begin
  559.    inherited Notification(aComponent, Operation);
  560.    if (Operation = opRemove) then
  561.    begin
  562.       if (aComponent = FLevel1) then FLevel1 := nil;
  563.       if (aComponent = FLevel2) then FLevel2 := nil;
  564.       {$IFNDEF LEVEL_ONLY}
  565.       if (aComponent = FMeter1) then FMeter1 := nil;
  566.       if (aComponent = FMeter2) then FMeter2 := nil;
  567.       if (aComponent = FOscope1) then FOscope1 := nil;
  568.       if (aComponent = FOscope2) then FOscope2 := nil;
  569.       if (aComponent = FLight1) then FLight1 := nil;
  570.       if (aComponent = FLight2) then FLight2 := nil;
  571.       if (aComponent = FSpectrum1) then FSpectrum1 := nil;
  572.       if (aComponent = FSpectrum2) then FSpectrum2 := nil;
  573.       if (aComponent = FSpectrum3) then FSpectrum3 := nil;
  574.       if (aComponent = FSpectrum4) then FSpectrum4 := nil;
  575.       if (aComponent = FSpectrogram1) then FSpectrogram1 := nil;
  576.       if (aComponent = FSpectrogram2) then FSpectrogram2 := nil;
  577.       {$ENDIF}
  578.    end;
  579. end;
  580. {-- TMMConnector --------------------------------------------------------}
  581. procedure TMMConnector.UpdateTimer(Enabled: Boolean);
  582. var
  583. {$IFNDEF WIN32}
  584.    TimeCB: TTimeCallBack;
  585. {$ENDIF}
  586.    Time: integer;
  587. begin
  588.    FRefreshLevel      := False;
  589.    {$IFNDEF LEVEL_ONLY}
  590.    FRefreshMeter      := False;
  591.    FRefreshScope      := False;
  592.    FRefreshLight      := False;
  593.    FRefreshSpectrum   := False;
  594.    FRefreshSpectrogram:= False;
  595.    {$ENDIF}
  596.    if (FTimerID <> 0) then
  597.    begin
  598.       MMTimeKillEvent(FTimerID);
  599.       FTimerID := 0;
  600.    end;
  601.    if Enabled then
  602.    begin
  603.       if (BufferSize < 8192) then
  604.           Time := wioBytesToTime(PWaveFormat,BufferSize)
  605.       else
  606.           Time := 25;
  607.       FTimerID := MMTimeSetEvent(Time, False, @TimeCallBack, Longint(Self));
  608.       if (FTimerID = 0) then
  609.          raise EOutOfResources.Create({$IFDEF DELPHI3}SNoTimers{$ELSE}LoadStr(SNoTimers){$ENDIF});
  610.    end;
  611. end;
  612. {-- TMMConnector --------------------------------------------------------}
  613. procedure TMMConnector.SetEnterIdle(aValue: Boolean);
  614. begin
  615.    ENTER_IDLE_MODE := aValue;
  616. end;
  617. {-- TMMConnector --------------------------------------------------------}
  618. function TMMConnector.GetEnterIdle: Boolean;
  619. begin
  620.    Result := ENTER_IDLE_MODE;
  621. end;
  622. {-- TMMConnector --------------------------------------------------------}
  623. procedure TMMConnector.SetEnabled(aValue: Boolean);
  624. begin
  625.    if (aValue <> FEnabled) then
  626.    begin
  627.       FEnabled := aValue;
  628.       if not (csDesigning in ComponentState) then
  629.       begin
  630.          if not FEnabled then
  631.          begin
  632.             if FRunning then
  633.             begin
  634.                FRunning := False;
  635.                if FAutoTrigger then dec(LoopStarted);
  636.             end;
  637.             if (LoopStarted = 0) and RestoreIdle then
  638.             begin
  639.                Application.OnIdle := nil;
  640.                IdleHandler.Free;
  641.                IdleHandler := nil;
  642.                RestoreIdle := False;
  643.             end;
  644.             if assigned(FLevel1) then FLevel1.ResetData;
  645.             if assigned(FLevel2) then FLevel2.ResetData;
  646.             {$IFNDEF LEVEL_ONLY}
  647.             if assigned(FMeter1) then FMeter1.ResetData;
  648.             if assigned(FMeter2) then FMeter2.ResetData;
  649.             if assigned(FOscope1) then FOscope1.ResetData;
  650.             if assigned(FOscope2) then FOscope2.ResetData;
  651.             if assigned(FLight1) then FLight1.ResetData;
  652.             if assigned(FLight2) then FLight2.ResetData;
  653.             if assigned(FSpectrum1) then FSpectrum1.ResetData;
  654.             if assigned(FSpectrum2) then FSpectrum2.ResetData;
  655.             if assigned(FSpectrum3) then FSpectrum3.ResetData;
  656.             if assigned(FSpectrum4) then FSpectrum4.ResetData;
  657.             if assigned(FSpectrogram1) then FSpectrogram1.ResetData;
  658.             if assigned(FSpectrogram2) then FSpectrogram2.ResetData;
  659.             {$ENDIF}
  660.          end
  661.          else if FStarted and FRealTime then
  662.          begin
  663.             if FAutoTrigger and ENTER_IDLE_MODE then
  664.             begin
  665.                {$IFDEF WIN32}
  666.                if not assigned(Application.OnIdle) and (IdleHandler = nil) then
  667.                begin
  668.                   IdleHandler := TIdleHandler.Create;
  669.                   Application.OnIdle := IdleHandler.Idle;
  670.                   RestoreIdle := True;
  671.                end;
  672.                {$ENDIF}
  673.             end;
  674.             PostMessage(ConnectorWindow,CM_CON_START,0,Longint(Self));
  675.          end;
  676.       end;
  677.    end;
  678. end;
  679. {-- TMMConnector --------------------------------------------------------}
  680. procedure TMMConnector.SetRealTime(aValue: Boolean);
  681. begin
  682.    if (aValue <> FRealTime) then
  683.    begin
  684.       if isOpen then
  685.          raise EMMConnectorError.Create(LoadResStr(IDS_PROPERTYOPEN));
  686.       FRealTime := aValue;
  687.    end;
  688. end;
  689. {-- TMMConnector --------------------------------------------------------}
  690. procedure TMMConnector.SetSpeed(aValue: integer);
  691. begin
  692.    if (aValue <> FSpeed) then
  693.    begin
  694.       FSpeed := MinMax(aValue,1,MAXSPEED);
  695.       if not (csDesigning in ComponentState) then UpdateSpeed(Self);
  696.    end;
  697. end;
  698. {-- TMMConnector --------------------------------------------------------}
  699. procedure TMMConnector.SetTriggerMode(aValue: TMMTriggerMode);
  700. begin
  701.    if (aValue <> FTriggerMode) then
  702.    begin
  703.       FTriggerMode := aValue;
  704.    end;
  705. end;
  706. {-- TMMConnector --------------------------------------------------------}
  707. procedure TMMConnector.SetTriggerLevel(aValue: integer);
  708. begin
  709.    if (aValue <> FTriggerLevel) then
  710.    begin
  711.       FTriggerLevel := aValue;
  712.    end;
  713. end;
  714. {-- TMMConnector --------------------------------------------------------}
  715. procedure TMMConnector.SetLevel(index: integer; aValue: TMMLevel);
  716. begin
  717.    { bug fix for AXControl under VB }
  718.    if Longint(Self) = Longint(aValue) then exit;
  719.    case index of
  720.         0: if (FLevel1 = aValue) or ((aValue <> nil) and (FLevel2 = aValue)) then exit
  721.            else FLevel1 := aValue;
  722.         1: if (FLevel2 = aValue) or ((aValue <> nil) and (FLevel1 = aValue)) then exit
  723.            else FLevel2 := aValue;
  724.    end;
  725.    FRefreshLevel := False;
  726.    if aValue <> nil then SetWaveParams;
  727.    {$IFDEF WIN32}
  728.    {$IFDEF TRIAL}
  729.    {$DEFINE _HACK2}
  730.    {$I MMHACK.INC}
  731.    {$ENDIF}
  732.    {$ENDIF}
  733. end;
  734. {$IFNDEF LEVEL_ONLY}
  735. {-- TMMConnector --------------------------------------------------------}
  736. procedure TMMConnector.SetMeter(index: integer; aValue: TMMMeter);
  737. begin
  738.    { bug fix for AXControl under VB }
  739.    if Longint(Self) = Longint(aValue) then exit;
  740.    case index of
  741.         0: if (FMeter1 = aValue) or ((aValue <> nil) and (FMeter2 = aValue)) then exit
  742.            else FMeter1 := aValue;
  743.         1: if (FMeter2 = aValue) or ((aValue <> nil) and (FMeter1 = aValue)) then exit
  744.            else FMeter2 := aValue;
  745.    end;
  746.    FRefreshMeter := False;
  747.    if aValue <> nil then SetWaveParams;
  748. end;
  749. {-- TMMConnector --------------------------------------------------------}
  750. procedure TMMConnector.SetOscope(index: integer; aValue: TMMOscope);
  751. begin
  752.    { bug fix for AXControl under VB }
  753.    if Longint(Self) = Longint(aValue) then exit;
  754.    case index of
  755.         0: if (FOscope1 = aValue) or ((aValue <> nil) and (FOscope2 = aValue)) then exit
  756.            else FOscope1 := aValue;
  757.         1: if (FOscope2 = aValue) or ((aValue <> nil) and (FOscope1 = aValue)) then exit
  758.            else FOscope2 := aValue;
  759.    end;
  760.    FRefreshScope := False;
  761.    if aValue <> nil then SetWaveParams;
  762. end;
  763. {-- TMMConnector --------------------------------------------------------}
  764. procedure TMMConnector.SetLight(index: integer; aValue: TMMLight);
  765. begin
  766.    { bug fix for AXControl under VB }
  767.    if Longint(Self) = Longint(aValue) then exit;
  768.    case index of
  769.         0: if (FLight1 = aValue) or ((aValue <> nil) and (FLight2 = aValue)) then exit
  770.            else FLight1 := aValue;
  771.         1: if (FLight2 = aValue) or ((aValue <> nil) and (FLight1 = aValue)) then exit
  772.            else FLight2 := aValue;
  773.    end;
  774.    FRefreshLight := False;
  775.    if aValue <> nil then SetWaveParams;
  776. end;
  777. {-- TMMConnector --------------------------------------------------------}
  778. procedure TMMConnector.SetSpectrum(index: integer; aValue: TMMSpectrum);
  779. begin
  780.    { bug fix for AXControl under VB }
  781.    if Longint(Self) = Longint(aValue) then exit;
  782.    case index of
  783.         0: if (FSpectrum1 = aValue) then exit else FSpectrum1 := aValue;
  784.         1: if (FSpectrum2 = aValue) then exit else FSpectrum2 := aValue;
  785.         2: if (FSpectrum3 = aValue) then exit else FSpectrum3 := aValue;
  786.         3: if (FSpectrum4 = aValue) then exit else FSpectrum4 := aValue;
  787.    end;
  788.    FRefreshSpectrum := False;
  789.    if aValue <> nil then SetWaveParams;
  790.    {$IFDEF WIN32}
  791.    {$IFDEF TRIAL}
  792.    {$DEFINE _HACK3}
  793.    {$I MMHACK.INC}
  794.    {$ENDIF}
  795.    {$ENDIF}
  796. end;
  797. {-- TMMConnector --------------------------------------------------------}
  798. procedure TMMConnector.SetSpectrogram(index: integer; aValue: TMMSpectrogram);
  799. begin
  800.    { bug fix for AXControl under VB }
  801.    if Longint(Self) = Longint(aValue) then exit;
  802.    case index of
  803.         0: if (FSpectrogram1 = aValue) or ((aValue <> nil) and (FSpectrogram2 = aValue)) then exit
  804.            else FSpectrogram1 := aValue;
  805.         1: if (FSpectrogram2 = aValue) or ((aValue <> nil) and (FSpectrogram1 = aValue)) then exit
  806.            else FSpectrogram2 := aValue;
  807.    end;
  808.    FRefreshSpectrogram := False;
  809.    if aValue <> nil then SetWaveParams;
  810. end;
  811. {$ENDIF}
  812. {-- TMMConnector --------------------------------------------------------}
  813. procedure TMMConnector.SetPWaveFormat(aValue: PWaveFormatEx);
  814. begin
  815.    inherited SetPWaveFormat(aValue);
  816.    SetWaveParams;
  817. end;
  818. {-- TMMConnector --------------------------------------------------------}
  819. procedure TMMConnector.SetWaveParams;
  820. var
  821.    wfx: TWaveFormatEx;
  822. begin
  823.    if (PWaveFormat <> nil) then
  824.    begin
  825.       if not FStarted then
  826.       begin
  827.          FCanConvert := False;
  828.          if (PWaveFormat^.wFormatTag = WAVE_FORMAT_PCM) then
  829.          begin
  830.             FIsPCMFormat := True;
  831.             wfx          := PWaveFormat^;
  832.          end
  833.          else
  834.          begin
  835.             FIsPCMFormat := False;
  836.             if FAutoConvert then
  837.             begin
  838.                wfx := acmSuggestPCMFormat(PWaveFormat);
  839.                if (wfx.wFormatTag <> 0) then
  840.                    FCanConvert := acmQueryConvert(PWaveFormat,@wfx,True);
  841.             end;
  842.          end;
  843.       end
  844.       else wfx := FDstWaveFormat^;
  845.       if (FIsPCMFormat or FCanConvert) then
  846.       begin
  847.          if wfx.wBitsPerSample = 8 then
  848.             FSilence := 128
  849.          else
  850.             FSilence := 0;
  851.          if assigned(FLevel1) then
  852.             FLevel1.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  853.          if assigned(FLevel2) then
  854.             FLevel2.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  855.          {$IFNDEF LEVEL_ONLY}
  856.          if assigned(FMeter1) then
  857.             FMeter1.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  858.          if assigned(FMeter2) then
  859.             FMeter2.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  860.          if assigned(FOscope1) then
  861.             FOscope1.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  862.          if assigned(FOscope2) then
  863.             FOscope2.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  864.          if assigned(FLight1) then
  865.             FLight1.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  866.          if assigned(FLight2) then
  867.             FLight2.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  868.          if assigned(FSpectrum1) then
  869.             FSpectrum1.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  870.          if assigned(FSpectrum2) then
  871.             FSpectrum2.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  872.          if assigned(FSpectrum3) then
  873.             FSpectrum3.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  874.          if assigned(FSpectrum4) then
  875.             FSpectrum4.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  876.          if assigned(FSpectrogram1) then
  877.             FSpectrogram1.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  878.          if assigned(FSpectrogram2) then
  879.             FSpectrogram2.PCMWaveFormat := PPCMWaveFormat(@wfx)^;
  880.          {$ENDIF}
  881.       end;
  882.    end;
  883. end;
  884. {-- TMMConnector --------------------------------------------------------}
  885. procedure TMMConnector.Started;
  886. var
  887.    wfx: TWaveFormatEx;
  888. begin
  889.    inherited Started;
  890.    if not (csDesigning in ComponentState) and
  891.           (PWaveFormat <> nil) and not FStarted then
  892.    begin
  893.       FSrcData := nil;
  894.       FDstData := nil;
  895.       if (PWaveFormat^.wFormatTag = WAVE_FORMAT_PCM) then
  896.       begin
  897.          FIsPCMFormat := True;
  898.          FCanConvert  := False;
  899.          FDstWaveFormat := PWaveFormat;
  900.          FDstBufferSize := BufferSize;
  901.          FSrcData := GlobalAllocMem(BufferSize);
  902.          FDstData := FSrcData;
  903.       end
  904.       else
  905.       begin
  906.          FIsPCMFormat := False;
  907.          FCanConvert := False;
  908.          if FAutoConvert then
  909.          begin
  910.             wfx := acmSuggestPCMFormat(PWaveFormat);
  911.             FDstWaveFormat := wioCopyWaveFormat(@wfx);
  912.             FSrcData := GlobalAllocMem(BufferSize);
  913.             FConvert := acmBeginConvert(PWaveFormat,FDstWaveFormat,FSrcData,BufferSize,True);
  914.             if (FConvert <> nil) then
  915.             begin
  916.                FCanConvert := True;
  917.                FDstData := FConvert^.lpDstBuffer;
  918.                FDstBufferSize := FConvert^.dwDstBufferSize;
  919.             end
  920.             else
  921.             begin
  922.                GlobalFreeMem(Pointer(FSrcData));
  923.                GlobalFreeMem(Pointer(FDstWaveFormat));
  924.                FDstBufferSize := 0;
  925.             end;
  926.          end;
  927.       end;
  928.       FRefreshLevel       := False;
  929.       {$IFNDEF LEVEL_ONLY}
  930.       FRefreshMeter       := False;
  931.       FRefreshScope       := False;
  932.       FRefreshLight       := False;
  933.       FRefreshSpectrum    := False;
  934.       FRefreshSpectrogram := False;
  935.       {$ENDIF}
  936.       FLevelRefresh       := 0;
  937.       {$IFNDEF LEVEL_ONLY}
  938.       FMeterRefresh       := 0;
  939.       FOscopeRefresh      := 0;
  940.       FLightRefresh       := 0;
  941.       FSpectrumRefresh    := 0;
  942.       FSpectrogramRefresh := 0;
  943.       {$ENDIF}
  944.       if (FIsPCMFormat or FCanConvert) and (FDstData <> nil) then
  945.       begin
  946.          {$IFDEF WIN32}
  947.          FillChar(FDataSection, SizeOf(FDataSection), 0);
  948.          InitializeCriticalSection(FDataSection);
  949.          {$ENDIF}
  950.          UpdateSpeed(Self);
  951.          FStarted := True;
  952.          SetWaveParams;
  953.          if FEnabled and FRealTime then
  954.          begin
  955.             if FAutoTrigger and ENTER_IDLE_MODE then
  956.             begin
  957.                {$IFDEF WIN32}
  958.                if not assigned(Application.OnIdle) and (IdleHandler = nil) then
  959.                begin
  960.                   IdleHandler := TIdleHandler.Create;
  961.                   Application.OnIdle := IdleHandler.Idle;
  962.                   RestoreIdle := True;
  963.                end;
  964.                {$ENDIF}
  965.             end;
  966.             PostMessage(ConnectorWindow,CM_CON_START,0,Longint(Self));
  967.          end;
  968.       end;
  969.    end;
  970. end;
  971. {-- TMMConnector --------------------------------------------------------}
  972. procedure TMMConnector.Paused;
  973. begin
  974.    if not (csDesigning in ComponentState) and FStarted and not FPaused then
  975.    begin
  976.       FPaused := True;
  977.       if (FDstData <> nil) and (FIsPCMFormat or FCanConvert) then
  978.           GlobalFillMem(FDstData^, FDstBufferSize, FSilence);
  979.       if FRealTime then UpdateTimer(True);
  980.    end;
  981.    inherited Paused;
  982. end;
  983. {-- TMMConnector --------------------------------------------------------}
  984. procedure TMMConnector.Restarted;
  985. begin
  986.    if not (csDesigning in ComponentState) and FPaused then
  987.    begin
  988.       FPaused := False;
  989.       if FRealTime then UpdateTimer(False);
  990.    end;
  991.    inherited Restarted;
  992. end;
  993. {-- TMMConnector --------------------------------------------------------}
  994. procedure TMMConnector.Stopped;
  995. begin
  996.    if not (csDesigning in ComponentState) and FStarted then
  997.    begin
  998.       FStarted := False;
  999.       if FRunning then
  1000.       begin
  1001.          FRunning := False;
  1002.          if FAutoTrigger then dec(LoopStarted);
  1003.          if (LoopStarted = 0) and RestoreIdle then
  1004.          begin
  1005.             Application.OnIdle := nil;
  1006.             IdleHandler.Free;
  1007.             IdleHandler := nil;
  1008.             RestoreIdle := False;
  1009.          end;
  1010.       end;
  1011.       FPaused := False;
  1012.       UpdateTimer(False);
  1013.       if FCanConvert and (FConvert <> nil) then
  1014.       begin
  1015.          acmDoneConvert(FConvert);
  1016.          FDstData := nil;
  1017.          GlobalFreeMem(Pointer(FDstWaveFormat));
  1018.       end;
  1019.       GlobalFreeMem(Pointer(FSrcData));
  1020.       {$IFDEF WIN32}
  1021.       DeleteCriticalSection(FDataSection);
  1022.       {$ENDIF}
  1023.       if FRefresh then
  1024.       begin
  1025.          if assigned(FLevel1) then FLevel1.ResetData;
  1026.          if assigned(FLevel2) then FLevel2.ResetData;
  1027.          {$IFNDEF LEVEL_ONLY}
  1028.          if assigned(FMeter1) then FMeter1.ResetData;
  1029.          if assigned(FMeter2) then FMeter2.ResetData;
  1030.          if assigned(FOscope1) then FOscope1.ResetData;
  1031.          if assigned(FOscope2) then FOscope2.ResetData;
  1032.          if assigned(FLight1) then FLight1.ResetData;
  1033.          if assigned(FLight2) then FLight2.ResetData;
  1034.          if assigned(FSpectrum1) then FSpectrum1.ResetData;
  1035.          if assigned(FSpectrum2) then FSpectrum2.ResetData;
  1036.          if assigned(FSpectrum3) then FSpectrum3.ResetData;
  1037.          if assigned(FSpectrum4) then FSpectrum4.ResetData;
  1038.          if assigned(FSpectrogram1) then FSpectrogram1.ResetData;
  1039.          if assigned(FSpectrogram2) then FSpectrogram2.ResetData;
  1040.          {$ENDIF}
  1041.       end;
  1042.    end;
  1043.    inherited Stopped;
  1044. end;
  1045. {-- TMMConnector --------------------------------------------------------}
  1046. procedure TMMConnector.Reseting;
  1047. begin
  1048.    if not (csDesigning in ComponentState) and FStarted then
  1049.    begin
  1050.       if (FDstData <> nil) and (FIsPCMFormat or FCanConvert) then
  1051.           GlobalFillMem(FDstData^, FDstBufferSize, FSilence);
  1052.    end;
  1053.    inherited Reseting;
  1054. end;
  1055. {-- TMMConnector --------------------------------------------------------}
  1056. procedure TMMConnector.ProcessData;
  1057. var
  1058.    Offset: Longint;
  1059.    DataPtr,DataPtr2: PChar;
  1060.    Size,Size2: integer;
  1061.    TimeOK,Time2OK: Boolean;
  1062.    {$IFNDEF LEVEL_ONLY}
  1063.    Scope: TMMOscope;
  1064.    {$ENDIF}
  1065. begin
  1066.    if FEnabled and (FRunning or (not FRealtime and FStarted)) and (FDstData <> nil) then
  1067.    begin
  1068.       {$IFDEF WIN32}
  1069.       EnterCriticalSection(FDataSection);
  1070.       try
  1071.       {$ENDIF}
  1072.          if FRefreshLevel then
  1073.          begin
  1074.             Size := 0;
  1075.             DataPtr := FDstData;
  1076.             TimeOK := True;
  1077.             if assigned(FLevel1) then Size := FLevel1.BytesPerLevel;
  1078.             if assigned(FLevel2) then Size := Max(Size,FLevel2.BytesPerLevel);
  1079.             if Synchronize then
  1080.             begin
  1081.                FStepTime := 1000000;
  1082.                FStepTime := Trunc(FStepTime*FIndexLevel/FDstWaveFormat^.nAvgBytesPerSec);
  1083.                if (TimeGetExactTime-FBufTime < FStepTime) then
  1084.                begin
  1085.                   TimeOK := False;
  1086.                end;
  1087.             end;
  1088.             if TimeOK then
  1089.             begin
  1090.                inc(DataPtr,FIndexLevel);
  1091.                inc(FIndexLevel,Size);
  1092.                if (DataPtr + Size <= FDstData + FRealBufferSize) then
  1093.                begin
  1094.                   { paint the level. }
  1095.                   if assigned(FLevel1) then FLevel1.RefreshPCMData(DataPtr);
  1096.                   if assigned(FLevel2) then FLevel2.RefreshPCMData(DataPtr);
  1097.                   inc(FLevelRefresh);
  1098.                end
  1099.                else FRefreshLevel := False;
  1100.             end;
  1101.          end;
  1102.          {$IFNDEF LEVEL_ONLY}
  1103.          if FRefreshMeter then
  1104.          begin
  1105.             Size := 0;
  1106.             DataPtr := FDstData;
  1107.             TimeOK := True;
  1108.             if assigned(FMeter1) then Size := FMeter1.BytesPerMeter;
  1109.             if assigned(FMeter2) then Size := Max(Size,FMeter2.BytesPerMeter);
  1110.             if FSynchronize then
  1111.             begin
  1112.                FStepTime := 1000000;
  1113.                FStepTime := Trunc(FStepTime*FIndexMeter/FDstWaveFormat^.nAvgBytesPerSec);
  1114.                if (TimeGetExactTime-FBufTime < FStepTime) then TimeOK := False;
  1115.             end;
  1116.             if TimeOK then
  1117.             begin
  1118.                inc(DataPtr,FIndexMeter);
  1119.                inc(FIndexMeter,Size);
  1120.                if (DataPtr + Size <= FDstData + FRealBufferSize) then
  1121.                begin
  1122.                   { paint the meter. }
  1123.                   if assigned(FMeter1) then FMeter1.RefreshPCMData(DataPtr);
  1124.                    if assigned(FMeter2) then FMeter2.RefreshPCMData(DataPtr);
  1125.                   inc(FMeterRefresh);
  1126.                end
  1127.                else FRefreshMeter := False;
  1128.             end;
  1129.          end;
  1130.          if FRefreshScope then
  1131.          begin
  1132.             Size := 0;
  1133.             Offset := -1;
  1134.             DataPtr := FDstData;
  1135.             TimeOK := True;
  1136.             if assigned(FOscope2) then
  1137.             begin
  1138.                Size := FOscope2.BytesPerScope;
  1139.                Scope := FOscope2;
  1140.             end;
  1141.             if assigned(FOscope1) then
  1142.             begin
  1143.                Size := Max(Size,FOscope1.BytesPerScope);
  1144.                Scope := FOscope1;
  1145.             end;
  1146.             inc(DataPtr, FIndexScope);
  1147.             if (FTriggerMode <> tmNone) and not FPaused then
  1148.             begin
  1149.                Offset := pcmFindZeroCross(FDstWaveFormat, DataPtr,
  1150.                                           FRealBufferSize-FIndexScope,
  1151.                                           0, Byte(FTriggerMode), FTriggerLevel);
  1152.             end;
  1153.             if FSynchronize then
  1154.             begin
  1155.                FStepTime := 1000000;
  1156.                FStepTime := Trunc(FStepTime*FIndexScope/FDstWaveFormat^.nAvgBytesPerSec);
  1157.                if (TimeGetExactTime-FBufTime < FStepTime) then TimeOK := False;
  1158.             end;
  1159.             if TimeOK then
  1160.             with Scope do
  1161.             begin
  1162.                if (Offset > 0) then
  1163.                begin
  1164.                   inc(FIndexScope,Offset);
  1165.                   inc(DataPtr, Offset);
  1166.                end;
  1167.                if Scroll and Accelerate then
  1168.                   inc(FIndexScope, FFTLength div 4 * (Ord(BitLength)+1)*(Ord(Mode)+1))
  1169.                else
  1170.                   inc(FIndexScope, Size);
  1171.                if (DataPtr + Size <= FDstData + FRealBufferSize) then
  1172.                begin
  1173.                   { paint the scope. }
  1174.                   if assigned(FOscope1) then FOscope1.RefreshPCMData(DataPtr);
  1175.                   if assigned(FOscope2) then FOscope2.RefreshPCMData(DataPtr);
  1176.                   inc(FOscopeRefresh);
  1177.                end
  1178.                else FRefreshScope := False;
  1179.             end;
  1180.          end;
  1181.          if FRefreshLight then
  1182.          begin
  1183.             Size := 0;
  1184.             DataPtr := FDstData;
  1185.             TimeOK := True;
  1186.             if assigned(FLight1) then Size := FLight1.BytesPerLight;
  1187.             if assigned(FLight2) then Size := Max(Size,FLight2.BytesPerLight);
  1188.             if FSynchronize then
  1189.             begin
  1190.                FStepTime := 1000000;
  1191.                FStepTime := Trunc(FStepTime*FIndexLight/FDstWaveFormat^.nAvgBytesPerSec);
  1192.                if (TimeGetExactTime-FBufTime < FStepTime) then TimeOK := False;
  1193.             end;
  1194.             if TimeOK then
  1195.             begin
  1196.                inc(DataPtr,FIndexLight);
  1197.                inc(FIndexLight,Size);
  1198.                if (DataPtr + Size <= FDstData + FRealBufferSize) then
  1199.                begin
  1200.                   { paint the light. }
  1201.                   if assigned(FLight1) then FLight1.RefreshPCMData(DataPtr);
  1202.                   if assigned(FLight2) then FLight2.RefreshPCMData(DataPtr);
  1203.                   inc(FLightRefresh);
  1204.                end
  1205.                else FRefreshLight := False;
  1206.             end;
  1207.          end;
  1208.          if FRefreshSpectrum then
  1209.          begin
  1210.             Size := 0;
  1211.             DataPtr := FDstData;
  1212.             TimeOK := True;
  1213.             if assigned(FSpectrum1) then Size := FSpectrum1.BytesPerSpectrum;
  1214.             if assigned(FSpectrum2) then Size := Max(Size,FSpectrum2.BytesPerSpectrum);
  1215.             if assigned(FSpectrum3) then Size := Max(Size,FSpectrum3.BytesPerSpectrum);
  1216.             if assigned(FSpectrum4) then Size := Max(Size,FSpectrum4.BytesPerSpectrum);
  1217.             if FSynchronize then
  1218.             begin
  1219.                FStepTime := 1000000;
  1220.                FStepTime := Trunc(FStepTime*FIndexSpectrum/FDstWaveFormat^.nAvgBytesPerSec);
  1221.                if (TimeGetExactTime-FBufTime < FStepTime) then TimeOK := False;
  1222.             end;
  1223.             if TimeOK then
  1224.             begin
  1225.                inc(DataPtr,FIndexSpectrum);
  1226.                inc(FIndexSpectrum,Size);
  1227.                if (DataPtr + Size <= FDstData + FRealBufferSize) then
  1228.                begin
  1229.                   { paint the spectrum. }
  1230.                   if assigned(FSpectrum1) then FSpectrum1.RefreshPCMData(DataPtr);
  1231.                   if assigned(FSpectrum2) then FSpectrum2.RefreshPCMData(DataPtr);
  1232.                   if assigned(FSpectrum3) then FSpectrum3.RefreshPCMData(DataPtr);
  1233.                   if assigned(FSpectrum4) then FSpectrum4.RefreshPCMData(DataPtr);
  1234.                   inc(FSpectrumRefresh);
  1235.                end
  1236.                else
  1237.                begin
  1238.                   FRefreshSpectrum := False;
  1239.                end;
  1240.             end;
  1241.          end;
  1242.          if FRefreshSpectrogram then
  1243.          begin
  1244.             Size := 0;
  1245.             Size2:= 0;
  1246.             DataPtr := nil;
  1247.             DataPtr2 := nil;
  1248.             TimeOK := False;
  1249.             Time2OK := False;
  1250.             if assigned(FSpectrogram1) then
  1251.             with FSpectrogram1 do
  1252.             begin
  1253.                DataPtr := FDstData;
  1254.                Size := BytesPerSpectrogram;
  1255.                if FSynchronize then
  1256.                begin
  1257.                   FStepTime := 1000000;
  1258.                   FStepTime := Trunc(FStepTime*FIndexSpectrogram1/FDstWaveFormat^.nAvgBytesPerSec);
  1259.                   if (TimeGetExactTime-FBufTime >= FStepTime) then TimeOK := True;
  1260.                end
  1261.                else TimeOK := True;
  1262.                if TimeOK then
  1263.                begin
  1264.                   inc(DataPtr,FIndexSpectrogram1);
  1265.                   if Accelerate then
  1266.                      inc(FIndexSpectrogram1, Size div 4)
  1267.                   else
  1268.                      inc(FIndexSpectrogram1, Size);
  1269.                end;
  1270.             end;
  1271.             if assigned(FSpectrogram2) then
  1272.             with FSpectrogram2 do
  1273.             begin
  1274.                DataPtr2 := FDstData;
  1275.                Size2 := BytesPerSpectrogram;
  1276.                if FSynchronize then
  1277.                begin
  1278.                   FStepTime := 1000000;
  1279.                   FStepTime := Trunc(FStepTime*FIndexSpectrogram2/FDstWaveFormat^.nAvgBytesPerSec);
  1280.                   if (TimeGetExactTime-FBufTime >= FStepTime) then Time2OK := True;
  1281.                end
  1282.                else Time2OK := True;
  1283.                if Time2OK then
  1284.                begin
  1285.                   inc(DataPtr2,FIndexSpectrogram2);
  1286.                   if Accelerate then
  1287.                      inc(FIndexSpectrogram2, Size div 4)
  1288.                   else
  1289.                      inc(FIndexSpectrogram2, Size2);
  1290.                end;
  1291.             end;
  1292.             if TimeOK or Time2OK then
  1293.             begin
  1294.                if ((DataPtr <> nil) and (DataPtr + Size <= FDstData + FRealBufferSize)) or
  1295.                   ((DataPtr2 <> nil) and (DataPtr2 + Size2 <= FDstData + FRealBufferSize)) then
  1296.                begin
  1297.                   { paint the spectrogram. }
  1298.                   if assigned(FSpectrogram1) and TimeOK and
  1299.                     (DataPtr + Size <= FDstData + FRealBufferSize) then
  1300.                     FSpectrogram1.RefreshPCMData(DataPtr);
  1301.                   if assigned(FSpectrogram2) and Time2OK and
  1302.                      (DataPtr2 + Size2 <= FDstData + FRealBufferSize) then
  1303.                      FSpectrogram2.RefreshPCMData(DataPtr2);
  1304.                   inc(FSpectrogramRefresh);
  1305.                end
  1306.                else FRefreshSpectrogram := False;
  1307.             end;
  1308.          end;
  1309.          {$ENDIF}
  1310.       {$IFDEF WIN32}
  1311.       finally
  1312.          LeaveCriticalSection(FDataSection);
  1313.       end;
  1314.       {$ENDIF}
  1315.       if assigned(FOnTrigger) then FOnTrigger(Self);
  1316.    end;
  1317. end;
  1318. {-- TMMConnector --------------------------------------------------------}
  1319. procedure TMMConnector.NewBuffer(lpData: PChar; dwLength: DWORD);
  1320. begin
  1321.    if FEnabled and not FPaused and (FIsPCMFormat or FCanConvert) then
  1322.    begin
  1323.        if (lpData <> nil) then
  1324.        begin
  1325.           FBufTime := TimeGetExactTime;
  1326.           {$IFDEF WIN32}
  1327.           EnterCriticalSection(FDataSection);
  1328.           try
  1329.           {$ENDIF}
  1330.             FRealBufferSize := Min(dwLength,BufferSize);
  1331.             GlobalMoveMem(lpData^,FSrcData^,FRealBufferSize);
  1332.             { if we have a compressed format try to convert the format }
  1333.             if not FIsPCMFormat and FCanConvert then
  1334.             begin
  1335.                FRealBufferSize := acmDoConvert(FConvert,FRealBufferSize);
  1336.                if FRealBufferSize <= 0 then exit;
  1337.             end;
  1338.           {$IFDEF WIN32}
  1339.           finally
  1340.             LeaveCriticalSection(FDataSection);
  1341.           end;
  1342.           {$ENDIF}
  1343.           if assigned(FLevel1) or assigned(FLevel2) then
  1344.           begin
  1345.              FRefreshLevel := True;
  1346.              FIndexLevel   := 0;
  1347.           end;
  1348.           {$IFNDEF LEVEL_ONLY}
  1349.           if assigned(FMeter1) or assigned(FMeter2) then
  1350.           begin
  1351.              FRefreshMeter := True;
  1352.              FIndexMeter   := 0;
  1353.           end;
  1354.           if assigned(FOscope1) or assigned(FOscope2) then
  1355.           begin
  1356.              FRefreshScope := True;
  1357.              FIndexScope   := 0;
  1358.           end;
  1359.           if assigned(FLight1) or assigned(FLight2) then
  1360.           begin
  1361.              FRefreshLight := True;
  1362.              FIndexLight   := 0;
  1363.           end;
  1364.           if assigned(FSpectrum1) or assigned(FSpectrum2) or
  1365.              assigned(FSpectrum3) or assigned(FSpectrum4) then
  1366.           begin
  1367.              FRefreshSpectrum := True;
  1368.              FIndexSpectrum   := 0;
  1369.           end;
  1370.           if assigned(FSpectrogram1) or assigned(FSpectrogram2) then
  1371.           begin
  1372.              FRefreshSpectrogram := True;
  1373.              FIndexSpectrogram1  := 0;
  1374.              FIndexSpectrogram2  := 0;
  1375.           end;
  1376.           {$ENDIF}
  1377.           if not FRealTime and FAutoTrigger then ProcessData;
  1378.        end;
  1379.    end;
  1380. end;
  1381. {-- TMMConnector --------------------------------------------------------}
  1382. procedure TMMConnector.BufferReady(lpwh: PWaveHdr);
  1383. var
  1384.    p: PWaveHdr;
  1385. begin
  1386.    if FSynchronize and (PMMWaveHdr(lpwh)^.lpNext <> nil) and (PMMWaveHdr(lpwh)^.wh.dwBytesRecorded > 0) then
  1387.       p := PMMWaveHdr(lpwh)^.lpNext
  1388.    else
  1389.       p := lpwh;
  1390.    if (p <> nil) then
  1391.        NewBuffer(p^.lpData,p^.dwBytesRecorded);
  1392.    inherited BufferReady(lpwh);
  1393. end;
  1394. {-- TMMConnector --------------------------------------------------------}
  1395. procedure TMMConnector.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
  1396. begin
  1397.    inherited BufferLoad(lpwh, MoreBuffers);
  1398.    NewBuffer(lpwh^.lpData,lpwh.dwBytesRecorded);
  1399. end;
  1400. {-- TMMConnector --------------------------------------------------------}
  1401. procedure TMMConnector.GetPeak(var PeakL, PeakR: Smallint);
  1402. begin
  1403.    if (FIsPCMFormat or FCanConvert) and (FDstData <> nil) then
  1404.    begin
  1405.       pcmFindPeak(FDstWaveFormat,
  1406.                   FDstData, FRealBufferSize,
  1407.                   PeakL, PeakR);
  1408.    end
  1409.    else
  1410.    begin
  1411.       PeakL := FSilence;
  1412.       PeakR := FSilence;
  1413.    end;
  1414. end;
  1415. {-- TMMConnector --------------------------------------------------------}
  1416. procedure TMMConnector.SetAutoTrigger(aValue: Boolean);
  1417. begin
  1418.    if (aValue <> FAutoTrigger) then
  1419.    begin
  1420.       FAutoTrigger := aValue;
  1421.       if not (csDesigning in ComponentState) then
  1422.       begin
  1423.          if not FAutoTrigger then
  1424.          begin
  1425.             if FRunning then
  1426.             begin
  1427.                dec(LoopStarted);
  1428.                FRunning := False;
  1429.             end;
  1430.             if (LoopStarted = 0) and RestoreIdle then
  1431.             begin
  1432.                Application.OnIdle := nil;
  1433.                IdleHandler.Free;
  1434.                IdleHandler := nil;
  1435.                RestoreIdle := False;
  1436.             end;
  1437.          end
  1438.          else if FStarted and FEnabled and FRealTime then
  1439.          begin
  1440.             if FAutoTrigger and ENTER_IDLE_MODE then
  1441.             begin
  1442.                {$IFDEF WIN32}
  1443.                if not assigned(Application.OnIdle) and (IdleHandler = nil) then
  1444.                begin
  1445.                   IdleHandler := TIdleHandler.Create;
  1446.                   Application.OnIdle := IdleHandler.Idle;
  1447.                   RestoreIdle := True;
  1448.                end;
  1449.                {$ENDIF}
  1450.             end;
  1451.             PostMessage(ConnectorWindow,CM_CON_START,0,Longint(Self));
  1452.          end;
  1453.       end;
  1454.    end;
  1455.    {$IFDEF WIN32}
  1456.    {$IFDEF TRIAL}
  1457.    {$DEFINE _HACK1}
  1458.    {$I MMHACK.INC}
  1459.    {$ENDIF}
  1460.    {$ENDIF}
  1461. end;
  1462. {-- TMMConnector --------------------------------------------------------}
  1463. procedure TMMConnector.Trigger;
  1464. begin
  1465.    if FEnabled and (FRunning or (not FRealtime and FStarted)) and not FAutoTrigger then
  1466.    begin
  1467.       {$IFDEF WIN32}
  1468.       if (FInHandler = 0) then
  1469.       begin
  1470.          if (GetCurrentThreadID <> MainThreadID) then
  1471.          begin
  1472.             {$IFDEF WIN32}
  1473.             InterlockedIncrement(FInHandler);
  1474.             {$ENDIF}
  1475.             PostMessage(ConnectorWindow,CM_CON_TRIGGER,0,Longint(Self));
  1476.          end
  1477.          else ProcessData;
  1478.       end;
  1479.       {$ELSE}
  1480.       ProcessData;
  1481.       {$ENDIF}
  1482.    end;
  1483. end;
  1484. end.