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

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: 17.09.98 - 22:21:52 $                                        =}
  24. {========================================================================}
  25. unit MMSplitt;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     SysUtils,
  36.     Messages,
  37.     Classes,
  38.     Controls,
  39.     MMSystem,
  40.     MMObj,
  41.     MMDSPObj,
  42.     MMUtils,
  43.     MMString,
  44.     MMRegs,
  45.     MMPCMSup,
  46.     MMACMSup,
  47.     MMWaveIO;
  48. const
  49.   {$IFDEF CBUILDER3} {$EXTERNALSYM MAXPORTS} {$ENDIF}
  50.   MAXPORTS = 4;
  51. type
  52.   EMMSplitterError  = class(Exception);
  53.   {-- TMMOutputSplitter -------------------------------------------------------}
  54.   TMMOutputSplitter = class(TMMDSPComponent)
  55.   private
  56.     FPorts      : array[0..MAXPORTS-1] of TMMDSPComponent;
  57.     FTempBuffer : PChar;
  58.     procedure SetOutputs(index: integer; aValue: TMMDSPComponent);
  59.     function  GetOutputs(index: integer): TMMDSPComponent;
  60.   protected
  61.     procedure UpdateParams; override;
  62.     procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  63.     procedure Opened; override;
  64.     procedure Closed; override;
  65.     procedure Started; override;
  66.     procedure Paused; override;
  67.     procedure Restarted; override;
  68.     procedure Stopped; override;
  69.     procedure Reseting; override;
  70.     procedure Looped; override;
  71.     procedure BufferReady(lpwh: PWaveHdr); override;
  72.     procedure BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean); override;
  73.     procedure DeconnectNotification(C: TComponent; Port: TMMPort; PortName: string); override;
  74.     function  CanConnectInput(aComponent: TComponent): Boolean; override;
  75.   public
  76.     constructor Create(AOwner:TComponent); override;
  77.     destructor  Destroy; override;
  78.     function CanConnectOutput1(aComponent: TComponent): Boolean; virtual;
  79.     function CanConnectOutput2(aComponent: TComponent): Boolean; virtual;
  80.     function CanConnectOutput3(aComponent: TComponent): Boolean; virtual;
  81.     function CanConnectOutput4(aComponent: TComponent): Boolean; virtual;
  82.   published
  83.     property Input;
  84.     property Output1: TMMDSPComponent index 0 read GetOutputs write SetOutputs;
  85.     property Output2: TMMDSPComponent index 1 read GetOutputs write SetOutputs;
  86.     property Output3: TMMDSPComponent index 2 read GetOutputs write SetOutputs;
  87.     property Output4: TMMDSPComponent index 3 read GetOutputs write SetOutputs;
  88.   end;
  89. implementation
  90. uses TypInfo;
  91. {== TMMOutputSplitter =========================================================}
  92. constructor TMMOutputSplitter.Create(AOwner: TComponent);
  93. begin
  94.    inherited Create(AOwner);
  95.    FillChar(FPorts,sizeOf(FPorts),0);
  96.    FTempBuffer := nil;
  97.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  98.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  99. end;
  100. {-- TMMOutputSplitter ---------------------------------------------------------}
  101. destructor TMMOutputSplitter.Destroy;
  102. begin
  103.    Output1 := nil;
  104.    Output2 := nil;
  105.    Output3 := nil;
  106.    Output4 := nil;
  107.    inherited Destroy;
  108. end;
  109. {-- TMMOutputSplitter ---------------------------------------------------------}
  110. procedure TMMOutputSplitter.UpdateParams;
  111. var
  112.    i: integer;
  113. begin
  114.    inherited UpdateParams;
  115.    if (csLoading in ComponentState) or
  116.       (csReading in ComponentState) or
  117.       (csDestroying in ComponentState) then exit;
  118.    for i := 0 to MAXPORTS-1 do
  119.    begin
  120.       if (FPorts[i] <> nil) then
  121.           FPorts[i].ChangePWaveFormat(PWaveFormat);
  122.    end;
  123. end;
  124. {-- TMMOutputSplitter ---------------------------------------------------------}
  125. Procedure TMMOutputSplitter.SetPWaveFormat(aValue: PWaveFormatEx);
  126. var
  127.    i: integer;
  128. begin
  129.    inherited SetPWaveFormat(aValue);
  130.    if not (csLoading in ComponentState) and
  131.       not (csReading in ComponentState) and
  132.       not (csDestroying in ComponentState) then
  133.    begin
  134.       for i := 0 to MAXPORTS-1 do
  135.           if (FPorts[i] <> nil) then
  136.               FPorts[i].ChangePWaveFormat(PWaveFormat);
  137.    end;
  138. end;
  139. {-- TMMOutputSplitter ---------------------------------------------------------}
  140. procedure TMMOutputSplitter.DeconnectNotification(C: TComponent; Port: TMMPort; PortName: string);
  141. var
  142.    PropInfo: PPropInfo;
  143.    i: integer;
  144. begin
  145.    if (Port = poInput) then
  146.    begin
  147.       for i := 0 to MAXPORTS-1 do
  148.       if (FPorts[i] = C) and (FOutPropName = PortName) then
  149.       begin
  150.          PropInfo := GetPropInfo(C.ClassInfo, FOutPropName);
  151.          if (PropInfo <> nil) and (GetOrdProp(C,PropInfo) = Longint(Self)) then
  152.          begin
  153.             FPorts[i] := nil;
  154.          end;
  155.       end;
  156.    end;
  157.    inherited DeconnectNotification(C,Port,PortName);
  158. end;
  159. {-- TMMOutputSplitter ---------------------------------------------------------}
  160. function TMMOutputSplitter.CanConnectInput(aComponent: TComponent): Boolean;
  161. var
  162.    i: integer;
  163. begin
  164.    Result := False;
  165.    if (aComponent <> Self) and (aComponent is TMMDSPComponent) and
  166.       (GetPropInfo(TMMDSPComponent(aComponent).ClassInfo, 'Output') <> nil) then
  167.    begin
  168.       Result := True;
  169.       { don't allow ring connection }
  170.       i := 0;
  171.       while i < MAXPORTS do
  172.       begin
  173.          if (FPorts[i] <> nil) and not FPorts[i].CanConnectInput(aComponent) then
  174.          begin
  175.             Result := False;
  176.             exit;
  177.          end;
  178.          inc(i);
  179.       end;
  180.    end;
  181. end;
  182. {-- TMMOutputSplitter ---------------------------------------------------------}
  183. function TMMOutputSplitter.CanConnectOutput1(aComponent: TComponent): Boolean;
  184. begin
  185.    Result := False;
  186.    if (aComponent <> Self) and (aComponent is TMMDSPComponent) and
  187.       (aComponent <> Output2) and (aComponent <> Output3) and (aComponent <> Output4) and
  188.       (GetPropInfo(TMMDSPComponent(aComponent).ClassInfo, 'Input') <> nil) then
  189.    begin
  190.       { don't allow ring connection }
  191.       if (Input <> nil) then
  192.           Result := Input.CanConnectOutput(aComponent)
  193.       else
  194.           Result := True;
  195.    end;
  196. end;
  197. {-- TMMOutputSplitter ---------------------------------------------------------}
  198. function TMMOutputSplitter.CanConnectOutput2(aComponent: TComponent): Boolean;
  199. begin
  200.    Result := False;
  201.    if (aComponent <> Self) and (aComponent is TMMDSPComponent) and
  202.       (aComponent <> Output1) and (aComponent <> Output3) and (aComponent <> Output4) and
  203.       (GetPropInfo(TMMDSPComponent(aComponent).ClassInfo, 'Input') <> nil) then
  204.    begin
  205.       { don't allow ring connection }
  206.       if (Input <> nil) then
  207.           Result := Input.CanConnectOutput(aComponent)
  208.       else
  209.           Result := True;
  210.    end;
  211. end;
  212. {-- TMMOutputSplitter ---------------------------------------------------------}
  213. function TMMOutputSplitter.CanConnectOutput3(aComponent: TComponent): Boolean;
  214. begin
  215.    Result := False;
  216.    if (aComponent <> Self) and (aComponent is TMMDSPComponent) and
  217.       (aComponent <> Output1) and (aComponent <> Output2) and (aComponent <> Output4) and
  218.       (GetPropInfo(TMMDSPComponent(aComponent).ClassInfo, 'Input') <> nil) then
  219.    begin
  220.       { don't allow ring connection }
  221.       if (Input <> nil) then
  222.           Result := Input.CanConnectOutput(aComponent)
  223.       else
  224.           Result := True;
  225.    end;
  226. end;
  227. {-- TMMOutputSplitter ---------------------------------------------------------}
  228. function TMMOutputSplitter.CanConnectOutput4(aComponent: TComponent): Boolean;
  229. begin
  230.    Result := False;
  231.    if (aComponent <> Self) and (aComponent is TMMDSPComponent) and
  232.       (aComponent <> Output1) and (aComponent <> Output2) and (aComponent <> Output3) and
  233.       (GetPropInfo(TMMDSPComponent(aComponent).ClassInfo, 'Input') <> nil) then
  234.    begin
  235.       { don't allow ring connection }
  236.       if (Input <> nil) then
  237.           Result := Input.CanConnectOutput(aComponent)
  238.       else
  239.           Result := True;
  240.    end;
  241. end;
  242. {-- TMMOutputSplitter ---------------------------------------------------------}
  243. procedure TMMOutputSplitter.SetOutputs(index: integer; aValue: TMMDSPComponent);
  244.    procedure SetPort(idx: integer; PortName: string; C: TMMDSPComponent);
  245.    type
  246.       TCheckProc = function(aComponent: TComponent): Boolean of object;
  247.    var
  248.       CheckProc: TCheckProc;
  249.    begin
  250.       case index of
  251.           0: CheckProc := CanConnectOutput1;
  252.           1: CheckProc := CanConnectOutput2;
  253.           2: CheckProc := CanConnectOutput3;
  254.           3: CheckProc := CanConnectOutput4;
  255.       end;
  256.       if (C <> FPorts[idx]) and ((C = nil) or CheckProc(C)) then
  257.       begin
  258.          if (FPorts[idx] <> nil) then
  259.          begin
  260.             GlobalDeconnectNotification(Self,poOutput,PortName);
  261.             FPorts[idx].ChangePWaveFormat(nil);
  262.             FPorts[idx]  := nil;
  263.             FOutPropName := '';
  264.          end;
  265.          if (C <> nil) then
  266.          begin
  267.             GlobalDeconnectNotification(C,poInput,'Input');
  268.             FPorts[idx]  := C;
  269.             FOutPropName := 'Input';
  270.             FPorts[idx].SetInputPort(Self,PortName);
  271.             UpdateParams;
  272.          end;
  273.       end;
  274.    end;
  275. begin
  276.    SetPort(index,'Output'+IntToStr(index+1),aValue);
  277.    {$IFDEF WIN32}
  278.    {$IFDEF TRIAL}
  279.    {$DEFINE _HACK1}
  280.    {$I MMHACK.INC}
  281.    {$ENDIF}
  282.    {$ENDIF}
  283. end;
  284. {-- TMMOutputSplitter ---------------------------------------------------------}
  285. function TMMOutputSplitter.GetOutputs(index: integer): TMMDSPComponent;
  286. begin
  287.    Result := FPorts[index];
  288. end;
  289. {-- TMMOutputSplitter ---------------------------------------------------------}
  290. procedure TMMOutputSplitter.Opened;
  291. var
  292.    i: integer;
  293.    Current: TMMDSPComponent;
  294. begin
  295.    if not IsOpen then
  296.    begin
  297.       FTempBuffer := GlobalAllocMem(Max(QUEUE_WRITE_SIZE,BufferSize));
  298.       for i := 0 to MAXPORTS-1 do
  299.       begin
  300.          if (FPorts[i] <> nil) then
  301.          begin
  302.             Current := FPorts[i];
  303.             { go trough all components and notify }
  304.             repeat
  305.                if not (Current is TMMCustomSoundComponent) then
  306.                begin
  307.                   Current.BufferSize := BufferSize;
  308.                   Current.Opened;
  309.                end
  310.                else if (Current <> Self) then
  311.                begin       { there is another sound component on the right side }
  312.                   Current.BufferSize := BufferSize;
  313.                   Current.Opened;
  314.                   break;
  315.                end;
  316.                Current := Current.Output;
  317.             until (Current = nil);
  318.          end;
  319.       end;
  320.       inherited Opened;
  321.    end;
  322. end;
  323. {-- TMMOutputSplitter ---------------------------------------------------------}
  324. procedure TMMOutputSplitter.Closed;
  325. var
  326.    i: integer;
  327.    Current: TMMDSPComponent;
  328. begin
  329.    if IsOpen then
  330.    begin
  331.       for i := 0 to MAXPORTS-1 do
  332.       begin
  333.          if (FPorts[i] <> nil) then
  334.          begin
  335.             Current := FPorts[i];
  336.             { search the last component }
  337.             while (Current.Output <> nil) do
  338.             begin
  339.                Current := Current.Output;
  340.                if (Current is TMMCustomSoundComponent) and (Current <> Self) then
  341.                begin
  342.                   { there is another sound component on the right side }
  343.                   Current.Closed;
  344.                   break;
  345.                end;
  346.             end;
  347.             Current := FPorts[i];
  348.             { go trough all components and notify }
  349.             repeat
  350.                if not (Current is TMMCustomSoundComponent) then
  351.                begin
  352.                   Current.Closed;
  353.                end
  354.                else if (Current <> Self) then
  355.                begin
  356.                   { there is another sound component on the right side }
  357.                   break;
  358.                end;
  359.                Current := Current.Output;
  360.             until (Current = nil);
  361.          end;
  362.       end;
  363.       GlobalFreeMem(Pointer(FTempBuffer));
  364.       inherited Closed;
  365.    end;
  366. end;
  367. {-- TMMOutputSplitter ---------------------------------------------------------}
  368. procedure TMMOutputSplitter.Started;
  369. var
  370.    i: integer;
  371.    Current: TMMDSPComponent;
  372. begin
  373.    if IsOpen and not IsStarted then
  374.    begin
  375.       for i := 0 to MAXPORTS-1 do
  376.       begin
  377.          if (FPorts[i] <> nil) then
  378.          begin
  379.             Current := FPorts[i];
  380.             { go trough all components and notify }
  381.             repeat
  382.                if not (Current is TMMCustomSoundComponent) then
  383.                begin
  384.                   Current.Started;
  385.                end
  386.                else if (Current <> Self) then
  387.                begin
  388.                   Current.Started;
  389.                   break;   { there is another sound component on the right side }
  390.                end;
  391.                Current := Current.Output;
  392.             until (Current = nil);
  393.          end;
  394.       end;
  395.       inherited Started;
  396.    end;
  397. end;
  398. {-- TMMOutputSplitter ---------------------------------------------------------}
  399. procedure TMMOutputSplitter.Stopped;
  400. var
  401.    i: integer;
  402.    Current: TMMDSPComponent;
  403. begin
  404.    if IsStarted then
  405.    begin
  406.       for i := 0 to MAXPORTS-1 do
  407.       begin
  408.          if (FPorts[i] <> nil) then
  409.          begin
  410.             Current := FPorts[i];
  411.             { search the last component }
  412.             while (Current.Output <> nil) do
  413.             begin
  414.                Current := Current.Output;
  415.                if (Current is TMMCustomSoundComponent) and (Current <> Self) then
  416.                begin
  417.                   { there is another sound component on the right side }
  418.                   Current.Stopped;
  419.                   break;
  420.                end;
  421.             end;
  422.             Current := FPorts[i];
  423.             { now go trough all components and notify }
  424.             repeat
  425.                if not (Current is TMMCustomSoundComponent) then
  426.                begin
  427.                   Current.Stopped;
  428.                end
  429.                else if (Current <> Self) then
  430.                begin
  431.                   { there is another sound component on the right side }
  432.                   break;
  433.                end;
  434.                Current := Current.Output;
  435.             until (Current = nil);
  436.          end;
  437.       end;
  438.       inherited Stopped;
  439.    end;
  440. end;
  441. {-- TMMOutputSplitter ---------------------------------------------------------}
  442. procedure TMMOutputSplitter.Paused;
  443. var
  444.    i: integer;
  445.    Current: TMMDSPComponent;
  446. begin
  447.    if IsOpen and not IsPaused then
  448.    begin
  449.       for i := 0 to MAXPORTS-1 do
  450.       begin
  451.          if (FPorts[i] <> nil) then
  452.          begin
  453.            Current := FPorts[i];
  454.            { go trough all components and notify }
  455.            repeat
  456.               if not (Current is TMMCustomSoundComponent) then
  457.               begin
  458.                  Current.Paused;
  459.               end
  460.               else if (Current <> Self) then
  461.               begin
  462.                  Current.Paused;
  463.                  break;   { there is another sound component on the right side }
  464.               end;
  465.               Current := Current.Output;
  466.            until (Current = nil);
  467.          end;
  468.       end;
  469.       inherited Paused;
  470.    end;
  471. end;
  472. {-- TMMOutputSplitter ---------------------------------------------------------}
  473. procedure TMMOutputSplitter.Restarted;
  474. var
  475.    i: integer;
  476.    Current: TMMDSPComponent;
  477. begin
  478.    if IsPaused then
  479.    begin
  480.       for i := 0 to MAXPORTS-1 do
  481.       begin
  482.          if (FPorts[i] <> nil) then
  483.          begin
  484.             Current := FPorts[i];
  485.             { go trough all components and notify }
  486.             repeat
  487.                if not (Current is TMMCustomSoundComponent) then
  488.                begin
  489.                   Current.Restarted;
  490.                end
  491.                else if (Current <> Self) then
  492.                begin
  493.                   Current.Restarted;
  494.                   break;   { there is another sound component on the right side }
  495.                end;
  496.                Current := Current.Output;
  497.             until (Current = nil);
  498.          end;
  499.       end;
  500.       inherited Paused;
  501.    end;
  502. end;
  503. {-- TMMOutputSplitter ---------------------------------------------------------}
  504. procedure TMMOutputSplitter.Reseting;
  505. var
  506.    i: integer;
  507.    Current: TMMDSPComponent;
  508. begin
  509.    for i := 0 to MAXPORTS-1 do
  510.    begin
  511.       if (FPorts[i] <> nil) then
  512.       begin
  513.          Current := FPorts[i];
  514.          { go trough all components and notify }
  515.          repeat
  516.             if not (Current is TMMCustomSoundComponent) then
  517.             begin
  518.                Current.Reseting;
  519.             end
  520.             else if (Current <> Self) then
  521.             begin
  522.                Current.Reseting;
  523.                break;   { there is another sound component on the right side }
  524.             end;
  525.             Current := Current.Output;
  526.          until (Current = nil);
  527.       end;
  528.    end;
  529.    inherited Reseting;
  530. end;
  531. {-- TMMOutputSplitter ---------------------------------------------------------}
  532. procedure TMMOutputSplitter.Looped;
  533. var
  534.    i: integer;
  535.    Current: TMMDSPComponent;
  536. begin
  537.    for i := 0 to MAXPORTS-1 do
  538.    begin
  539.       if (FPorts[i] <> nil) then
  540.       begin
  541.          Current := FPorts[i];
  542.          { go trough all components and notify }
  543.          repeat
  544.             if not (Current is TMMCustomSoundComponent) then
  545.             begin
  546.                Current.Looped;
  547.             end
  548.             else if (Current <> Self) then
  549.             begin
  550.                Current.Looped;
  551.                break;   { there is another sound component on the right side }
  552.             end;
  553.             Current := Current.Output;
  554.          until (Current = nil);
  555.       end;
  556.    end;
  557.    inherited Looped;
  558. end;
  559. {-- TMMOutputSplitter ---------------------------------------------------------}
  560. procedure TMMOutputSplitter.BufferReady(lpwh: PWaveHdr);
  561. var
  562.    i: integer;
  563.    Current: TMMDSPComponent;
  564.    lpdata: PChar;
  565. begin
  566.    inherited BufferReady(lpwh);
  567.    lpData := lpwh.lpData;
  568.    lpwh.lpData := FTempBuffer;
  569.    for i := 0 to MAXPORTS-1 do
  570.    begin
  571.       if (FPorts[i] <> nil) then
  572.       begin
  573.          // we need to make a copy of the data because some filters might change the buffer data
  574.          GlobalMoveMem(lpData^,lpwh.lpData^,lpwh.dwBytesRecorded);
  575.          FPorts[i].BufferReady(lpwh);
  576.       end;
  577.    end;
  578.    lpwh.lpData := lpData;
  579. end;
  580. {-- TMMOutputSplitter ---------------------------------------------------------}
  581. procedure TMMOutputSplitter.BufferLoad(lpwh: PWaveHdr; var MoreBuffers: Boolean);
  582. begin
  583.    raise EMMSplitterError.Create('You can not load data from a splitter !');
  584. end;
  585. end.