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"
37#include "../../../../prefs/PrefsDialog.h"
38#include "../../../../prefs/ThemePrefs.h"
45#include <wx/combobox.h>
58 const wxMouseState &state = st.
state;
59 const wxRect &rect = st.
rect;
60 if (state.ButtonIsDown(wxMOUSE_BTN_LEFT)) {
62 std::vector<UIHandlePtr> results;
88 results.push_back(result);
148template<
typename Table >
152 auto pData =
static_cast<Table&
>(
handler ).mpData;
153 auto &track =
static_cast<WaveTrack&
>(pData->track);
154 auto &
project = pData->project;
158 menu.Enable(
id, !unsafe );
199 return IdOfFormat( track.GetSampleFormat() );
234 int id =
event.GetId();
255 if (newFormat == track.GetSampleFormat())
261 XO(
"Processing... 0%%"),
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));
289 track.ConvertToSampleFormat(newFormat, progressUpdate);
295 XO(
"Format Change"));
340 static const auto fn = initFn< RateMenuTable >(
342 return IdOfRate( (
int)track.
GetRate() );
366static
int gRates[
nRates] = { 8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000,
367176400, 192000, 352800, 384000 };
372 for (
int i = 0; i<
nRates; i++) {
387 if (pLocked != &track)
388 pLocked->SyncLockAdjust(end1, end2);
393 wxString rateString = wxString::Format(
wxT(
"%.3f"), rate);
405 int id =
event.GetId();
448 S.StartVerticalLay(
true);
451 S.StartHorizontalLay(wxEXPAND,
false);
453 cb =
S.AddCombo(
XXO(
"New sample rate (Hz):"),
456#if defined(__WXMAC__)
462 S.EndHorizontalLay();
463 S.AddStandardButtons();
467 dlg.SetClientSize(dlg.GetSizer()->CalcMin());
470 if (dlg.ShowModal() != wxID_OK)
476 if (cb->GetValue().ToLong(&lrate) && lrate >= 1 && lrate <= 1000000)
478 newRate = (int)lrate;
483 XO(
"The entered value is invalid"),
540static std::vector<WaveChannelSubViewType>
AllTypes()
573 ? std::make_unique<Entry>(
579 auto &track = table.FindWaveTrack();
581 menu.Check(
id, view.GetMultiView());
590 static const auto initFn = [](
bool radio ){
return
596 const auto IdForType =
598 const auto begin = allTypes.begin();
600 (std::find(
begin, allTypes.end(), type) -
begin);
604 auto &track = table.FindWaveTrack();
608 const auto displays = view.GetDisplays();
609 const auto end = displays.end();
611 std::find_if(displays.begin(),
end,
613 return id == IdForType(type); }));
614 menu.Check(
id, check );
618 if ( !radio && displays.size() == 1 && check )
619 menu.Enable(
id,
false );
622 Append(Adapt<My>([type,
id](My &table) {
623 const auto pTrack = &table.FindWaveTrack();
625 const auto itemType =
626 view.GetMultiView() ? Entry::CheckItem : Entry::RadioItem;
627 return std::make_unique<Entry>( type.name.Internal(), itemType,
628 id, type.name.Msgid(),
630 initFn( !view.GetMultiView() ) );
643 if ( canMakeStereo ) {
648 auto &track = table.FindWaveTrack();
649 auto next = * ++
tracks.Find(&track);
652 next->NChannels() == 1 &&
653 track_cast<WaveTrack*>(next));
655 menu.Enable(
id, canMakeStereo );
694 auto &track =
static_cast<WaveTrack&
>(mpData->track);
696 bool multi = !view.GetMultiView();
697 const auto &displays = view.GetDisplays();
698 const auto display = displays.empty()
700 view.SetMultiView(multi);
705 view.SetDisplay(display, !multi);
711 int idInt =
event.GetId();
719 if (view.GetMultiView()) {
730 const auto displays = view.GetDisplays();
731 const bool wrongType =
732 !(displays.size() == 1 && displays[0].id ==
id);
752 const auto left = *first;
753 const auto right = *std::next(first);
757 auto eqTrims = [](
double a,
double b)
759 return std::abs(a - b) <=
760 std::numeric_limits<double>::epsilon() * std::max(a, b);
762 const auto eps = 0.5 / left.
GetRate();
763 const auto &rightIntervals = right.Intervals();
765 auto it = std::find_if(
766 rightIntervals.begin(),
767 rightIntervals.end(),
771 return std::abs(a->Start() - b->Start()) < eps &&
772 std::abs(a->End() - b->End()) < eps &&
773 eqTrims(a->GetTrimLeft(), b->GetTrimLeft()) &&
774 eqTrims(a->GetTrimRight(), b->GetTrimRight()) &&
775 a->HasEqualPitchAndSpeed(*b);
777 if(it == rightIntervals.end())
785 !checkAligned(*left, *right))
789"The tracks you are attempting to merge to stereo contain clips at\n"
790"different positions, or otherwise mismatching clips. Merging them\n"
791"will render the tracks.\n\n"
792"This causes any realtime effects to be applied to the waveform and\n"
793"hidden data to be removed. Additionally, the entire track will\n"
794"become one large clip.\n\n"
795"Do you wish to continue?"
804 const auto viewMinimized =
807 const auto averageViewHeight =
822 std::max(left->
GetRate(), right->GetRate()),
827 tracks.Insert(*first, mix);
831 for(
const auto& channel : mix->Channels())
835 view.SetMinimized(viewMinimized);
836 view.SetExpandedHeight(averageViewHeight);
840 XO(
"Made '%s' a stereo track").
Format(mix->GetName()),
856 const std::vector<WaveTrack::Holder> unlinkedTracks = track.
SplitChannels();
858 unlinkedTracks[0]->SetPan(-1.0f);
859 unlinkedTracks[1]->SetPan(1.0f);
862 for (
const auto track : unlinkedTracks) {
866 if (view.GetHeight() < view.GetMinimizedHeight())
867 view.SetExpandedHeight(view.GetMinimizedHeight());
868 totalHeight += view.GetHeight();
872 int averageHeight = totalHeight / nChannels;
874 for (
const auto track : unlinkedTracks)
890 XO(
"Swap Channels"));
919 XO(
"Split to Mono"));
930 {
wxT(
"/SubViews/Extra"),
wxT(
"WaveColor,SpectrogramSettings")},
944#include "../../../../widgets/ASlider.h"
945#include "../../../ui/CommonTrackInfo.h"
946#include "../../../../TrackPanelDrawingContext.h"
953 (
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow*),
954 wxDC *dc,
const wxRect &rect,
const Track *pTrack,
956 bool captured,
bool highlight )
958 wxRect sliderRect = rect;
960 auto wt =
static_cast<const WaveTrack*
>( pTrack );
961 Selector( sliderRect, wt, captured, pParent )->OnPaint(*dc, highlight);
966 const wxRect &rect,
const Track *pTrack )
969 auto dc = &context.
dc;
970 bool hit = target && target->GetTrack().get() == pTrack;
971 bool captured = hit && target->IsDragging();
978 pParent, captured, hit);
983 const wxRect &rect,
const Track *pTrack )
986 auto dc = &context.
dc;
987 bool hit = target && target->GetTrack().get() == pTrack;
990 bool captured = hit && target->IsDragging();
997 pParent, captured, hit);
1003 static const int offset = 3;
1004 dc->DrawText(
string.Translation(), rect.x + offset, rect.y);
1009 const wxRect &rect,
const Track *pTrack )
1011 auto dc = &context.
dc;
1012 auto wt =
static_cast<const WaveTrack*
>(pTrack);
1017 auto rate = wt ? wt->
GetRate() : 44100.0;
1022 s =
XO(
"Stereo, %dHz");
1024 s =
XO(
"Mono, %dHz");
1025 s.
Format( (
int) (rate + 0.5) );
1032 const wxRect &rect,
const Track *pTrack )
1034 auto dc = &context.
dc;
1035 auto wt =
static_cast<const WaveTrack*
>(pTrack);
1068 dest.y = topleft.y + results.first;
1069 dest.height = results.second;
1076 dest.y = topleft.y + results.first;
1091std::unique_ptr<LWSlider>
1102 auto rect = panel.
FindRect( controls );
1105 return GainSlider( sliderRect, &wt,
false, &panel );
1109(
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow *pParent)
1111 static std::once_flag
flag;
1115 wxPoint pos = sliderRect.GetPosition();
1116 float gain = t ? t->
GetGain() : 1.0;
1124 slider->SetParent( pParent );
1132 const wxPoint point{ 0, 0 };
1138 gGain = std::make_unique<LWSlider>(
nullptr,
XO(
"Gain"),
1139 wxPoint(sliderRect.x, sliderRect.y),
1140 wxSize(sliderRect.width, sliderRect.height),
1142 gGain->SetDefaultValue(defPos);
1145 wxPoint(sliderRect.x, sliderRect.y),
1146 wxSize(sliderRect.width, sliderRect.height),
1155 auto rect = panel.
FindRect( controls );
1158 return PanSlider( sliderRect, &wt,
false, &panel );
1162(
const wxRect &sliderRect,
const WaveTrack *t,
bool captured, wxWindow *pParent)
1164 static std::once_flag
flag;
1168 wxPoint pos = sliderRect.GetPosition();
1169 float pan = t ? t->
GetPan() : 0.0;
1177 slider->SetParent( pParent );
1185 const wxPoint point{ 0, 0 };
1191 gPan = std::make_unique<LWSlider>(
nullptr,
XO(
"Pan"),
1192 wxPoint(sliderRect.x, sliderRect.y),
1193 wxSize(sliderRect.width, sliderRect.height),
1195 gPan->SetDefaultValue(defPos);
1198 wxPoint(sliderRect.x, sliderRect.y),
1199 wxSize(sliderRect.width, sliderRect.height),
1207 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")
Track::Holder 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)
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::GetFirst(track);menu.Check(id, view.GetMultiView());}) :nullptr;}))
static std::vector< WaveChannelSubViewType > AllTypes()
TrackInfo::TCPLine TCPLine
static const auto enableSplitStereo
static int gRates[nRates]
WaveTrackTCPLines waveTrackTCPLines
AppendRadioItem("16Bit", On16BitID, GetSampleFormatStr(int16Sample), POPUP_MENU_FN(OnFormatChange), fn)
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 &&next->NChannels()==1 &&track_cast< WaveTrack * >(next));} menu.Enable(id, canMakeStereo);})
WaveTrackPopupMenuTable & GetWaveTrackMenuTable()
static const auto MenuPathStart
static const auto isUnsafe
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)
virtual size_t NChannels() const =0
Report the number of channels.
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.
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 &track)
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 TrackList & Get(AudacityProject &project)
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.
void SetDisplay(Display display, bool exclusive=true)
static WaveChannelView & GetFirst(WaveTrack &wt)
Get the view of the first 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)
!brief Sets the new rate for the track without resampling it
std::vector< Holder > SplitChannels()
sampleFormat GetSampleFormat() const override
void SetPan(float newPan)
double GetEndTime() const override
Implement WideSampleSequence.
double GetRate() const override
size_t NChannels() const override
A constant property.
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)
Namespace containing an enum 'what to do on a refresh?'.
AUDACITY_DLL_API std::pair< int, int > CalcItemY(const TCPLines &lines, unsigned iItem)
WAVE_TRACK_API sampleCount GetSequenceSamplesCount(const WaveTrack &track)
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
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept
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.