/**********************************************************************

  Audacity: A Digital Audio Editor

  ExportPluginHelpers.cpp
 
  Dominic Mazzoni

  Vitaly Sverchinsky split from ExportPlugin.h

**********************************************************************/

#include "ExportPluginHelpers.h"
#include "Track.h"
#include "Mix.h"
#include "WaveTrack.h"
#include "MixAndRender.h"
#include "ExportUtils.h"
#include "ExportPlugin.h"
#include "StretchingSequence.h"

//Create a mixer by computing the time warp factor
std::unique_ptr<Mixer> ExportPluginHelpers::CreateMixer(const TrackList &tracks,
         bool selectionOnly,
         double startTime, double stopTime,
         unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
         double outRate, sampleFormat outFormat,
         MixerOptions::Downmix *mixerSpec)
{
   Mixer::Inputs inputs;

   for (auto pTrack: ExportUtils::FindExportWaveTracks(tracks, selectionOnly))
      inputs.emplace_back(
         StretchingSequence::Create(*pTrack, pTrack->GetClipInterfaces()),
         GetEffectStages(*pTrack));
   // MB: the stop time should not be warped, this was a bug.
   return std::make_unique<Mixer>(move(inputs),
                  // Throw, to stop exporting, if read fails:
                  true,
                  Mixer::WarpOptions{ tracks.GetOwner() },
                  startTime, stopTime,
                  numOutChannels, outBufferSize, outInterleaved,
                  outRate, outFormat,
                  true, mixerSpec);
}

namespace
{
   double EvalExportProgress(Mixer &mixer, double t0, double t1)
   {
      const auto duration = t1 - t0;
      if(duration > 0)
         return std::clamp(mixer.MixGetCurrentTime() - t0, .0, duration) / duration;
      return .0;
   }
}

ExportResult ExportPluginHelpers::UpdateProgress(ExportProcessorDelegate& delegate, Mixer &mixer, double t0, double t1)
{
   delegate.OnProgress(EvalExportProgress(mixer, t0, t1));
   if(delegate.IsStopped())
      return ExportResult::Stopped;
   if(delegate.IsCancelled())
      return ExportResult::Cancelled;
   return ExportResult::Success;
}

