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 );
697 const auto pTrack =
static_cast<WaveTrack*
>(mpData->pTrack);
699 bool multi = !view.GetMultiView();
700 const auto &displays = view.GetDisplays();
701 const auto display = displays.empty()
703 view.SetMultiView(multi);
708 view.SetDisplay(display, !multi);
714 int idInt =
event.GetId();
722 if (view.GetMultiView()) {
733 const auto displays = view.GetDisplays();
734 const bool wrongType =
735 !(displays.size() == 1 && displays[0].id ==
id);
755 const auto left = *first;
756 const auto right = *std::next(first);
760 auto eqTrims = [](
double a,
double b)
762 return std::abs(a - b) <=
763 std::numeric_limits<double>::epsilon() * std::max(a, b);
765 const auto eps = 0.5 / left.
GetRate();
766 const auto rightIntervals = right.Intervals();
769 auto it = std::find_if(
770 rightIntervals.begin(),
771 rightIntervals.end(),
775 return std::abs(a->Start() - b->Start()) < eps &&
776 std::abs(a->End() - b->End()) < eps &&
777 eqTrims(a->GetTrimLeft(), b->GetTrimLeft()) &&
778 eqTrims(a->GetTrimRight(), b->GetTrimRight()) &&
779 a->HasEqualPitchAndSpeed(*b);
781 if(it == rightIntervals.end())
789 !checkAligned(*left, *right))
793"The tracks you are attempting to merge to stereo contain clips at\n"
794"different positions, or otherwise mismatching clips. Merging them\n"
795"will render the tracks.\n\n"
796"This causes any realtime effects to be applied to the waveform and\n"
797"hidden data to be removed. Additionally, the entire track will\n"
798"become one large clip.\n\n"
799"Do you wish to continue?"
808 const auto viewMinimized =
811 const auto averageViewHeight =
826 std::max(left->
GetRate(), right->GetRate()),
831 const auto newTrack = *mix->begin();
833 tracks.Insert(*first, std::move(*mix));
837 for(
const auto& channel : newTrack->Channels())
841 view.SetMinimized(viewMinimized);
842 view.SetExpandedHeight(averageViewHeight);
846 XO(
"Made '%s' a stereo track").
Format( newTrack->GetName() ),
862 static_cast<WaveTrack*
>(pTrack)->CopyClipEnvelopes();
864 assert(unlinkedTracks.size() == 2);
867 static_cast<WaveTrack*
>(unlinkedTracks[0])->SetPan(-1.0f);
868 static_cast<WaveTrack*
>(unlinkedTracks[1])->SetPan(1.0f);
871 for (
const auto track : unlinkedTracks) {
875 if (view.GetHeight() < view.GetMinimizedHeight())
876 view.SetExpandedHeight(view.GetMinimizedHeight());
877 totalHeight += view.GetHeight();
881 int averageHeight = totalHeight / nChannels;
883 for (
const auto track : unlinkedTracks)
901 const bool hasFocus = trackFocus.
Get() == pTrack;
902 static_cast<WaveTrack*
>(pTrack)->CopyClipEnvelopes();
906 trackFocus.
Set(track);
911 XO(
"Swap Channels"));
941 XO(
"Split to Mono"));
952 {
wxT(
"/SubViews/Extra"),
wxT(
"WaveColor,SpectrogramSettings")},
966#include "../../../../widgets/ASlider.h"
967#include "../../../ui/CommonTrackInfo.h"
968#include "../../../../TrackPanelDrawingContext.h"
975 (
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow*),
976 wxDC *dc,
const wxRect &rect,
const Track *pTrack,
978 bool captured,
bool highlight )
980 wxRect sliderRect = rect;
982 auto wt =
static_cast<const WaveTrack*
>( pTrack );
983 Selector( sliderRect, wt, captured, pParent )->OnPaint(*dc, highlight);
988 const wxRect &rect,
const Track *pTrack )
991 auto dc = &context.
dc;
992 bool hit = target && target->GetTrack().get() == pTrack;
993 bool captured = hit && target->IsDragging();
1000 pParent, captured, hit);
1005 const wxRect &rect,
const Track *pTrack )
1008 auto dc = &context.
dc;
1009 bool hit = target && target->GetTrack().get() == pTrack;
1012 bool captured = hit && target->IsDragging();
1019 pParent, captured, hit);
1025 static const int offset = 3;
1026 dc->DrawText(
string.Translation(), rect.x + offset, rect.y);
1031 const wxRect &rect,
const Track *pTrack )
1033 auto dc = &context.
dc;
1034 auto wt =
static_cast<const WaveTrack*
>(pTrack);
1039 auto rate = wt ? wt->
GetRate() : 44100.0;
1044 s =
XO(
"Stereo, %dHz");
1046 s =
XO(
"Mono, %dHz");
1047 s.
Format( (
int) (rate + 0.5) );
1054 const wxRect &rect,
const Track *pTrack )
1056 auto dc = &context.
dc;
1057 auto wt =
static_cast<const WaveTrack*
>(pTrack);
1090 dest.y = topleft.y + results.first;
1091 dest.height = results.second;
1098 dest.y = topleft.y + results.first;
1113std::unique_ptr<LWSlider>
1124 auto rect = panel.
FindRect( controls );
1127 return GainSlider( sliderRect, &wt,
false, &panel );
1131(
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow *pParent)
1133 static std::once_flag
flag;
1137 wxPoint pos = sliderRect.GetPosition();
1138 float gain = t ? t->
GetGain() : 1.0;
1146 slider->SetParent( pParent );
1154 const wxPoint point{ 0, 0 };
1160 gGain = std::make_unique<LWSlider>(
nullptr,
XO(
"Gain"),
1161 wxPoint(sliderRect.x, sliderRect.y),
1162 wxSize(sliderRect.width, sliderRect.height),
1164 gGain->SetDefaultValue(defPos);
1167 wxPoint(sliderRect.x, sliderRect.y),
1168 wxSize(sliderRect.width, sliderRect.height),
1177 auto rect = panel.
FindRect( controls );
1180 return PanSlider( sliderRect, &wt,
false, &panel );
1184(
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow *pParent)
1186 static std::once_flag
flag;
1190 wxPoint pos = sliderRect.GetPosition();
1191 float pan = t ? t->
GetPan() : 0.0;
1199 slider->SetParent( pParent );
1207 const wxPoint point{ 0, 0 };
1213 gPan = std::make_unique<LWSlider>(
nullptr,
XO(
"Pan"),
1214 wxPoint(sliderRect.x, sliderRect.y),
1215 wxSize(sliderRect.width, sliderRect.height),
1217 gPan->SetDefaultValue(defPos);
1220 wxPoint(sliderRect.x, sliderRect.y),
1221 wxSize(sliderRect.width, sliderRect.height),
1229 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)
sampleFormat GetSampleFormat() const override
void SetPan(float newPan)
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.