14#include "../../ui/PlayableTrackButtonHandles.h"
20#include "../../../../CellularPanel.h"
24#include "../../../../ProjectWindows.h"
25#include "../../../../RefreshCode.h"
29#include "../../../../TrackArtist.h"
30#include "../../../../TrackPanel.h"
32#include "../../../../TrackPanelMouseEvent.h"
35#include "../../../../prefs/PrefsDialog.h"
36#include "../../../../prefs/ThemePrefs.h"
43#include <wx/combobox.h>
56 const wxMouseState &state = st.
state;
57 const wxRect &rect = st.
rect;
58 if (state.ButtonIsDown(wxMOUSE_BTN_LEFT)) {
60 std::vector<UIHandlePtr> results;
86 results.push_back(result);
146template<
typename Table >
150 auto pData =
static_cast<Table&
>(
handler ).mpData;
151 const auto pTrack =
static_cast<WaveTrack*
>(pData->pTrack);
152 auto &
project = pData->project;
155 menu.Check(
id,
id ==
findValue( *pTrack ) );
156 menu.Enable(
id, !unsafe );
197 return IdOfFormat( track.GetSampleFormat() );
232 int id =
event.GetId();
253 if (newFormat == pTrack->GetSampleFormat())
259 XO(
"Processing... 0%%"),
263 assert(pTrack->IsLeader());
268 sampleCount totalSamples = pTrack->GetSequenceSamplesCount();
274 auto progressUpdate = [&progress, &totalSamples, &processedSamples]
275 (
size_t newlyProcessedCount)->
void
277 processedSamples += newlyProcessedCount;
278 double d_processed = processedSamples.
as_double();
279 double d_total = totalSamples.
as_double();
280 int percentage{
static_cast<int>((d_processed / d_total) * 100) };
282 auto progressStatus = progress.Update(d_processed, d_total,
283 XO(
"Processing... %i%%").Format(percentage));
291 assert(pTrack->IsLeader());
292 pTrack->ConvertToSampleFormat(newFormat, progressUpdate);
298 XO(
"Format Change"));
343 static const auto fn = initFn< RateMenuTable >(
345 return IdOfRate( (
int)track.
GetRate() );
369static
int gRates[
nRates] = { 8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000,
370176400, 192000, 352800, 384000 };
375 for (
int i = 0; i<
nRates; i++) {
390 if (pLocked != pTrack)
391 pLocked->SyncLockAdjust(end1, end2);
396 wxString rateString = wxString::Format(
wxT(
"%.3f"), rate);
408 int id =
event.GetId();
434 rate.Printf(
wxT(
"%ld"),
lrint(pTrack->GetRate()));
451 S.StartVerticalLay(
true);
454 S.StartHorizontalLay(wxEXPAND,
false);
456 cb =
S.AddCombo(
XXO(
"New sample rate (Hz):"),
459#if defined(__WXMAC__)
465 S.EndHorizontalLay();
466 S.AddStandardButtons();
470 dlg.SetClientSize(dlg.GetSizer()->CalcMin());
473 if (dlg.ShowModal() != wxID_OK)
479 if (cb->GetValue().ToLong(&lrate) && lrate >= 1 && lrate <= 1000000)
481 newRate = (int)lrate;
486 XO(
"The entered value is invalid"),
543static std::vector<WaveChannelSubViewType>
AllTypes()
576 ? std::make_unique<Entry>(
582 auto &track = table.FindWaveTrack();
584 menu.Check(
id, view.GetMultiView());
593 static const auto initFn = [](
bool radio ){
return
599 const auto IdForType =
601 const auto begin = allTypes.begin();
603 (std::find(
begin, allTypes.end(), type) -
begin);
607 auto &track = table.FindWaveTrack();
611 const auto displays = view.GetDisplays();
612 const auto end = displays.end();
614 std::find_if(displays.begin(),
end,
616 return id == IdForType(type); }));
617 menu.Check(
id, check );
621 if ( !radio && displays.size() == 1 && check )
622 menu.Enable(
id,
false );
625 Append(Adapt<My>([type,
id](My &table) {
626 const auto pTrack = &table.FindWaveTrack();
628 const auto itemType =
629 view.GetMultiView() ? Entry::CheckItem : Entry::RadioItem;
630 return std::make_unique<Entry>( type.name.Internal(), itemType,
631 id, type.name.Msgid(),
633 initFn( !view.GetMultiView() ) );
646 if ( canMakeStereo ) {
651 auto &track = table.FindWaveTrack();
652 auto next = * ++
tracks.Find(&track);
656 track_cast<WaveTrack*>(next));
658 menu.Enable(
id, canMakeStereo );
681 #ifndef EXPERIMENTAL_DA
700 const auto pTrack =
static_cast<WaveTrack*
>(mpData->pTrack);
702 bool multi = !view.GetMultiView();
703 const auto &displays = view.GetDisplays();
704 const auto display = displays.empty()
706 view.SetMultiView(multi);
711 view.SetDisplay(display, !multi);
717 int idInt =
event.GetId();
725 if (view.GetMultiView()) {
736 const auto displays = view.GetDisplays();
737 const bool wrongType =
738 !(displays.size() == 1 && displays[0].id ==
id);
758 const auto left = *first;
759 const auto right = *std::next(first);
763 auto eqTrims = [](
double a,
double b)
765 return std::abs(a - b) <=
766 std::numeric_limits<double>::epsilon() * std::max(a, b);
768 const auto eps = 0.5 / left.GetRate();
769 const auto rightIntervals = right.Intervals();
770 for(
const auto& a : left.Intervals())
772 auto it = std::find_if(
773 rightIntervals.begin(),
774 rightIntervals.end(),
778 return std::abs(a->Start() - b->Start()) < eps &&
779 std::abs(a->End() - b->End()) < eps &&
780 eqTrims(a->GetTrimLeft(), b->GetTrimLeft()) &&
781 eqTrims(a->GetTrimRight(), b->GetTrimRight()) &&
782 a->StretchRatioEquals(b->GetStretchRatio());
784 if(it == rightIntervals.end())
792 !checkAligned(*left, *right))
796"The tracks you are attempting to merge to stereo contain clips at\n"
797"different positions, or otherwise mismatching clips. Merging them\n"
798"will render the tracks.\n\n"
799"This causes any realtime effects to be applied to the waveform and\n"
800"hidden data to be removed. Additionally, the entire track will\n"
801"become one large clip.\n\n"
802"Do you wish to continue?"
811 const auto viewMinimized =
814 const auto averageViewHeight =
829 std::max(left->GetRate(), right->GetRate()),
831 std::max(left->GetSampleFormat(), right->GetSampleFormat()),
834 const auto newTrack = *mix->begin();
836 tracks.Insert(*first, std::move(*mix));
840 for(
const auto& channel : newTrack->Channels())
844 view.SetMinimized(viewMinimized);
845 view.SetExpandedHeight(averageViewHeight);
849 XO(
"Made '%s' a stereo track").
Format( newTrack->GetName() ),
865 static_cast<WaveTrack*
>(pTrack)->CopyClipEnvelopes();
867 assert(unlinkedTracks.size() == 2);
870 static_cast<WaveTrack*
>(unlinkedTracks[0])->SetPan(-1.0f);
871 static_cast<WaveTrack*
>(unlinkedTracks[1])->SetPan(1.0f);
874 for (
const auto track : unlinkedTracks) {
878 if (view.GetHeight() < view.GetMinimizedHeight())
879 view.SetExpandedHeight(view.GetMinimizedHeight());
880 totalHeight += view.GetHeight();
884 int averageHeight = totalHeight / nChannels;
886 for (
const auto track : unlinkedTracks)
904 const bool hasFocus = trackFocus.
Get() == pTrack;
905 static_cast<WaveTrack*
>(pTrack)->CopyClipEnvelopes();
909 trackFocus.
Set(track);
914 XO(
"Swap Channels"));
944 XO(
"Split to Mono"));
955 {
wxT(
"/SubViews/Extra"),
wxT(
"WaveColor,SpectrogramSettings")},
969#include "../../../../widgets/ASlider.h"
970#include "../../../ui/CommonTrackInfo.h"
971#include "../../../../TrackPanelDrawingContext.h"
978 (
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow*),
979 wxDC *dc,
const wxRect &rect,
const Track *pTrack,
981 bool captured,
bool highlight )
983 wxRect sliderRect = rect;
985 auto wt =
static_cast<const WaveTrack*
>( pTrack );
986 Selector( sliderRect, wt, captured, pParent )->OnPaint(*dc, highlight);
991 const wxRect &rect,
const Track *pTrack )
994 auto dc = &context.
dc;
995 bool hit = target && target->GetTrack().get() == pTrack;
996 bool captured = hit && target->IsDragging();
1003 pParent, captured, hit);
1008 const wxRect &rect,
const Track *pTrack )
1011 auto dc = &context.
dc;
1012 bool hit = target && target->GetTrack().get() == pTrack;
1015 bool captured = hit && target->IsDragging();
1022 pParent, captured, hit);
1028 static const int offset = 3;
1029 dc->DrawText(
string.Translation(), rect.x + offset, rect.y);
1034 const wxRect &rect,
const Track *pTrack )
1036 auto dc = &context.
dc;
1037 auto wt =
static_cast<const WaveTrack*
>(pTrack);
1042 auto rate = wt ? wt->
GetRate() : 44100.0;
1047 s =
XO(
"Stereo, %dHz");
1049 s =
XO(
"Mono, %dHz");
1050 s.
Format( (
int) (rate + 0.5) );
1057 const wxRect &rect,
const Track *pTrack )
1059 auto dc = &context.
dc;
1060 auto wt =
static_cast<const WaveTrack*
>(pTrack);
1081#ifdef EXPERIMENTAL_DA
1097 dest.y = topleft.y + results.first;
1098 dest.height = results.second;
1105 dest.y = topleft.y + results.first;
1120std::unique_ptr<LWSlider>
1131 auto rect = panel.
FindRect( controls );
1134 return GainSlider( sliderRect, &wt,
false, &panel );
1138(
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow *pParent)
1140 static std::once_flag
flag;
1144 wxPoint pos = sliderRect.GetPosition();
1145 float gain = t ? t->
GetGain() : 1.0;
1153 slider->SetParent( pParent );
1161 const wxPoint point{ 0, 0 };
1167 gGain = std::make_unique<LWSlider>(
nullptr,
XO(
"Gain"),
1168 wxPoint(sliderRect.x, sliderRect.y),
1169 wxSize(sliderRect.width, sliderRect.height),
1171 gGain->SetDefaultValue(defPos);
1174 wxPoint(sliderRect.x, sliderRect.y),
1175 wxSize(sliderRect.width, sliderRect.height),
1184 auto rect = panel.
FindRect( controls );
1187 return PanSlider( sliderRect, &wt,
false, &panel );
1191(
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow *pParent)
1193 static std::once_flag
flag;
1197 wxPoint pos = sliderRect.GetPosition();
1198 float pan = t ? t->
GetPan() : 0.0;
1206 slider->SetParent( pParent );
1214 const wxPoint point{ 0, 0 };
1220 gPan = std::make_unique<LWSlider>(
nullptr,
XO(
"Pan"),
1221 wxPoint(sliderRect.x, sliderRect.y),
1222 wxSize(sliderRect.width, sliderRect.height),
1224 gPan->SetDefaultValue(defPos);
1227 wxPoint(sliderRect.x, sliderRect.y),
1228 wxSize(sliderRect.width, sliderRect.height),
1236 return std::make_shared<WaveTrackControls>( track.
SharedPointer() );
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
std::shared_ptr< UIHandle > UIHandlePtr
std::vector< TrackInfo::TCPLine > TCPLines
XXO("&Cut/Copy/Paste Toolbar")
TrackListHolder MixAndRender(const TrackIterRange< const WaveTrack > &trackRange, const Mixer::WarpOptions &warpOptions, const wxString &newTrackName, WaveTrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime)
Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effec...
wxFrame * FindProjectFrame(AudacityProject *project)
Get a pointer to the window associated with a project, or null if the given pointer is null,...
An AudacityException with no visible message.
DEFINE_ATTACHED_VIRTUAL_OVERRIDE(DoGetWaveTrackControls)
AppendCheckItem("8000", OnRate8ID, XXO("8000 Hz"), POPUP_MENU_FN(OnRateChange), fn)
static std::vector< WaveChannelSubViewType > AllTypes()
TrackInfo::TCPLine TCPLine
Append(Adapt< My >([](My &table) { return(WaveChannelSubViews::numFactories() > 1) ? std::make_unique< Entry >("MultiView", Entry::CheckItem, OnMultiViewID, XXO("&Multi-view"), POPUP_MENU_FN(OnMultiView), table, [](PopupMenuHandler &handler, wxMenu &menu, int id){ auto &table=static_cast< WaveTrackMenuTable & >(handler);auto &track=table.FindWaveTrack();const auto &view=WaveChannelView::Get(track);menu.Check(id, view.GetMultiView());}) :nullptr;}))
static const auto enableSplitStereo
static int gRates[nRates]
WaveTrackTCPLines waveTrackTCPLines
AppendRadioItem("16Bit", On16BitID, GetSampleFormatStr(int16Sample), POPUP_MENU_FN(OnFormatChange), fn)
WaveTrackPopupMenuTable & GetWaveTrackMenuTable()
static const auto MenuPathStart
static const auto isUnsafe
AppendItem("MakeStereo", OnMergeStereoID, XXO("Ma&ke Stereo Track"), POPUP_MENU_FN(OnMergeStereo), [](PopupMenuHandler &handler, wxMenu &menu, int id){ bool canMakeStereo=!isUnsafe(handler) &&isMono(handler);if(canMakeStereo) { AudacityProject &project=static_cast< WaveTrackMenuTable & >(handler).mpData->project;auto &tracks=TrackList::Get(project);auto &table=static_cast< WaveTrackMenuTable & >(handler);auto &track=table.FindWaveTrack();auto next= *++tracks.Find(&track);canMakeStereo=(next &&TrackList::NChannels(*next)==1 &&track_cast< WaveTrack * >(next));} menu.Enable(id, canMakeStereo);})
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Formerly part of TrackPanel, this abstract base class has no special knowledge of Track objects and i...
wxRect FindRect(const TrackPanelCell &cell)
static ChannelView & Get(Channel &channel)
bool GetMinimized() const
void SetExpandedHeight(int height)
static size_t numFactories()
How many static factories have been registered with this specialization of Site.
Subclass & Get(const RegisteredFactory &key)
Get reference to an attachment, creating on demand if not present, down-cast it to Subclass.
virtual std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *) override=0
std::shared_ptr< Track > FindTrack()
static UIHandlePtr HitTest(std::weak_ptr< GainSliderHandle > &holder, const wxMouseState &state, const wxRect &rect, const std::shared_ptr< Track > &pTrack)
Lightweight version of ASlider. In other words it does not have a window permanently associated with ...
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
static UIHandlePtr HitTest(std::weak_ptr< PanSliderHandle > &holder, const wxMouseState &state, const wxRect &rect, const std::shared_ptr< Track > &pTrack)
static const TCPLines & StaticWaveTCPLines()
bool IsAudioActive() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static RealtimeEffectList & Get(AudacityProject &project)
size_t GetStatesCount() const noexcept
static RealtimeEffectManager & Get(AudacityProject &project)
bool IsActive() const noexcept
To be called only from main thread.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
static TrackIterRange< Track > Group(Track *pTrack)
bool IsSyncLocked() const
static SyncLockState & Get(AudacityProject &project)
static TrackArtist * Get(TrackPanelDrawingContext &)
static TrackControls & Get(Track &track)
Abstract base class for an object holding data associated with points on a time axis.
std::shared_ptr< Subclass > SharedPointer()
const wxString & GetName() const
Name is always the same for all channels of a group.
static Track * SwapChannels(Track &track)
static TrackList & Get(AudacityProject &project)
std::vector< Track * > UnlinkChannels(Track &track)
Removes linkage if track belongs to a group.
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
Can be thrown when user cancels operations, as with a progress dialog. Delayed handler does nothing.
bool Set(constSamplePtr buffer, sampleFormat format, sampleCount start, size_t len, sampleFormat effectiveFormat=widestSampleFormat)
Random-access assignment of a range of samples.
void SetDisplay(Display display, bool exclusive=true)
static WaveChannelView & Get(WaveChannel &channel)
PopupMenuTable * GetMenuExtension(Track *pTrack) override
std::weak_ptr< MuteButtonHandle > mMuteHandle
static unsigned DefaultWaveTrackHeight()
~WaveTrackControls() override
std::weak_ptr< PanSliderHandle > mPanHandle
static void GetGainRect(const wxPoint &topLeft, wxRect &dest)
static void GetPanRect(const wxPoint &topLeft, wxRect &dest)
std::weak_ptr< EffectsButtonHandle > mEffectsHandle
const TCPLines & GetTCPLines() const override
std::weak_ptr< GainSliderHandle > mGainHandle
static LWSlider * PanSlider(CellularPanel &panel, const WaveTrack &wt)
std::weak_ptr< SoloButtonHandle > mSoloHandle
static void ReCreatePanSlider(struct ThemeChangeMessage)
std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject) override
static void ReCreateGainSlider(struct ThemeChangeMessage)
static LWSlider * GainSlider(CellularPanel &panel, const WaveTrack &wt)
static WaveTrackFactory & Get(AudacityProject &project)
A Track that contains audio waveform data.
void SetRate(double newRate)
double GetEndTime() const override
Implement WideSampleSequence.
double GetRate() const override
auto GetChannel(size_t iChannel)
Positions or offsets within audio files need a wide type.
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
void SetName(const TranslatableString &title)
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
AUDACITY_DLL_API unsigned DefaultTrackHeight(const TCPLines &topLines)
AUDACITY_DLL_API void GetSliderHorizontalBounds(const wxPoint &topleft, wxRect &dest)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Namespace containing an enum 'what to do on a refresh?'.
AUDACITY_DLL_API std::pair< int, int > CalcItemY(const TCPLines &lines, unsigned iItem)
static float findValue(const float *spectrum, float bin0, float bin1, unsigned nBins, bool autocorrelation, int gain, int range)
void SliderDrawFunction(LWSlider *(*Selector)(const wxRect &sliderRect, const WaveTrack *t, bool captured, wxWindow *), wxDC *dc, const wxRect &rect, const Track *pTrack, wxWindow *pParent, bool captured, bool highlight)
std::unique_ptr< LWSlider > gPanCaptured
void Status1DrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
std::function< int(WaveTrack &) > ValueFinder
void GainSliderDrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
std::unique_ptr< LWSlider > gGain
void Status2DrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
void PanSliderDrawFunction(TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack)
PopupMenuTableEntry::InitFunction initFn(const ValueFinder &findValue)
std::unique_ptr< LWSlider > gGainCaptured
std::unique_ptr< LWSlider > gPan
void StatusDrawFunction(const TranslatableString &string, wxDC *dc, const wxRect &rect)
AuthorizationHandler handler
For defining overrides of the method.
MessageBoxOptions && ButtonStyle(Button style) &&
Immutable structure is an argument to Mixer's constructor.
std::optional< PreferredSystemAppearance > appearance
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
static const std::vector< WaveChannelSubViewType > & All()
Discover all registered types.