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

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.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: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. unit MMMixBlk;
  26. {$I COMPILER.INC}
  27. {.$DEFINE _MMDEBUG}
  28. interface
  29. uses
  30. {$IFDEF WIN32}
  31.     Windows,
  32. {$ELSE}
  33.     WinTypes,
  34.     WinProcs,
  35. {$ENDIF}
  36.     Forms,
  37.     Messages,
  38.     Stdctrls,
  39.     ExtCtrls,
  40.     SysUtils,
  41.     Controls,
  42.     Classes,
  43.     Graphics,
  44.     MMObj,
  45.     MMObsrv,
  46.     MMUtils,
  47.     MMScale,
  48.     MMLevel,
  49.     MMSlider,
  50. {$IFDEF BUILD_ACTIVEX}
  51.     AxCtrlsUtil,
  52. {$ENDIF}
  53.     MMMixer,
  54.     MMMixCtl;
  55. const
  56.     MM_SETPARENT = MM_USER + 1;
  57. type
  58.     TMMSetParentAction = (saInsert,saInsNoRole,saRemove,saUpdate);
  59.     TMMSetParent = record
  60.         Msg      : Cardinal;
  61.         Action   : Cardinal;
  62.         Control  : TControl;
  63.         Result   : LongInt;
  64.     end;
  65. type
  66.     TMMBlockSliderStyle  = (ssWin95);
  67.     TMMBlockSliderRole   = (srPan,srLeftVolume,srRightVolume);
  68.     {-- TMMCustomBlockSlider -----------------------------------------------}
  69.     TMMCustomBlockSlider = class(TMMCustomMixerSlider)
  70.     private
  71.         FStyle  : TMMBlockSliderStyle;
  72.         FRole   : TMMBlockSliderRole;
  73.         FIsRole : Boolean;
  74.         procedure SetStyle(Value: TMMBlockSliderStyle);
  75.         procedure SetRole(Value: TMMBlockSliderRole);
  76.     protected
  77.         procedure SetParent(Value: TWinControl); override;
  78.         procedure UpdateStyle; virtual;
  79. {$IFDEF BUILD_ACTIVEX}
  80.         procedure MMParentWindowChanged(var M: TMessage); message MM_PARENTWINDOWCHANGED;
  81.         procedure ChangeDesigning(Value: Boolean); override;
  82. {$ENDIF}
  83.     public
  84.         constructor Create(AOwner: TComponent); override;
  85.     protected
  86.         property Style: TMMBlockSliderStyle read FStyle write SetStyle default ssWin95;
  87.         property Role: TMMBlockSliderRole read FRole write SetRole default srPan;
  88.         property GrooveSize nodefault;
  89.         property ScalePosition nodefault;
  90.         property Logarithmic nodefault;
  91.     end;
  92.     {-- TMMMixerBlockSlider ---------------------------------------------}
  93.     TMMMixerBlockSlider = class(TMMCustomBlockSlider)
  94.     published
  95.         property OnEnter;
  96.         property OnExit;
  97.         property OnKeyDown;
  98.         property OnKeyPress;
  99.         property OnKeyUp;
  100.         property OnChange;
  101.         property OnTrack;
  102.         property OnTrackEnd;
  103.         property OnDrawThumb;
  104.         property OnDrawGroove;
  105.         property Style;
  106.         property Role;
  107.         property Logarithmic;
  108.         property Sensitivity;
  109.         property Enabled;
  110.         property Visible;
  111.         property Color;
  112.         property ParentShowHint;
  113.         property PopupMenu;
  114.         property ShowHint;
  115.         property TabStop;
  116.         property TabOrder;
  117.         property Width;
  118.         property Height;
  119.         property Bevel;
  120.         property Groove;
  121.         property FocusAction;
  122.         property FocusColor;
  123.         property GrooveColor;
  124.         property ThumbColor;
  125.         property DisabledColor;
  126.         property HandCursor;
  127.         property Orientation;
  128.         property GrooveSize;
  129.         property ThumbWidth;
  130.         property ThumbHeight;
  131.         property ThumbStyle;
  132.         property Scale;
  133.         property ScalePosition;
  134.         property ScaleDistance;
  135.         property PicLeft;
  136.         property PicRight;
  137.         property Position;
  138.     end;
  139.     TMMBlockLevelStyle  = (lsWin95);
  140.     TMMBlockLevelRole   = (lrLeftLevel,lrRightLevel);
  141.     {-- TMMCustomBlockLevel ------------------------------------------------}
  142.     TMMCustomBlockLevel = class(TMMCustomLevel)
  143.     private
  144.         FStyle  : TMMBlockLevelStyle;
  145.         FRole   : TMMBlockLevelRole;
  146.         FIsRole : Boolean;
  147.         procedure SetStyle(Value: TMMBlockLevelStyle);
  148.         procedure SetRole(Value: TMMBlockLevelRole);
  149.     protected
  150.         procedure UpdateStyle; virtual;
  151.         procedure SetParent(Value: TWinControl); override;
  152. {$IFDEF BUILD_ACTIVEX}
  153.         procedure MMParentWindowChanged(var M: TMessage); message MM_PARENTWINDOWCHANGED;
  154.         procedure ChangeDesigning(Value: Boolean); override;
  155. {$ENDIF}
  156.     public
  157.         constructor Create(AOwner: TComponent); override;
  158.     protected
  159.         property Style: TMMBlockLevelStyle read FStyle write SetStyle default lsWin95;
  160.         property Role: TMMBlockLevelRole read FRole write SetRole default lrLeftLevel;
  161.         property Color nodefault;
  162.         property SpotWidth nodefault;
  163.         property Bar1Color nodefault;
  164.         property Bar2Color nodefault;
  165.         property Bar3Color nodefault;
  166.         property Inactive1Color nodefault;
  167.         property Inactive2Color nodefault;
  168.         property Inactive3Color nodefault;
  169.         property Point1 nodefault;
  170.         property Point2 nodefault;
  171.         property LogAmp nodefault;
  172.         property NumPeaks nodefault;
  173.     end;
  174.     {-- TMMMixerBlockLevel ----------------------------------------------}
  175.     TMMMixerBlockLevel = class(TMMCustomBlockLevel)
  176.     published
  177.         property OnClick;
  178.         property OnDblClick;
  179.         property OnMouseDown;
  180.         property OnMouseMove;
  181.         property OnMouseUp;
  182.         property OnGainOverflow;
  183.         property OnPcmOverflow;
  184.         property Style;
  185.         property Role;
  186.         property Align;
  187.         property Bevel;
  188.         property ParentShowHint;
  189.         property ParentColor;
  190.         property ShowHint;
  191.         property Visible;
  192.         property Color;
  193.         property Enabled;
  194.         property Kind;
  195.         property Height;
  196.         property Width;
  197.         property SpotSpace;
  198.         property SpotWidth;
  199.         property Bar1Color;
  200.         property Bar2Color;
  201.         property Bar3Color;
  202.         property Inactive1Color;
  203.         property Inactive2Color;
  204.         property Inactive3Color;
  205.         property InactiveDoted;
  206.         property ActiveDoted;
  207.         property Point1;
  208.         property Point2;
  209.         property Direction;
  210.         property BitLength;
  211.         property Channel;
  212.         property Mode;
  213.         property Gain;
  214.         property Samples;
  215.         property Sensitivy;
  216.         property LogAmp;
  217.         property NumPeaks;
  218.         property PeakSpeed;
  219.         property PeakDelay;
  220.         property DecayMode;
  221.         property Decay;
  222.         property Value;
  223.     end;
  224.     {-- TMMCustomBlockCheck ----------------------------------------------}
  225.     TMMCustomBlockCheck = class(TMMCustomMixerCheckBox)
  226.     protected
  227.         procedure SetParent(Value: TWinControl); override;
  228. {$IFDEF BUILD_ACTIVEX}
  229.         procedure MMParentWindowChanged(var M: TMessage); message MM_PARENTWINDOWCHANGED;
  230.         procedure MMDesignModeChanged(var M: TMessage); message MM_DESIGNMODECHANGED;
  231.     public
  232.         constructor Create(AOwner: TComponent); override;
  233. {$ENDIF}
  234.     end;
  235.     {-- TMMMixerBlockCheck -----------------------------------------------}
  236.     TMMMixerBlockCheck = class(TMMCustomBlockCheck)
  237.     published
  238.         property OnDragDrop;
  239.         property OnDragOver;
  240.         property OnEndDrag;
  241.         property OnEnter;
  242.         property OnExit;
  243.         property OnKeyDown;
  244.         property OnKeyPress;
  245.         property OnKeyUp;
  246.         property OnMouseDown;
  247.         property OnMouseMove;
  248.         property OnMouseUp;
  249.         property OnStartDrag;
  250.         property AutoCaption;
  251.         property Short;
  252.         property Enabled;
  253.         property Checked;
  254.         property Caption;
  255.         property Alignment;
  256.         property Color;
  257.         property Ctl3D;
  258.         property DragCursor;
  259.         property DragMode;
  260.         property Font;
  261.         property ParentColor;
  262.         property ParentCtl3D;
  263.         property ParentFont;
  264.         property ParentShowHint;
  265.         property PopupMenu;
  266.         property ShowHint;
  267.         property TabOrder;
  268.         property TabStop;
  269.         property Visible;
  270.     end;
  271.     TMMBlockLabelRole   = (lrLineTitle,lrPanTitle,lrVolumeTitle);
  272.     {-- TMMCustomMixerLabel ----------------------------------------------}
  273. {$IFNDEF BUILD_ACTIVEX}
  274.     TMMCustomBlockLabel = class(TCustomLabel)
  275. {$ELSE}
  276.     TMMCustomBlockLabel = class(TStaticText)
  277. {$ENDIF}
  278.     private
  279.         FRole  : TMMBlockLabelRole;
  280.         FIsRole: Boolean;
  281.         procedure SetRole(Value: TMMBlockLabelRole);
  282.     protected
  283.         procedure SetParent(Value: TWinControl); override;
  284. {$IFDEF BUILD_ACTIVEX}
  285.         procedure MMParentWindowChanged(var M: TMessage); message MM_PARENTWINDOWCHANGED;
  286.         procedure MMDesignModeChanged(var M: TMessage); message MM_DESIGNMODECHANGED;
  287.     public
  288.         constructor Create(AOwner: TComponent); override;
  289. {$ENDIF}
  290.     protected
  291.         property Role: TMMBlockLabelRole read FRole write SetRole default lrLineTitle;
  292.     end;
  293.     {-- TMMMixerBlockLabel ----------------------------------------------}
  294.     TMMMixerBlockLabel = class(TMMCustomBlockLabel)
  295.     published
  296.         property OnClick;
  297.         property OnDblClick;
  298.         property OnDragDrop;
  299.         property OnDragOver;
  300.         property OnEndDrag;
  301.         property OnMouseDown;
  302.         property OnMouseMove;
  303.         property OnMouseUp;
  304.         property OnStartDrag;
  305.         property Role;
  306.         property Align;
  307.         property Alignment;
  308.         property AutoSize;
  309.         property Caption;
  310.         property Color;
  311.         property DragCursor;
  312.         property DragMode;
  313.         property Enabled;
  314.         property FocusControl;
  315.         property Font;
  316.         property ParentColor;
  317.         property ParentFont;
  318.         property ParentShowHint;
  319.         property PopupMenu;
  320.         property ShowAccelChar;
  321.         property ShowHint;
  322.         property Visible;
  323. {$IFNDEF BUILD_ACTIVEX}
  324.         property Transparent;
  325.         property WordWrap;
  326. {$ENDIF}
  327.     end;
  328.     EMMBlockError = class(Exception);
  329.     TMMBlockStyle = (bsWin95);
  330.     TMMMuteKind   = (mkMute,mkSelect);
  331.     {-- TMMCustomMixerBlock ------------------------------------------------}
  332.     TMMCustomMixerBlock = class(TMMCustomPanel)
  333.     private
  334.         FAutoArrange: Boolean;
  335.         FAutoSize   : Boolean;
  336.         FPan        : TMMCustomBlockSlider;
  337.         FMute       : TMMCustomBlockCheck;
  338.         FVolumeLeft : TMMCustomBlockSlider;
  339.         FVolumeRight: TMMCustomBlockSlider;
  340.         FLevelLeft  : TMMCustomBlockLevel;
  341.         FLevelRight : TMMCustomBlockLevel;
  342.         FLineTitle  : TMMCustomBlockLabel;
  343.         FPanTitle   : TMMCustomBlockLabel;
  344.         FVolumeTitle: TMMCustomBlockLabel;
  345.         FPanCtl     : TMMPanControl;
  346.         FVolumeCtl  : TMMVolumeControl;
  347.         FMuteCtl    : TMMMixerControl;
  348.         FConnector  : TMMMixerConnector;
  349.         FPeakCtl    : TMMMixerControl;
  350.         FLine       : TMMAudioLine;
  351.         FObserver   : TMMObserver;
  352.         FMixer      : TMMCustomMixerControl;
  353.         FItem       : TMMItemIndex;
  354.         FMixObserver: TMMObserver;
  355.         FStyle      : TMMBlockStyle;
  356.         FRemoving   : TControl;
  357.         FKDummy     : TMMMuteKind;
  358.         procedure SetLine(Value: TMMAudioLine);
  359.         procedure LineNotify(Sender, Data : TObject);
  360.         procedure SetAutoArrange(Value: Boolean);
  361.         procedure SetAutoSize(Value: Boolean);
  362.         procedure SetStyle(Value: TMMBlockStyle);
  363.         procedure SetMixer(Value: TMMCustomMixerControl);
  364.         procedure MixNotify(Sender, Data: TObject);
  365.         procedure SetItem(Value: TMMItemIndex);
  366.     protected
  367.         procedure UpdateBlock; virtual;
  368.         procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  369.         procedure InsertCtl(C: TComponent); virtual;
  370.         procedure Loaded; override;
  371.         procedure ArrangeControls; virtual;
  372.         procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  373.         procedure ConnectLine;
  374.         procedure DisconnectLine;
  375.         procedure ConnectControls;
  376.         procedure MMSetParent(var Msg: TMMSetParent); message MM_SETPARENT;
  377.         procedure CollectControls;
  378. {$IFDEF BUILD_ACTIVEX}
  379.         procedure ChangeDesigning(Value: Boolean); override;
  380. {$ENDIF}
  381.     public
  382.         constructor Create(AOwner: TComponent); override;
  383.         destructor  Destroy; override;
  384.         function GetMuteKind: TMMMuteKind;
  385.         property Pan: TMMCustomBlockSlider read FPan;
  386.         property Mute: TMMCustomBlockCheck read FMute;
  387.         property VolumeLeft: TMMCustomBlockSlider read FVolumeLeft;
  388.         property VolumeRight: TMMCustomBlockSlider read FVolumeRight;
  389.         property LevelLeft: TMMCustomBlockLevel read FLevelLeft;
  390.         property LevelRight: TMMCustomBlockLevel read FLevelRight;
  391.         property LineTitle: TMMCustomBlockLabel read FLineTitle;
  392.         property PanTitle: TMMCustomBlockLabel read FPanTitle;
  393.         property VolumeTitle: TMMCustomBlockLabel read FVolumeTitle;
  394.     protected
  395.         property Line: TMMAudioLine read FLine write SetLine;
  396.         property AutoArrange : Boolean read FAutoArrange write SetAutoArrange default True;
  397.         property AutoSize : Boolean read FAutoSize write SetAutoSize default True;
  398.         property Style: TMMBlockStyle read FStyle write SetStyle default bsWin95;
  399.         property Mixer: TMMCustomMixerControl read FMixer write SetMixer;
  400.         property Item: TMMItemIndex read FItem write SetItem default NoItem;
  401.         property MuteKind: TMMMuteKind read GetMuteKind write FKDummy stored False;
  402.     end;
  403.     {-- TMMMixerBlock ------------------------------------------------------}
  404.     TMMMixerBlock = class(TMMCustomMixerBlock)
  405.     published
  406.         property OnClick;
  407.         property OnDblClick;
  408.         property OnDragDrop;
  409.         property OnDragOver;
  410.         property OnEndDrag;
  411.         property OnEnter;
  412.         property OnExit;
  413.         property OnMouseDown;
  414.         property OnMouseMove;
  415.         property OnMouseUp;
  416.         property OnResize;
  417.         {$IFDEF WIN32}
  418.         property OnStartDrag;
  419.         {$ENDIF}
  420.         property Align;
  421.         property Bevel;
  422.         property DragCursor;
  423.         property DragMode;
  424.         property Enabled;
  425.         property Color;
  426.         property Ctl3D;
  427.         property Font;
  428.         property ParentColor;
  429.         property ParentCtl3D;
  430.         property ParentFont;
  431.         property ParentShowHint;
  432.         property PopupMenu;
  433.         property ShowHint;
  434.         property TabOrder;
  435.         property TabStop;
  436.         property Visible;
  437.         property Line;
  438.         property AutoArrange;
  439.         property AutoSize;
  440.         property Style;
  441.         property Mixer;
  442.         property Item;
  443.         property MuteKind;
  444.     end;
  445. implementation
  446. const
  447.     SpkLeftBmp  = 'SPK_LEFT';
  448.     SpkRightBmp = 'SPK_RIGHT';
  449. {$IFDEF DELPHI2}
  450. const
  451. {$ELSE}
  452. resourcestring
  453. {$ENDIF}
  454.   SIncorrectyUsed = 'This controls can be used only with MixerBlock';
  455. {$IFDEF WIN32}
  456.     {$R MMMIXBLK.D32}
  457. {$ELSE}
  458.     {$R MMMIXBLK.D16}
  459. {$ENDIF}
  460. {-----------------------------------------------------------------------}
  461. function  FindBlock(C: TControl): TMMCustomMixerBlock;
  462. var
  463.    Ctl: TControl;
  464. begin
  465.    Ctl := C;
  466.    while (Ctl <> nil) and not (Ctl is TMMCustomMixerBlock) do
  467.           Ctl := Ctl.Parent;
  468.    Result := Ctl as TMMCustomMixerBlock;
  469. end;
  470. {-----------------------------------------------------------------------}
  471. procedure PostChange(C: TControl; Action: TMMSetParentAction);
  472. var
  473.    Block: TControl;
  474. begin
  475.    Block := FindBlock(C);
  476.    if Block <> nil then
  477.       Block.Perform(MM_SETPARENT,Cardinal(Action),Cardinal(C));
  478. end;
  479. {-----------------------------------------------------------------------}
  480. procedure CheckParent(Value: TWinControl);
  481. begin
  482.    if Value <> nil then
  483.       if FindBlock(Value) = nil then
  484.          { TODO: Should be resource id }
  485.          raise EMMBlockError.Create(SIncorrectyUsed);
  486. end;
  487. {$IFDEF BUILD_ACTIVEX}
  488. {-----------------------------------------------------------------------}
  489. function FindBlockByHandle(Handle, TopHandle: HWND): TMMCustomMixerBlock;
  490. begin
  491.   if (Handle <> 0) and (Handle <> -1) then
  492.   begin
  493.     repeat
  494.       Result := TMMCustomMixerBlock(MMActiveXControls.DelphiControlByHandle(
  495.         Handle));
  496.       if (Result <> nil) and (Result is TMMCustomMixerBlock) then
  497.         exit;
  498.       if Handle = TopHandle then
  499.         break;
  500.       Handle := GetParent(Handle);
  501.     until Handle = 0;
  502.   end;
  503.   Result := nil;
  504. end;
  505. {-----------------------------------------------------------------------}
  506. procedure CheckCorrectUsage(Control: TWinControl);
  507. begin
  508.   with Control do
  509.     if (csDesigning in ComponentState) and
  510.        (not MMActiveXControls.ControlsByDelphiControl[Control].IsParked) and
  511.        (not Assigned(FindBlockByHandle(ParentWindow, 0))) then
  512.       raise EMMBlockError.Create(SIncorrectyUsed);
  513. end;
  514. {-----------------------------------------------------------------------}
  515. procedure TMMCustomBlockSlider.MMParentWindowChanged(var M: TMessage);
  516. begin
  517.   SetParent(FindBlockByHandle(M.LParam, M.WParam));
  518.   CheckCorrectUsage(Self);
  519. end;
  520. {-----------------------------------------------------------------------}
  521. procedure TMMCustomBlockCheck.MMParentWindowChanged(var M: TMessage);
  522. begin
  523.   SetParent(FindBlockByHandle(M.LParam, M.WParam));
  524.   CheckCorrectUsage(Self);
  525. end;
  526. {-----------------------------------------------------------------------}
  527. procedure TMMCustomBlockLevel.MMParentWindowChanged(var M: TMessage);
  528. begin
  529.   SetParent(FindBlockByHandle(M.LParam, M.WParam));
  530.   CheckCorrectUsage(Self);
  531. end;
  532. {-----------------------------------------------------------------------}
  533. procedure TMMCustomBlockLabel.MMParentWindowChanged(var M: TMessage);
  534. begin
  535.   SetParent(FindBlockByHandle(M.LParam, M.WParam));
  536.   CheckCorrectUsage(Self);
  537. end;
  538. {-----------------------------------------------------------------------}
  539. constructor TMMCustomBlockCheck.Create(AOwner: TComponent);
  540. begin
  541.   inherited;
  542.   SetDesigning(True);
  543. end;
  544. {-----------------------------------------------------------------------}
  545. constructor TMMCustomBlockLabel.Create(AOwner: TComponent);
  546. begin
  547.   inherited;
  548.   SetDesigning(True);
  549. end;
  550. {-----------------------------------------------------------------------}
  551. procedure TMMCustomBlockSlider.ChangeDesigning(Value: Boolean);
  552. begin
  553.   inherited;
  554.   CheckCorrectUsage(Self);
  555. end;
  556. {-----------------------------------------------------------------------}
  557. procedure TMMCustomBlockLevel.ChangeDesigning(Value: Boolean);
  558. begin
  559.   inherited;
  560.   CheckCorrectUsage(Self);
  561. end;
  562. {-----------------------------------------------------------------------}
  563. procedure TMMCustomBlockCheck.MMDesignModeChanged(var M: TMessage);
  564. begin
  565.   CheckCorrectUsage(Self);
  566. end;
  567. {-----------------------------------------------------------------------}
  568. procedure TMMCustomBlockLabel.MMDesignModeChanged(var M: TMessage);
  569. begin
  570.   CheckCorrectUsage(Self);
  571. end;
  572. {$ENDIF}
  573. {== TMMCustomBlockSlider ===============================================}
  574. constructor TMMCustomBlockSlider.Create(AOwner: TComponent);
  575. begin
  576.    inherited Create(AOwner);
  577.    FStyle := ssWin95;
  578.    FRole  := srPan;
  579.    UpdateStyle;
  580. end;
  581. {-- TMMCustomBlockSlider -----------------------------------------------}
  582. procedure TMMCustomBlockSlider.SetParent(Value: TWinControl);
  583. begin
  584.    CheckParent(Value);
  585.    if Parent <> Value then
  586.    begin
  587.       PostChange(Self,saRemove);
  588.       inherited SetParent(Value);
  589.       if FIsRole then
  590.          PostChange(Self,saInsert)
  591.       else
  592.          PostChange(Self,saInsNoRole);
  593.    end;
  594. end;
  595. {-- TMMCustomBlockSlider -----------------------------------------------}
  596. procedure TMMCustomBlockSlider.SetStyle(Value: TMMBlockSliderStyle);
  597. begin
  598.    if Value <> FStyle then
  599.    begin
  600.       FStyle := Value;
  601.       UpdateStyle;
  602.    end;
  603. end;
  604. {-- TMMCustomBlockSlider -----------------------------------------------}
  605. procedure TMMCustomBlockSlider.SetRole(Value: TMMBlockSliderRole);
  606. begin
  607.    if not FIsRole or (Value <> FRole) then
  608.    begin
  609.       FIsRole := True;
  610.       FRole   := Value;
  611.       UpdateStyle;
  612.       PostChange(Self,saUpdate);
  613.    end;
  614. end;
  615. {-- TMMCustomBlockSlider -----------------------------------------------}
  616. procedure TMMCustomBlockSlider.UpdateStyle;
  617. begin
  618.    Bevel.BevelOuter:= bvNone;
  619.    Scale.Visible   := True;
  620.    Scale.Connect   := False;
  621.    Scale.Origin    := soInner;
  622.    Scale.Size      := 6;
  623.    GrooveSize      := 1;
  624.    if FRole = srPan then
  625.    begin
  626.       PicLeft.Handle := LoadBitmap(hInstance,SpkLeftBmp);
  627.       PicRight.Handle := LoadBitmap(hInstance,SpkRightBmp);
  628.       Scale.TickCount := 3;
  629.       Scale.EnlargeEvery := 2;
  630.       ScalePosition := spBelowOrRight;
  631.       Logarithmic := False;
  632.    end
  633.    else
  634.    begin
  635.       PicLeft := nil;
  636.       PicRight := nil;
  637.       Scale.TickCount := 7;
  638.       Scale.EnlargeEvery := 6;
  639.       ScalePosition := spBoth;
  640.       Logarithmic := True;
  641.    end;
  642. end;
  643. {== TMMCustomBlockLevel ================================================}
  644. constructor TMMCustomBlockLevel.Create(AOwner: TComponent);
  645. begin
  646.    inherited Create(AOwner);
  647.    FStyle := lsWin95;
  648.    FRole  := lrLeftLevel;
  649.    UpdateStyle;
  650. end;
  651. {-- TMMCustomBlockLevel ------------------------------------------------}
  652. procedure TMMCustomBlockLevel.SetStyle(Value: TMMBlockLevelStyle);
  653. begin
  654.    if Value <> FStyle then
  655.    begin
  656.       FStyle := Value;
  657.       UpdateStyle;
  658.    end;
  659. end;
  660. {-- TMMCustomBlockLevel ------------------------------------------------}
  661. procedure TMMCustomBlockLevel.SetRole(Value: TMMBlockLevelRole);
  662. begin
  663.    if not FIsRole or (Value <> FRole) then
  664.    begin
  665.       FIsRole := True;
  666.       FRole   := Value;
  667.       UpdateStyle;
  668.       PostChange(Self,saUpdate);
  669.    end;
  670. end;
  671. {-- TMMCustomBlockLevel ------------------------------------------------}
  672. procedure TMMCustomBlockLevel.UpdateStyle;
  673. begin
  674.    Bevel.BorderWidth   := 1;
  675.    Color               := clBtnFace;
  676.    SpotWidth           := 6;
  677.    Bar1Color           := clGreen;
  678.    Bar2Color           := clLime;
  679.    Bar3Color           := clYellow;
  680.    Inactive1Color      := clBtnFace;
  681.    Inactive2Color      := clBtnFace;
  682.    Inactive3Color      := clBtnFace;
  683.    Point1              := 45;
  684.    Point2              := 60;
  685.    LogAmp              := False;
  686.    NumPeaks            := 0;
  687. end;
  688. {-- TMMCustomBlockLevel ------------------------------------------------}
  689. procedure TMMCustomBlockLevel.SetParent(Value: TWinControl);
  690. begin
  691.    CheckParent(Value);
  692.    if Parent <> Value then
  693.    begin
  694.       PostChange(Self,saRemove);
  695.       inherited SetParent(Value);
  696.       if FIsRole then
  697.          PostChange(Self,saInsert)
  698.       else
  699.          PostChange(Self,saInsNoRole)
  700.    end;
  701. end;
  702. {== TMMCustomBlockCheck ================================================}
  703. procedure TMMCustomBlockCheck.SetParent(Value: TWinControl);
  704. begin
  705.    CheckParent(Value);
  706.    if Parent <> Value then
  707.    begin
  708.       PostChange(Self,saRemove);
  709.       inherited SetParent(Value);
  710.       PostChange(Self,saInsert)
  711.    end;
  712. end;
  713. {== TMMCustomBlockLabel ================================================}
  714. procedure TMMCustomBlockLabel.SetParent(Value: TWinControl);
  715. begin
  716.    CheckParent(Value);
  717.    if Parent <> Value then
  718.    begin
  719.       PostChange(Self,saRemove);
  720.       inherited SetParent(Value);
  721.       if FIsRole then
  722.          PostChange(Self,saInsert)
  723.       else
  724.          PostChange(Self,saInsNoRole)
  725.    end;
  726. end;
  727. {-- TMMCustomBlockLabel ------------------------------------------------}
  728. procedure TMMCustomBlockLabel.SetRole(Value: TMMBlockLabelRole);
  729. begin
  730.    if not FIsRole or (FRole <> Value) then
  731.    begin
  732.       FRole   := Value;
  733.       FIsRole := True;
  734.       PostChange(Self,saUpdate);
  735.    end;
  736. end;
  737. {== TMMCustomMixerBlock ================================================}
  738. constructor TMMCustomMixerBlock.Create(AOwner: TComponent);
  739. begin
  740.    inherited Create(AOwner);
  741.    ControlStyle            := ControlStyle - [csSetCaption];
  742.    FObserver               := TMMObserver.Create;
  743.    FObserver.OnNotify      := LineNotify;
  744.    FAutoArrange            := True;
  745.    FAutoSize               := True;
  746.    FStyle                  := bsWin95;
  747.    FPanCtl                 := TMMPanControl.Create(Self);
  748.    FVolumeCtl              := TMMVolumeControl.Create(Self);
  749.    FPanCtl.VolumeControl   := FVolumeCtl;
  750.    FMuteCtl                := TMMMixerControl.Create(Self);
  751.    FMuteCtl.ControlType    := ctMute;
  752.    FConnector              := TMMMixerConnector.Create(Self);
  753.    FPeakCtl                := TMMMixerControl.Create(Self);
  754.    FPeakCtl.ControlType    := ctPeakMeter;
  755.    FConnector.Control      := FPeakCtl;
  756.    FItem                   := NoItem;
  757.    FMixObserver            := TMMObserver.Create;
  758.    FMixObserver.OnNotify   := MixNotify;
  759.    Width                   := 100;
  760.    Height                  := 250;
  761. end;
  762. {-- TMMCustomMixerBlock ------------------------------------------------}
  763. destructor TMMCustomMixerBlock.Destroy;
  764. begin
  765.    FPanCtl.Free;
  766.    FVolumeCtl.Free;
  767.    FMuteCtl.Free;
  768.    FPeakCtl.Free;
  769.    FConnector.Free;
  770.    FObserver.Free;
  771.    FMixObserver.Free;
  772.    inherited Destroy;
  773. end;
  774. {$IFDEF BUILD_ACTIVEX}
  775. {-- TMMCustomMixerBlock ------------------------------------------------}
  776. procedure TMMCustomMixerBlock.ChangeDesigning(Value: Boolean);
  777. begin
  778.   inherited;
  779.   FPanCtl.ChangeDesigning(Value);
  780.   FVolumeCtl.ChangeDesigning(Value);
  781.   FMuteCtl.ChangeDesigning(Value);
  782.   FConnector.ChangeDesigning(Value);
  783.   FPeakCtl.ChangeDesigning(Value);
  784. end;
  785. {$ENDIF}
  786. {-- TMMCustomMixerBlock ------------------------------------------------}
  787. procedure TMMCustomMixerBlock.UpdateBlock;
  788. begin
  789.    if (csDestroying in ComponentState) then
  790.        Exit;
  791.    if not (csLoading in ComponentState) then
  792.    begin
  793.       CollectControls;
  794.       if csDesigning in ComponentState then
  795.       begin
  796.          if Style = bsWin95 then
  797.          begin
  798.             if FPan <> nil then
  799.                FPan.Style := ssWin95;
  800.             if FVolumeLeft <> nil then
  801.                FVolumeLeft.Style := ssWin95;
  802.             if FVolumeRight <> nil then
  803.                FVolumeRight.Style := ssWin95;
  804.             if FLevelLeft <> nil then
  805.                FLevelLeft.Style := lsWin95;
  806.             if FLevelRight <> nil then
  807.                FLevelRight.Style := lsWin95;
  808.          end;
  809.       end;
  810.       ConnectControls;
  811.       ArrangeControls;
  812.    end;
  813. end;
  814. {-- TMMCustomMixerBlock ------------------------------------------------}
  815. procedure TMMCustomMixerBlock.MMSetParent(var Msg: TMMSetParent);
  816. begin
  817.    inherited;
  818.    case TMMSetParentAction(Msg.Action) of
  819.         saRemove    : FRemoving := Msg.Control;
  820.         saInsNoRole : if (csDesigning in ComponentState) and
  821.                           not (csLoading in ComponentState) and
  822.                           not (csReading in ComponentState) then
  823.                               InsertCtl(Msg.Control); { Change control's role if needed }
  824.         saInsert    :;
  825.         saUpdate    :;
  826.    end;
  827.    UpdateBlock;
  828. end;
  829. {-- TMMCustomMixerBlock ------------------------------------------------}
  830. procedure TMMCustomMixerBlock.Notification(AComponent: TComponent; Operation: TOperation);
  831. begin
  832.    inherited Notification(AComponent,Operation);
  833.    if Operation = opRemove then
  834.       if AComponent = Line then
  835.          Line := nil
  836.       else if AComponent = Mixer then
  837.           Mixer := nil
  838.       else if AComponent is TControl then
  839.            if FindBlock(AComponent as TControl) = Self then
  840.               UpdateBlock;
  841. end;
  842. {-- TMMCustomMixerBlock ------------------------------------------------}
  843. procedure TMMCustomMixerBlock.InsertCtl(C: TComponent);
  844. begin
  845.    if (C is TMMCustomBlockSlider) then
  846.    begin
  847.       if FPan = nil then
  848.          (C as TMMCustomBlockSlider).Role := srPan
  849.       else if FVolumeLeft = nil then
  850.          (C as TMMCustomBlockSlider).Role := srLeftVolume
  851.       else if FVolumeRight = nil then
  852.          (C as TMMCustomBlockSlider).Role := srRightVolume
  853.       else
  854.          Exit;
  855.    end
  856.    else if C is TMMCustomBlockLevel then
  857.    begin
  858.       if FLevelLeft = nil then
  859.          (C as TMMCustomBlockLevel).Role := lrLeftLevel
  860.       else if FLevelRight = nil then
  861.          (C as TMMCustomBlockLevel).Role := lrRightLevel
  862.       else
  863.           Exit;
  864.    end
  865.    else if C is TMMCustomBlockLabel then
  866.    begin
  867.       if FLineTitle = nil then
  868.          (C as TMMCustomBlockLabel).Role := lrLineTitle
  869.       else if FPanTitle = nil then
  870.          (C as TMMCustomBlockLabel).Role := lrPanTitle
  871.       else if FVolumeTitle = nil then
  872.          (C as TMMCustomBlockLabel).Role := lrVolumeTitle
  873.       else
  874.          Exit;
  875.    end
  876.    else Exit;
  877. end;
  878. {-- TMMCustomMixerBlock ------------------------------------------------}
  879. procedure TMMCustomMixerBlock.SetLine(Value: TMMAudioLine);
  880. begin
  881.    if Value <> FLine then
  882.    begin
  883.       if FLine <> nil then
  884.       begin
  885.          FLine.RemoveObserver(FObserver);
  886.          DisconnectLine;
  887.       end;
  888.       FLine := Value;
  889.       if FLine <> nil then
  890.       begin
  891.          FLine.AddObserver(FObserver);
  892.          ConnectLine;
  893.       end;
  894.       ConnectControls;
  895.       ArrangeControls;
  896.    end;
  897. end;
  898. {-- TMMCustomMixerBlock ------------------------------------------------}
  899. procedure TMMCustomMixerBlock.LineNotify(Sender, Data : TObject);
  900. begin
  901.    if (Data = nil) or (Data is TMMLineIdChange) then
  902.    begin
  903.       ConnectControls;
  904.       ArrangeControls;
  905.    end;
  906. end;
  907. {-- TMMCustomMixerBlock ------------------------------------------------}
  908. procedure TMMCustomMixerBlock.Loaded;
  909. begin
  910.    inherited Loaded;
  911.    UpdateBlock;
  912. end;
  913. {-- TMMCustomMixerBlock ------------------------------------------------}
  914. procedure TMMCustomMixerBlock.ArrangeControls;
  915. var
  916.    R     : TRect;
  917.    HSpace: Integer;
  918.    VSpace: Integer;
  919.    VolW  : Integer;
  920.    PeakW : Integer;
  921.    procedure SubTop(Value: Integer);
  922.    begin
  923.       if R.Top + Value <= R.Bottom then
  924.          R.Top := R.Top + Value
  925.       else
  926.          R.Top := R.Bottom;
  927.    end;
  928.    procedure SubBottom(Value: Integer);
  929.    begin
  930.       if R.Bottom - Value >= R.Top then
  931.          R.Bottom := R.Bottom - Value
  932.       else
  933.          R.Bottom := R.Top;
  934.    end;
  935.    function ShouldArrange(C: TControl): Boolean;
  936.    begin
  937.     Result := AutoArrange and (C.Parent = Self);
  938.    end;
  939.    procedure PutAtTop;
  940.    begin
  941.       if FLineTitle <> nil then
  942.       begin
  943.          if ShouldArrange(FLineTitle) then
  944.          begin
  945.              FLineTitle.Top      := R.Top;
  946.              FLineTitle.Left     := R.Left;
  947.              if AutoSize then
  948.                 FLineTitle.Width    := R.Right - R.Left;
  949.              SubTop(FLineTitle.Height+VSpace);
  950.          end;
  951.          if Line = nil then
  952.             FLineTitle.Caption := 'Not connected'
  953.          else
  954.             FLineTitle.Caption := Line.LineInfo.Name;
  955.       end;
  956.       if FPanTitle <> nil then
  957.       begin
  958.          if ShouldArrange(FPanTitle) then
  959.          begin
  960.              FPanTitle.Top       := R.Top;
  961.              FPanTitle.Left      := R.Left;
  962.              if AutoSize then
  963.                 FPanTitle.Width     := R.Right - R.Left;
  964.          end;
  965.          { TODO: Should be resource id }
  966.          FPanTitle.Caption   := 'Balance:';
  967.          SubTop(FPanTitle.Height);
  968.       end;
  969.       if FPan <> nil then
  970.       begin
  971.          if ShouldArrange(FPan) then
  972.          begin
  973.              FPan.Top         := R.Top;
  974.              if AutoSize then
  975.              begin
  976.                  FPan.Left        := R.Left;
  977.                  FPan.Width       := R.Right - R.Left;
  978.              end
  979.              else
  980.                  FPan.Left        := R.Left + (R.Right - R.Left - FPan.Width) div 2;
  981.              SubTop(FPan.Height+VSpace);
  982.          end;
  983.       end;
  984.       SubTop(VSpace);
  985.       if FVolumeTitle <> nil then
  986.       begin
  987.          if ShouldArrange(FVolumeTitle) then
  988.          begin
  989.              FVolumeTitle.Top     := R.Top;
  990.              FVolumeTitle.Left    := R.Left;
  991.              if AutoSize then
  992.                 FVolumeTitle.Width   := R.Right - R.Left;
  993.          end;
  994.          FVolumeTitle.Caption := 'Volume:';
  995.          SubTop(FVolumeTitle.Height);
  996.       end;
  997.     end;
  998.     procedure PutAtBottom;
  999.     begin
  1000.        if FMute <> nil then
  1001.        begin
  1002.           if ShouldArrange(FMute) then
  1003.           begin
  1004.             FMute.Top    := R.Bottom - FMute.Height;
  1005.             if AutoSize then
  1006.             begin
  1007.                 FMute.Left   := R.Left;
  1008.                 FMute.Width  := R.Right - R.Left;
  1009.             end
  1010.             else
  1011.                 FMute.Left   := R.Left + (R.Right - R.Left - FMute.Width) div 2;
  1012.             SubBottom(FMute.Height + VSpace);
  1013.           end;
  1014.        end;
  1015.     end;
  1016.     procedure PutAtCenter;
  1017.     var
  1018.        Vol, Peak : Boolean;
  1019.        W         : Integer;
  1020.        procedure PutRect(C1, C2: TControl; R : TRect);
  1021.        begin
  1022.           if not AutoArrange then
  1023.             Exit;
  1024.             
  1025.           if C1 <> nil then
  1026.           begin
  1027.              if AutoSize then
  1028.              begin
  1029.                  C1.Top      := R.Top;
  1030.                  C1.Height   := R.Bottom - R.Top;
  1031.                  C1.Left     := R.Left;
  1032.                  if C2 <> nil then
  1033.                     C1.Width := (R.Right - R.Left) div 2 - HSpace div 2
  1034.                  else
  1035.                     C1.Width := (R.Right - R.Left);
  1036.              end
  1037.              else
  1038.              begin
  1039.                  C1.Top      := R.Top + (R.Bottom - R.Top - C1.Height) div 2;
  1040.                  if C2 <> nil then
  1041.                     C1.Left  := R.Left + ((R.Right - R.Left) div 2 - HSpace div 2 - C1.Width) div 2
  1042.                  else
  1043.                     C1.Left  := R.Left + ((R.Right - R.Left) - C1.Width) div 2;
  1044.              end;
  1045.           end;
  1046.           if C2 <> nil then
  1047.           begin
  1048.              if AutoSize then
  1049.              begin
  1050.                  C2.Top     := R.Top;
  1051.                  C2.Height  := R.Bottom - R.Top;
  1052.                  if C1 <> nil then
  1053.                     C2.Left := R.Left + (R.Right - R.Left) div 2 + HSpace div 2
  1054.                  else
  1055.                     C2.Left := R.Left;
  1056.                  C2.Width   := R.Right - C2.Left;
  1057.              end
  1058.              else
  1059.              begin
  1060.                  C2.Top     := R.Top + (R.Bottom - R.Top - C2.Height) div 2;
  1061.                  if C1 <> nil then
  1062.                     C2.Left := R.Left + (R.Right - R.Left) div 2 + HSpace div 2 + (((R.Right - R.Left) div 2 - HSpace div 2) - C2.Width) div 2
  1063.                  else
  1064.                     C2.Left := R.Left + (R.Right - R.Left - C2.Width) div 2;
  1065.              end;
  1066.           end;
  1067.        end;
  1068.        procedure PutVol(R: TRect);
  1069.        begin
  1070.           PutRect(FVolumeLeft,FVolumeRight,R);
  1071.        end;
  1072.        procedure PutLev(R: TRect);
  1073.        begin
  1074.           PutRect(FLevelLeft,FLevelRight,R);
  1075.        end;
  1076.     begin
  1077.         Vol     := (FVolumeLeft <> nil) or (FVolumeRight <> nil);
  1078.         Peak    := ((FLevelLeft <> nil) or (FLevelRight <> nil)) and
  1079.                    ((csDesigning in ComponentState) or (FPeakCtl.Available));
  1080.         W       := R.Right - R.Left;
  1081.         VolW    := 3 * (W div 4);
  1082.         PeakW   := W - VolW;
  1083.         if FLevelLeft <> nil then
  1084.         begin
  1085.            FLevelLeft.Kind      := lkVertical;
  1086.            FLevelLeft.Visible   := Peak;
  1087.         end;
  1088.         if FLevelRight <> nil then
  1089.         begin
  1090.            FLevelRight.Kind     := lkVertical;
  1091.            FLevelRight.Visible  := Peak;
  1092.         end;
  1093.         if Vol and Peak then
  1094.         begin
  1095.            PutVol(Bounds(R.Left,R.Top,VolW,R.Bottom-R.Top));
  1096.            PutLev(Bounds(R.Left+VolW,R.Top,PeakW,R.Bottom-R.Top));
  1097.         end
  1098.         else if Vol then
  1099.              PutVol(R)
  1100.         else if Peak then
  1101.             PutLev(R);
  1102.     end;
  1103. begin
  1104.    if (csLoading in ComponentState) or
  1105. {$IFNDEF BUILD_ACTIVEX}
  1106.       (Parent = nil) then
  1107. {$ELSE}
  1108.       (ParentWindow = 0) then
  1109. {$ENDIF}
  1110.        Exit;
  1111.    HSpace := Canvas.TextWidth('A');
  1112.    VSpace := Canvas.TextHeight('A') div 2;
  1113.    if Style = bsWin95 then
  1114.    begin
  1115.       R := ClientRect;
  1116.       InflateRect(R,-BevelExtend-HSpace,-BevelExtend-VSpace);
  1117.       PutAtTop;
  1118.       PutAtBottom;
  1119.       PutAtCenter;
  1120.       if AutoArrange then
  1121.       begin
  1122.           if FPan <> nil then
  1123.           begin
  1124.              FPan.TabOrder := 0;
  1125.              FPan.TabStop := True;
  1126.           end;
  1127.           if FVolumeLeft <> nil then
  1128.           begin
  1129.              FVolumeLeft.TabOrder := 1;
  1130.              FVolumeLeft.TabStop := True;
  1131.           end;
  1132.           if FVolumeRight <> nil then
  1133.           begin
  1134.              FVolumeRight.TabOrder := 2;
  1135.              FVolumeRight.TabStop := True;
  1136.           end;
  1137.           if FMute <> nil then
  1138.           begin
  1139.              FMute.TabOrder := 3;
  1140.              FMute.TabStop := True;
  1141.           end;
  1142.       end;
  1143.    end;
  1144. end;
  1145. {-- TMMCustomMixerBlock ------------------------------------------------}
  1146. procedure TMMCustomMixerBlock.SetAutoArrange(Value: Boolean);
  1147. begin
  1148.    if Value <> FAutoArrange then
  1149.    begin
  1150.       FAutoArrange := Value;
  1151.       ArrangeControls;
  1152.    end;
  1153. end;
  1154. {-- TMMCustomMixerBlock ------------------------------------------------}
  1155. procedure TMMCustomMixerBlock.SetAutoSize(Value: Boolean);
  1156. begin
  1157.    if Value <> FAutoSize then
  1158.    begin
  1159.       FAutoSize := Value;
  1160.       ArrangeControls;
  1161.    end;
  1162. end;
  1163. {-- TMMCustomMixerBlock ------------------------------------------------}
  1164. procedure TMMCustomMixerBlock.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  1165. begin
  1166.    inherited SetBounds(ALeft,ATop,AWidth,AHeight);
  1167.    ArrangeControls;
  1168. end;
  1169. {-- TMMCustomMixerBlock ------------------------------------------------}
  1170. procedure TMMCustomMixerBlock.SetStyle(Value: TMMBlockStyle);
  1171. begin
  1172.    if Value <> FStyle then
  1173.    begin
  1174.       FStyle := Value;
  1175.       UpdateBlock;
  1176.    end;
  1177. end;
  1178. {-- TMMCustomMixerBlock ------------------------------------------------}
  1179. procedure TMMCustomMixerBlock.ConnectLine;
  1180. begin
  1181.    FPanCtl.AudioLine    := FLine;
  1182.    FVolumeCtl.AudioLine := FLine;
  1183.    FMuteCtl.AudioLine   := FLine;
  1184.    FPeakCtl.AudioLine   := FLine;
  1185. end;
  1186. {-- TMMCustomMixerBlock ------------------------------------------------}
  1187. procedure TMMCustomMixerBlock.DisconnectLine;
  1188. begin
  1189.    FPanCtl.AudioLine    := nil;
  1190.    FVolumeCtl.AudioLine := nil;
  1191.    FMuteCtl.AudioLine   := nil;
  1192.    FPeakCtl.AudioLine   := nil;
  1193. end;
  1194. {-- TMMCustomMixerBlock ------------------------------------------------}
  1195. procedure TMMCustomMixerBlock.ConnectControls;
  1196. var
  1197.     AItem: TMMItemIndex;
  1198. begin
  1199.    if FPan <> nil then
  1200.       FPan.Control    := FPanCtl;
  1201.    if FMute <> nil then
  1202.    begin
  1203.       AItem := NoItem;
  1204.       if (Mixer <> nil) and Mixer.Available and (Line <> nil) then
  1205.           if Item = NoItem then
  1206.              AItem := Mixer.GetItemForLine(Line)
  1207.           else
  1208.              AItem := Item;
  1209.       if AItem <> NoItem then
  1210.       begin
  1211.          FMute.Control   := Mixer;
  1212.          FMute.Item      := AItem;
  1213.       end
  1214.       else
  1215.       begin
  1216.          FMute.Control   := FMuteCtl;
  1217.          FMute.Item      := NoItem;
  1218.       end;
  1219.    end;
  1220.    if FVolumeLeft <> nil then
  1221.    begin
  1222.       FVolumeLeft.Control := FVolumeCtl;
  1223.       if FVolumeRight = nil then
  1224.          FVolumeLeft.Channel := chBoth
  1225.       else
  1226.          FVolumeLeft.Channel := chLeft
  1227.    end;
  1228.    if FVolumeRight <> nil then
  1229.    begin
  1230.       FVolumeRight.Control := FVolumeCtl;
  1231.       if FVolumeLeft = nil then
  1232.          FVolumeRight.Channel := chBoth
  1233.       else
  1234.          FVolumeRight.Channel := chRight
  1235.    end;
  1236.    if FLevelLeft <> nil then
  1237.       FConnector.Level1 := FLevelLeft;
  1238.    if FLevelRight <> nil then
  1239.       FConnector.Level2 := FLevelRight;
  1240. end;
  1241. {-- TMMCustomMixerBlock ------------------------------------------------}
  1242. function TMMCustomMixerBlock.GetMuteKind: TMMMuteKind;
  1243. begin
  1244.    if (FMute <> nil) and (Mixer <> nil) and (FMute.Control = Mixer) then
  1245.        Result := mkSelect
  1246.    else
  1247.        Result := mkMute;
  1248. end;
  1249. {-- TMMCustomMixerBlock ------------------------------------------------}
  1250. procedure TMMCustomMixerBlock.CollectControls;
  1251.    procedure SetCtl(var P; C: TControl);
  1252.    begin
  1253.       TControl(P) := C;
  1254.    end;
  1255.    function  CheckCtl(C: TControl): Boolean;
  1256.    begin
  1257.       Result := False;
  1258.       if C = FRemoving then
  1259.          Exit;
  1260.       if C is TMMCustomBlockSlider then
  1261.       begin
  1262.          with C as TMMCustomBlockSlider do
  1263.          if Role = srPan then
  1264.             SetCtl(FPan,C)
  1265.          else if Role = srLeftVolume then
  1266.             SetCtl(FVolumeLeft,C)
  1267.          else if Role = srRightVolume then
  1268.             SetCtl(FVolumeRight,C)
  1269.       end
  1270.       else if C is TMMCustomBlockCheck then
  1271.             SetCtl(FMute,C)
  1272.       else if C is TMMCustomBlockLevel then
  1273.       begin
  1274.           with C as TMMCustomBlockLevel do
  1275.           if Role = lrLeftLevel then
  1276.              SetCtl(FLevelLeft,C)
  1277.           else if Role = lrRightLevel then
  1278.              SetCtl(FLevelRight,C)
  1279.       end
  1280.       else if C is TMMCustomBlockLabel then
  1281.       begin
  1282.          with C as TMMCustomBlockLabel do
  1283.          if Role = lrLineTitle then
  1284.             SetCtl(FLineTitle,C)
  1285.          else if Role = lrPanTitle then
  1286.             SetCtl(FPanTitle,C)
  1287.          else if Role = lrVolumeTitle then
  1288.             SetCtl(FVolumeTitle,C)
  1289.       end
  1290.       else
  1291.         Exit;
  1292.       Result := True;
  1293.    end;
  1294.    procedure Process(C: TWinControl);
  1295.    var
  1296.     i: Integer;
  1297.    begin
  1298.        for i := 0 to C.ControlCount - 1 do
  1299.         if not CheckCtl(C.Controls[i]) and (C.Controls[i] is TWinControl) then
  1300.             Process(C.Controls[i] as TWinControl);
  1301.    end;
  1302. begin
  1303.    FPan        := nil;
  1304.    FVolumeLeft := nil;
  1305.    FVolumeRight:= nil;
  1306.    FMute       := nil;
  1307.    FLevelLeft  := nil;
  1308.    FLevelRight := nil;
  1309.    FLineTitle  := nil;
  1310.    FPanTitle   := nil;
  1311.    FVolumeTitle:= nil;
  1312.    Process(Self);
  1313.    FRemoving := nil;
  1314. end;
  1315. {-- TMMCustomMixerBlock ------------------------------------------------}
  1316. procedure TMMCustomMixerBlock.SetMixer(Value: TMMCustomMixerControl);
  1317. begin
  1318.    if Value <> FMixer then
  1319.    begin
  1320.       if FMixer <> nil then
  1321.          FMixer.RemoveObserver(FMixObserver);
  1322.       FMixer := Value;
  1323.       if FMixer <> nil then
  1324.       begin
  1325.          FMixer.AddObserver(FMixObserver);
  1326.          FMixer.FreeNotification(Self);
  1327.       end;
  1328.       UpdateBlock;
  1329.    end;
  1330. end;
  1331. {-- TMMCustomMixerBlock ------------------------------------------------}
  1332. procedure TMMCustomMixerBlock.MixNotify(Sender, Data: TObject);
  1333. begin
  1334.    if (Data = nil) or (Data is TMMControlIdChange) then
  1335.        UpdateBlock;
  1336. end;
  1337. {-- TMMCustomMixerBlock ------------------------------------------------}
  1338. procedure TMMCustomMixerBlock.SetItem(Value: TMMItemIndex);
  1339. begin
  1340.    if Value <> FItem then
  1341.    begin
  1342.       FItem := Value;
  1343.       UpdateBlock;
  1344.    end;
  1345. end;
  1346. end.