Files
AC_Pro/VolumeFormUnit.cpp
2026-06-13 00:05:19 +08:00

614 lines
16 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "VolumeFormUnit.h"
#include "GlobalUnit.h"
#include "Undo.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//#pragma link "GeneralDialogPanel"
#pragma link "SkinTrackBar"
#pragma link "LineEdit"
#pragma resource "*.dfm"
TVolumeForm *VolumeForm;
#define PLAY_TYPE 0x00
#define INPUT_TYPE 0x01
#define COMPOSE_TYPE 0x04
#define VOICE_TYPE 0x10
#define FramColor TColor(0xAA9C91)
#define BkColor TColor(0x453F3A)
#define GroupFrame TColor(0x322F2B)
//---------------------------------------------------------------------------
__fastcall TVolumeForm::TVolumeForm(TComponent* Owner)
: TForm(Owner)
{
m_pTimer = NULL;
m_bRecording = false;
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::DoFormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if(X <= 0 || Y <= 0 || X >= Width || Y >= Height)
{
ModalResult = mrCancel;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::DoFormShow(TObject *Sender)
{
TPoint clientPos = ScreenToClient(Mouse->CursorPos);
if(clientPos.X > 0 && clientPos.Y > 0 &&
clientPos.X < Width && clientPos.Y < Height)
{
m_IsMouseOver = true;
MouseCapture = false;
}
else
{
m_IsMouseOver = false;
MouseCapture = true;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::CMMouseEnter(TMessage &Message)
{
TPoint clientPos = ScreenToClient(Mouse->CursorPos);
if(clientPos.X >= 0 && clientPos.Y >= 0 &&
clientPos.X <= Width && clientPos.Y <= Height && !m_IsMouseOver)
{
m_IsMouseOver = true;
if(MouseCapture)
MouseCapture = false;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::CMMouseLeave(TMessage &Message)
{
TPoint clientPos = ScreenToClient(Mouse->CursorPos);
if(clientPos.X <= 0 || clientPos.Y <= 0 ||
clientPos.X >= Width || clientPos.Y >= Height)
{
m_IsMouseOver = false;
if(!MouseCapture)
MouseCapture = true;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::WMKillFocus(TWMKillFocus &Message)
{
if(!m_IsMouseOver)
ModalResult = mrCancel;
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::OnMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
int X, int Y)
{
if(X < 0 || Y < 0 || X > Width || Y > Height)
{
ModalResult = mrCancel;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::MouseMove(TShiftState Shift, int X, int Y)
{
if(MouseCapture && X > 0 && X < Width && Y > 0 && Y < Height)
{
m_IsMouseOver = true;
if(MouseCapture)
MouseCapture = false;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
switch( Key ){
case VK_RETURN:
ModalResult = mrOk;
break;
case VK_ESCAPE:
ModalResult = mrCancel;
break;
case 'Z':
if( !m_bRecording && Shift.Contains( ssCtrl ) && !m_pTimer ){
int iType = -1;
if( Shift.Contains( ssShift ) ){
iType = g_Undo.GetRedoType();
if( iType==UNDO_VOLUME )
Undo( false );
}
else{
iType = g_Undo.GetUndoType();
if( iType==UNDO_VOLUME )
Undo( true );
}
if( iType>UNDO_VOLUME )
ModalResult = mrCancel;
}
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::WMEraseBkgnd(Winapi::Messages::TWMEraseBkgnd &Message)
{
TRect rect = GetClientRect();
TRect rectFill = rect;
TCanvas* tempCanvas = new TCanvas;
tempCanvas->Handle = Message.DC;
//»æÖƵ×É«
tempCanvas->Brush->Color = TColor(0x004D4641);
tempCanvas->FillRect( rectFill );
tempCanvas->Brush->Color = FramColor;
tempCanvas->FrameRect( rect );
tempCanvas->Pen->Color = GroupFrame;
tempCanvas->Brush->Color = BkColor;
tempCanvas->RoundRect(10, 10, 110, Height - 10, 5, 5);
tempCanvas->MoveTo(60, 15);
tempCanvas->LineTo(60, Height - 15);
int nTB = m_aTracks.size();
if( nTB>0 ){
int w = 14*2 + nTB * 20 + (nTB-1)* 32;
tempCanvas->RoundRect(115, 10, w+115, Height - 10, 5, 5);
int l = 115 + 14 + 20 + 16;
for( int i=1; i<nTB; i++ ){
tempCanvas->MoveTo(l, 15);
tempCanvas->LineTo(l, Height - 15);
l += 20 + 32;
}
}
delete tempCanvas;
Message.Result = true;
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::FormCreate(TObject *Sender)
{
m_InputTrackBar->Position = (int)( (double)g_fRecordVolume * 100 + 0.5 );
m_InputTrackBar->OnChange = DoVolumeChanged;
m_ShowInput->Caption = IntToStr( m_InputTrackBar->Position );
m_PlayTrackBar->Position = (int)( (double)g_fSpeakerVolume * 100 + 0.5 );
m_PlayTrackBar->OnChange = DoVolumeChanged;
m_ShowPlay->Caption = IntToStr( m_PlayTrackBar->Position );
int lPos = 129;
if( g_lstOpusStages.size()>0 ){
TSkinTrackBar* pTB = new TSkinTrackBar( this );
pTB->Orientation = false;
pTB->Parent = this;
pTB->Tag = COMPOSE_TYPE;
pTB->SetBounds( lPos, 34, 20, 150 );
pTB->Position = (int)( (double)g_fMusicVolume * 100 + 0.5 );
pTB->Enabled = !g_bComposeMute;
pTB->OnChange = DoVolumeChanged;
m_aTracks.push_back( pTB );
TCKBox* pCB = new TCKBox(this);
pCB->Parent = this;
pCB->Caption = "";
pCB->SetBounds( lPos-2, 184, 24, 16 );
pCB->Checked = !g_bComposeMute;
// pCB->Hint = "Õý³£/¾²Òô";
// pCB->ShowHint = true;
pCB->OnChange = DoTrackMute;
m_aChecks.push_back( pCB );
TLabel* pLB = new TLabel(this);
pLB->Parent = this;
pLB->AutoSize = false;
pLB->Caption = IntToStr( pTB->Position );
pLB->Alignment = taCenter;
pLB->SetBounds( lPos-6, 15, 30, 13 );
m_aLabels.push_back( pLB );
pLB = new TLabel(this);
pLB->Parent = this;
pLB->AutoSize = false;
pLB->Caption = "°é×à";
pLB->Alignment = taCenter;
pLB->SetBounds( lPos-1, 209, 24, 14 );
m_aLabels.push_back( pLB );
lPos += 20 + 32;
}
if( g_aAudioTracks.size()>1 ){
for( int i=1; i<g_aAudioTracks.size(); i++ ){
TSkinTrackBar* pTB = new TSkinTrackBar( this );
pTB->Orientation = false;
pTB->Parent = this;
pTB->Tag = VOICE_TYPE + i;
pTB->SetBounds( lPos, 34, 20, 150 );
pTB->Position = (int)( g_aAudioTracks[i]->volume );
pTB->Enabled = !g_aAudioTracks[i]->IsMute();
pTB->OnChange = DoVolumeChanged;
m_aTracks.push_back( pTB );
TCKBox* pCB = new TCKBox(this);
pCB->Parent = this;
pCB->Caption = "";
pCB->SetBounds( lPos-2, 184, 24, 16 );
pCB->Checked = !g_aAudioTracks[i]->IsMute();
pCB->OnChange = DoTrackMute;
m_aChecks.push_back( pCB );
TLabel* pLB = new TLabel(this);
pLB->Parent = this;
pLB->AutoSize = false;
pLB->Caption = IntToStr( pTB->Position );
pLB->Alignment = taCenter;
pLB->SetBounds( lPos-6, 15, 30, 13 );
m_aLabels.push_back( pLB );
pLB = new TLabel(this);
pLB->Parent = this;
pLB->AutoSize = false;
pLB->Caption = "Òô¹ì" + IntToStr( i );
pLB->Alignment = taCenter;
pLB->SetBounds( lPos-6, 209, 32, 14 );
m_aLabels.push_back( pLB );
lPos += 20 + 32;
}
}
else if( g_aAudioTracks[0]->lstBars.size()>0 ){
TSkinTrackBar* pTB = new TSkinTrackBar( this );
pTB->Orientation = false;
pTB->Parent = this;
pTB->Tag = VOICE_TYPE;
pTB->SetBounds( lPos, 34, 20, 150 );
pTB->Position = (int)( g_aAudioTracks[0]->volume );
pTB->Enabled = !g_aAudioTracks[0]->IsMute();
pTB->OnChange = DoVolumeChanged;
m_aTracks.push_back( pTB );
TCKBox* pCB = new TCKBox(this);
pCB->Parent = this;
pCB->Caption = "";
pCB->SetBounds( lPos-2, 184, 24, 16 );
pCB->Checked = !g_aAudioTracks[0]->IsMute();
pCB->OnChange = DoTrackMute;
m_aChecks.push_back( pCB );
TLabel* pLB = new TLabel(this);
pLB->Parent = this;
pLB->AutoSize = false;
pLB->Caption = IntToStr( pTB->Position );
pLB->Alignment = taCenter;
pLB->SetBounds( lPos-6, 15, 30, 13 );
m_aLabels.push_back( pLB );
pLB = new TLabel(this);
pLB->Parent = this;
pLB->AutoSize = false;
pLB->Caption = "Òô¹ì" + IntToStr( 1 );
pLB->Alignment = taCenter;
pLB->SetBounds( lPos-6, 209, 32, 14 );
m_aLabels.push_back( pLB );
}
int nTB = m_aTracks.size();
if( nTB>0 ){
Width += 5 + 14*2 + nTB * 20 + (nTB-1)* 32;
}
SetTransparent( this );
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::FormDestroy(TObject *Sender)
{
for( int i=0; i<m_aTracks.size(); i++ ){
delete m_aTracks[i];
delete m_aChecks[i];
delete m_aLabels[i*2];
delete m_aLabels[i*2+1];
}
if( m_pTimer ){
if( m_pTimer->Enabled ){
TimerProc( m_pTimer );
}
else{
delete m_pTimer;
m_pTimer = NULL;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::DoVolumeChanged(TObject *Sender)
{
TSkinTrackBar* pTB = (TSkinTrackBar*)Sender;
TLabel* pVLB = NULL;
float fVol = pTB->Position / 100.0;
if( pTB->Tag<VOICE_TYPE )
f_MM_SetStreamVolume( pTB->Tag, fVol );
if( pTB->Tag==PLAY_TYPE ){
g_fSpeakerVolume = fVol;
pVLB = m_ShowPlay;
}
else if( pTB->Tag==INPUT_TYPE ){
g_fRecordVolume = fVol;
pVLB = m_ShowInput;
}
else{
int iUndoCode = pTB->Tag;
int volBefore = 0, volAfter = pTB->Position;
if( pTB->Tag==COMPOSE_TYPE ){
volBefore = (int)( (double)g_fMusicVolume * 100 + 0.5 );
g_fMusicVolume = fVol;
pVLB = m_aLabels[0];
}
else{
int iTrack = pTB->Tag & 0x0F;
if( !IsTrackMute( ST_AUDIO, iTrack ) )
f_MM_SetAudioTrackParam( iTrack, 0, fVol );
volBefore = g_aAudioTracks[iTrack]->volume;
g_aAudioTracks[iTrack]->volume = pTB->Position;
for( int i=0; i<m_aTracks.size(); i++ ){
if( m_aTracks[i]==pTB ){
pVLB = m_aLabels[i*2];
break;
}
}
PostMessage( Application->MainFormHandle, UM_AUDIOVOLCHANGED, iTrack, 0 );
}
bool bAddUndo = true;
TUndoLite* pLite = g_Undo.GetLastLite();
if( pLite && pLite->iType==UNDO_VOLUME && pLite->iCode==iUndoCode
&& (int)pLite->pBefore>=0 && (int)pLite->pAfter>=0 ){
bAddUndo = false;
if( (int)pLite->pBefore==volAfter ){
g_Undo.CancelUndo();
}
else{
pLite->pAfter = (void*)volAfter;
}
}
if( bAddUndo ){
g_Undo.AddUndo( UNDO_VOLUME, iUndoCode, 0, 0,
(void*)volBefore, (void*)volAfter );
}
}
if( pVLB )
pVLB->Caption = String((int)(pTB->Position));
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::DoTrackMute(TObject *Sender)
{
for( int i=0; i<m_aChecks.size(); i++ ){
if( m_aChecks[i]==Sender ){
bool bNoMute = m_aChecks[i]->Checked;
float fVol = bNoMute ? m_aTracks[i]->Position / 100.0 : 0;
int volBefore, volAfter;
m_aTracks[i]->Enabled = bNoMute;
if( m_aTracks[i]->Tag==COMPOSE_TYPE ){
g_bComposeMute = !bNoMute;
f_MM_SetStreamVolume( m_aTracks[i]->Tag, fVol );
volBefore = bNoMute ? -1 : m_aTracks[i]->Position,
volAfter = bNoMute ? m_aTracks[i]->Position : -1;
}
else{
int iTrack = m_aTracks[i]->Tag & 0x0F;
bool bSet = false, bUnset = false;
ChangeTrackState( ST_AUDIO, iTrack, TRACK_MUTE, bSet, bUnset );
PostMessage( Application->MainFormHandle, UM_AUDIOVOLCHANGED, iTrack,
MAKELONG( TRACK_MUTE, bUnset ) );
volBefore = bNoMute ? -1 : bUnset,
volAfter = bNoMute ? bUnset : -1;
}
bool bAddUndo = true;
TUndoLite* pLite = g_Undo.GetLastLite();
if( pLite && pLite->iType==UNDO_VOLUME && pLite->iCode==m_aTracks[i]->Tag
&& (int)pLite->pBefore==volAfter
&& (int)pLite->pAfter==volBefore ){
g_Undo.CancelUndo();
bAddUndo = false;
}
if( bAddUndo ){
g_Undo.AddUndo( UNDO_VOLUME, m_aTracks[i]->Tag, 0, 0,
(void*)volBefore, (void*)volAfter );
}
break;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::TimerProc(TObject* Sender)
{
if( m_pTimer ){
m_pTimer->Enabled = false;
Undo( m_pTimer->Tag );
delete m_pTimer;
m_pTimer = NULL;
}
}
//---------------------------------------------------------------------------
int __fastcall TVolumeForm::ShowUndo( bool bUndo )
{
if( !m_pTimer ){
m_pTimer = new TTimer(this);
m_pTimer->OnTimer = TimerProc;
m_pTimer->Interval = 100;
m_pTimer->Tag = bUndo ? 1 : 0;
m_pTimer->Enabled = true;
}
return ShowModal();
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::OnRecord( bool bRecord )
{
m_bRecording = bRecord;
int nTB = m_aTracks.size();
if( nTB>0 ){
for( int i=0; i<nTB; i++ ){
m_aTracks[i]->Enabled = !bRecord && m_aChecks[i]->Checked;
m_aChecks[i]->Enabled = !bRecord;
}
}
}
//---------------------------------------------------------------------------
void TVolumeForm::Undo( bool bUndo )
{
TUndoLite* pLite = bUndo ? g_Undo.Undo() : g_Undo.Redo();
int volSet = (int)( bUndo ? pLite->pBefore : pLite->pAfter );
bool bMuted = (int)pLite->pBefore < 0 || (int)pLite->pAfter < 0;
TSkinTrackBar* pTB = NULL;
TLabel* pVLB = NULL;
TCKBox* pCB = NULL;
if( pLite->iCode==COMPOSE_TYPE ){
pTB = m_aTracks[0];
pVLB = m_aLabels[0];
pCB = m_aChecks[0];
}
else{
for( int i=0; i<m_aTracks.size(); i++ ){
if( m_aTracks[i]->Tag==pLite->iCode ){
pTB = m_aTracks[i];
pVLB = m_aLabels[i*2];
pCB = m_aChecks[i];
break;
}
}
}
pTB->Enabled = volSet>=0;
pCB->OnChange = NULL;
pCB->Checked = volSet>=0;
pCB->OnChange = DoTrackMute;
if( bMuted ){
if( pLite->iCode==COMPOSE_TYPE ){
g_bComposeMute = volSet<0;
f_MM_SetStreamVolume( pLite->iCode, volSet<0 ? 0 : volSet / 100.0 );
}
else{
int iTrack = pLite->iCode & 0x0F;
bool bSolo = volSet>0;
int iState = bSolo ? TRACK_SOLO : TRACK_MUTE;
bool bSet = false, bUnset = false;
ChangeTrackState( ST_AUDIO, iTrack, iState, bSet, bUnset );
PostMessage( Application->MainFormHandle, UM_AUDIOVOLCHANGED, iTrack,
MAKELONG( iState, bUnset ) );
}
}
else if( volSet>=0 ){
float fVol = volSet / 100.0;
if( pLite->iCode==COMPOSE_TYPE ){
g_fMusicVolume = fVol;
f_MM_SetStreamVolume( pLite->iCode, fVol );
}
else{
int iTrack = pTB->Tag & 0x0F;
bool bStateChange = g_aAudioTracks[iTrack]->IsMute();
if( bStateChange ){
g_aAudioTracks[iTrack]->Mute(false);
}
else{
if( !IsTrackMute( ST_AUDIO, iTrack ) )
f_MM_SetAudioTrackParam( iTrack, 0, fVol );
g_aAudioTracks[iTrack]->volume = volSet;
PostMessage( Application->MainFormHandle, UM_AUDIOVOLCHANGED, iTrack, 0 );
}
}
pTB->OnChange = NULL;
pTB->Position = volSet;
pTB->OnChange = DoVolumeChanged;
pVLB->Caption = String(IntToStr(volSet));
}
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::FormClose(TObject *Sender, TCloseAction &Action)
{
PostMessage( Application->MainForm->Handle, UM_SHOW_VOLSET, 0, 0 );
}
//---------------------------------------------------------------------------
void __fastcall TVolumeForm::ChangeRecordVol()
{
m_InputTrackBar->OnChange = NULL;
m_InputTrackBar->Position = (int)( (double)g_fRecordVolume * 100 + 0.5 );
m_InputTrackBar->OnChange = DoVolumeChanged;
m_ShowInput->Caption = IntToStr( m_InputTrackBar->Position );
}
//---------------------------------------------------------------------------