2010-01-23 19:44:49 +00:00
/**********************************************************************
Audacity : A Digital Audio Editor
Export . cpp
Dominic Mazzoni
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /**
\ class Export
\ brief Main class to control the export function .
*/ /****************************************************************/ /**
\ class ExportType
\ brief Container for information about supported export types .
*/ /****************************************************************/ /**
\ class ExportMixerDialog
\ brief Dialog for advanced mixing .
*/ /****************************************************************/ /**
\ class ExportMixerPanel
\ brief Panel that displays mixing for advanced mixing option .
*/ /********************************************************************/
2015-06-18 14:24:36 +00:00
# include "../Audacity.h"
# include "Export.h"
2010-01-23 19:44:49 +00:00
# include <wx/dynarray.h>
# include <wx/file.h>
# include <wx/filename.h>
# include <wx/msgdlg.h>
# include <wx/progdlg.h>
# include <wx/sizer.h>
# include <wx/slider.h>
2015-07-13 17:36:40 +00:00
# include <wx/statbox.h>
2010-01-23 19:44:49 +00:00
# include <wx/stattext.h>
# include <wx/string.h>
# include <wx/textctrl.h>
# include <wx/timer.h>
2014-10-18 18:41:56 +00:00
# include <wx/dcmemory.h>
2015-07-15 04:33:53 +00:00
# include <wx/window.h>
2010-01-23 19:44:49 +00:00
# include "ExportPCM.h"
# include "ExportMP3.h"
# include "ExportOGG.h"
# include "ExportFLAC.h"
# include "ExportCL.h"
# include "ExportMP2.h"
# include "ExportFFmpeg.h"
# include "sndfile.h"
# include "FileDialog.h"
# include "../DirManager.h"
# include "../FileFormats.h"
# include "../Internat.h"
# include "../Mix.h"
# include "../Prefs.h"
# include "../Project.h"
2015-06-18 14:24:36 +00:00
# include "../ShuttleGui.h"
2010-01-23 19:44:49 +00:00
# include "../WaveTrack.h"
# include "../widgets/Warning.h"
# include "../AColor.h"
2011-04-02 23:56:02 +00:00
# include "../Dependencies.h"
2010-01-23 19:44:49 +00:00
//----------------------------------------------------------------------------
// ExportPlugin
//----------------------------------------------------------------------------
# include <wx/arrimpl.cpp>
2014-01-13 21:09:14 +00:00
WX_DEFINE_USER_EXPORTED_OBJARRAY ( FormatInfoArray ) ;
2010-01-23 19:44:49 +00:00
ExportPlugin : : ExportPlugin ( )
{
mFormatInfos . Empty ( ) ;
}
ExportPlugin : : ~ ExportPlugin ( )
{
mFormatInfos . Clear ( ) ;
}
2013-08-25 21:51:26 +00:00
bool ExportPlugin : : CheckFileName ( wxFileName & WXUNUSED ( filename ) , int WXUNUSED ( format ) )
2010-01-23 19:44:49 +00:00
{
return true ;
}
2016-02-13 15:43:16 +00:00
/** \brief Add a NEW entry to the list of formats this plug-in can export
2010-01-23 19:44:49 +00:00
*
* To configure the format use SetFormat , SetCanMetaData etc with the index of
* the format .
* @ return The number of formats currently set up . This is one more than the
* index of the newly added format .
*/
int ExportPlugin : : AddFormat ( )
{
FormatInfo nf ;
mFormatInfos . Add ( nf ) ;
return mFormatInfos . Count ( ) ;
}
int ExportPlugin : : GetFormatCount ( )
{
return mFormatInfos . Count ( ) ;
}
/**
* @ param index The plugin to set the format for ( range 0 to one less than the
* count of formats )
*/
void ExportPlugin : : SetFormat ( const wxString & format , int index )
{
mFormatInfos [ index ] . mFormat = format ;
}
void ExportPlugin : : SetDescription ( const wxString & description , int index )
{
mFormatInfos [ index ] . mDescription = description ;
}
void ExportPlugin : : AddExtension ( const wxString & extension , int index )
{
mFormatInfos [ index ] . mExtensions . Add ( extension ) ;
}
void ExportPlugin : : SetExtensions ( const wxArrayString & extensions , int index )
{
mFormatInfos [ index ] . mExtensions = extensions ;
}
void ExportPlugin : : SetMask ( const wxString & mask , int index )
{
mFormatInfos [ index ] . mMask = mask ;
}
void ExportPlugin : : SetMaxChannels ( int maxchannels , int index )
{
mFormatInfos [ index ] . mMaxChannels = maxchannels ;
}
void ExportPlugin : : SetCanMetaData ( bool canmetadata , int index )
{
mFormatInfos [ index ] . mCanMetaData = canmetadata ;
}
wxString ExportPlugin : : GetFormat ( int index )
{
return mFormatInfos [ index ] . mFormat ;
}
wxString ExportPlugin : : GetDescription ( int index )
{
return mFormatInfos [ index ] . mDescription ;
}
wxString ExportPlugin : : GetExtension ( int index )
{
return mFormatInfos [ index ] . mExtensions [ 0 ] ;
}
wxArrayString ExportPlugin : : GetExtensions ( int index )
{
return mFormatInfos [ index ] . mExtensions ;
}
wxString ExportPlugin : : GetMask ( int index )
{
if ( ! mFormatInfos [ index ] . mMask . IsEmpty ( ) ) {
return mFormatInfos [ index ] . mMask ;
}
wxString mask = GetDescription ( index ) + wxT ( " | " ) ;
2015-05-16 09:20:27 +00:00
// Build the mask
2016-01-26 18:48:37 +00:00
// wxString ext = GetExtension(index);
2010-01-23 19:44:49 +00:00
wxArrayString exts = GetExtensions ( index ) ;
for ( size_t i = 0 ; i < exts . GetCount ( ) ; i + + ) {
2015-05-16 09:20:27 +00:00
mask + = wxT ( " *. " ) + exts [ i ] + wxT ( " ; " ) ;
2010-01-23 19:44:49 +00:00
}
2015-05-16 09:20:27 +00:00
return mask ;
2010-01-23 19:44:49 +00:00
}
int ExportPlugin : : GetMaxChannels ( int index )
{
return mFormatInfos [ index ] . mMaxChannels ;
}
bool ExportPlugin : : GetCanMetaData ( int index )
{
return mFormatInfos [ index ] . mCanMetaData ;
}
2016-01-26 19:14:10 +00:00
bool ExportPlugin : : IsExtension ( const wxString & ext , int index )
2010-01-23 19:44:49 +00:00
{
bool isext = false ;
for ( int i = index ; i < GetFormatCount ( ) ; i = GetFormatCount ( ) )
{
wxString defext = GetExtension ( i ) ;
wxArrayString defexts = GetExtensions ( i ) ;
int indofext = defexts . Index ( ext , false ) ;
if ( defext = = wxT ( " " ) | | ( indofext ! = wxNOT_FOUND ) )
isext = true ;
}
return isext ;
}
2013-08-25 21:51:26 +00:00
bool ExportPlugin : : DisplayOptions ( wxWindow * WXUNUSED ( parent ) , int WXUNUSED ( format ) )
2010-01-23 19:44:49 +00:00
{
return false ;
}
2015-07-13 21:38:24 +00:00
wxWindow * ExportPlugin : : OptionsCreate ( wxWindow * parent , int WXUNUSED ( format ) )
2015-07-13 17:36:40 +00:00
{
2016-02-13 23:06:49 +00:00
wxASSERT ( parent ) ; // To justify safenew
2016-06-25 18:18:23 +00:00
wxPanel * p = safenew wxPanelWrapper ( parent , wxID_ANY ) ;
2015-07-13 17:36:40 +00:00
ShuttleGui S ( p , eIsCreatingFromPrefs ) ;
S . StartHorizontalLay ( wxCENTER ) ;
{
S . StartHorizontalLay ( wxCENTER , 0 ) ;
{
S . Prop ( 1 ) . AddTitle ( _ ( " No format specific options " ) ) ;
}
S . EndHorizontalLay ( ) ;
}
S . EndHorizontalLay ( ) ;
return p ;
}
2010-10-07 23:01:49 +00:00
//Create a mixer by computing the time warp factor
2016-03-31 05:33:17 +00:00
std : : unique_ptr < Mixer > ExportPlugin : : CreateMixer ( const WaveTrackConstArray & inputTracks ,
2016-02-26 23:10:45 +00:00
const TimeTrack * timeTrack ,
2010-10-07 23:01:49 +00:00
double startTime , double stopTime ,
int numOutChannels , int outBufferSize , bool outInterleaved ,
double outRate , sampleFormat outFormat ,
bool highQuality , MixerSpec * mixerSpec )
{
2012-12-19 21:49:25 +00:00
// MB: the stop time should not be warped, this was a bug.
2016-03-31 05:33:17 +00:00
return std : : make_unique < Mixer > ( inputTracks ,
2015-04-14 18:52:22 +00:00
Mixer : : WarpOptions ( timeTrack ) ,
2012-12-19 21:49:25 +00:00
startTime , stopTime ,
2010-10-07 23:01:49 +00:00
numOutChannels , outBufferSize , outInterleaved ,
outRate , outFormat ,
highQuality , mixerSpec ) ;
}
2015-07-13 17:36:40 +00:00
2010-01-23 19:44:49 +00:00
//----------------------------------------------------------------------------
// Export
//----------------------------------------------------------------------------
2015-07-13 17:36:40 +00:00
BEGIN_EVENT_TABLE ( Exporter , wxEvtHandler )
EVT_FILECTRL_FILTERCHANGED ( wxID_ANY , Exporter : : OnFilterChanged )
END_EVENT_TABLE ( )
2010-01-23 19:44:49 +00:00
Exporter : : Exporter ( )
{
mMixerSpec = NULL ;
2015-08-10 02:35:14 +00:00
mBook = NULL ;
2015-07-13 17:36:40 +00:00
2013-11-25 04:59:07 +00:00
SetFileDialogTitle ( _ ( " Export Audio " ) ) ;
2010-01-23 19:44:49 +00:00
RegisterPlugin ( New_ExportPCM ( ) ) ;
RegisterPlugin ( New_ExportMP3 ( ) ) ;
# ifdef USE_LIBVORBIS
RegisterPlugin ( New_ExportOGG ( ) ) ;
# endif
# ifdef USE_LIBFLAC
RegisterPlugin ( New_ExportFLAC ( ) ) ;
# endif
# if USE_LIBTWOLAME
RegisterPlugin ( New_ExportMP2 ( ) ) ;
# endif
// Command line export not available on Windows and Mac platforms
RegisterPlugin ( New_ExportCL ( ) ) ;
# if defined(USE_FFMPEG)
RegisterPlugin ( New_ExportFFmpeg ( ) ) ;
# endif
}
Exporter : : ~ Exporter ( )
{
if ( mMixerSpec ) {
delete mMixerSpec ;
}
}
2013-10-22 21:11:58 +00:00
void Exporter : : SetFileDialogTitle ( const wxString & DialogTitle )
{
// The default title is "Export File"
mFileDialogTitle = DialogTitle ;
}
2010-01-23 19:44:49 +00:00
int Exporter : : FindFormatIndex ( int exportindex )
{
int c = 0 ;
2016-03-31 04:46:22 +00:00
for ( const auto & pPlugin : mPlugins )
2010-01-23 19:44:49 +00:00
{
2016-03-31 04:46:22 +00:00
for ( int j = 0 ; j < pPlugin - > GetFormatCount ( ) ; j + + )
2010-01-23 19:44:49 +00:00
{
if ( exportindex = = c ) return j ;
c + + ;
}
}
return 0 ;
}
2016-03-31 04:46:22 +00:00
void Exporter : : RegisterPlugin ( movable_ptr < ExportPlugin > & & ExportPlugin )
2010-01-23 19:44:49 +00:00
{
2016-03-31 04:46:22 +00:00
mPlugins . push_back ( std : : move ( ExportPlugin ) ) ;
2010-01-23 19:44:49 +00:00
}
2016-03-31 04:46:22 +00:00
const ExportPluginArray & Exporter : : GetPlugins ( )
2010-01-23 19:44:49 +00:00
{
return mPlugins ;
}
bool Exporter : : Process ( AudacityProject * project , bool selectedOnly , double t0 , double t1 )
{
// Save parms
mProject = project ;
mSelectedOnly = selectedOnly ;
mT0 = t0 ;
mT1 = t1 ;
// Gather track information
if ( ! ExamineTracks ( ) ) {
return false ;
}
// Ask user for file name
if ( ! GetFilename ( ) ) {
return false ;
}
2012-12-17 02:00:32 +00:00
// Check for down mixing
if ( ! CheckMix ( ) ) {
return false ;
}
2014-06-03 20:30:19 +00:00
// Let user edit MetaData
2010-01-23 19:44:49 +00:00
if ( mPlugins [ mFormat ] - > GetCanMetaData ( mSubFormat ) ) {
2016-02-11 16:03:12 +00:00
if ( ! ( project - > DoEditMetadata ( _ ( " Edit Metadata Tags for Export " ) , _ ( " Exported Tags " ) , mProject - > GetShowId3Dialog ( ) ) ) ) {
2010-01-23 19:44:49 +00:00
return false ;
}
}
// Ensure filename doesn't interfere with project files.
if ( ! CheckFilename ( ) ) {
return false ;
}
// Export the tracks
bool success = ExportTracks ( ) ;
// Get rid of mixerspec
if ( mMixerSpec ) {
delete mMixerSpec ;
mMixerSpec = NULL ;
}
return success ;
}
bool Exporter : : Process ( AudacityProject * project , int numChannels ,
2015-04-23 14:07:25 +00:00
const wxChar * type , const wxString & filename ,
2010-01-23 19:44:49 +00:00
bool selectedOnly , double t0 , double t1 )
{
// Save parms
mProject = project ;
mChannels = numChannels ;
mFilename = filename ;
mSelectedOnly = selectedOnly ;
mT0 = t0 ;
mT1 = t1 ;
mActualName = mFilename ;
2016-03-31 04:46:22 +00:00
int i = - 1 ;
for ( const auto & pPlugin : mPlugins ) {
+ + i ;
for ( int j = 0 ; j < pPlugin - > GetFormatCount ( ) ; j + + )
2010-01-23 19:44:49 +00:00
{
2016-03-31 04:46:22 +00:00
if ( pPlugin - > GetFormat ( j ) . IsSameAs ( type , false ) )
2010-01-23 19:44:49 +00:00
{
mFormat = i ;
mSubFormat = j ;
return ExportTracks ( ) ;
}
}
}
return false ;
}
bool Exporter : : ExamineTracks ( )
{
// Init
mNumSelected = 0 ;
mNumLeft = 0 ;
mNumRight = 0 ;
mNumMono = 0 ;
// First analyze the selected audio, perform sanity checks, and provide
// information as appropriate.
// Tally how many are right, left, mono, and make sure at
// least one track is selected (if selectedOnly==true)
double earliestBegin = mT1 ;
double latestEnd = mT0 ;
2016-02-26 23:10:45 +00:00
const TrackList * tracks = mProject - > GetTracks ( ) ;
TrackListConstIterator iter1 ( tracks ) ;
const Track * tr = iter1 . First ( ) ;
2010-01-23 19:44:49 +00:00
while ( tr ) {
if ( tr - > GetKind ( ) = = Track : : Wave ) {
if ( ( tr - > GetSelected ( ) | | ! mSelectedOnly ) & & ! tr - > GetMute ( ) ) { // don't count muted tracks
mNumSelected + + ;
if ( tr - > GetChannel ( ) = = Track : : LeftChannel ) {
mNumLeft + + ;
}
else if ( tr - > GetChannel ( ) = = Track : : RightChannel ) {
mNumRight + + ;
}
else if ( tr - > GetChannel ( ) = = Track : : MonoChannel ) {
// It's a mono channel, but it may be panned
float pan = ( ( WaveTrack * ) tr ) - > GetPan ( ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
if ( pan = = - 1.0 )
mNumLeft + + ;
else if ( pan = = 1.0 )
mNumRight + + ;
else if ( pan = = 0 )
mNumMono + + ;
else {
// Panned partially off-center. Mix as stereo.
mNumLeft + + ;
mNumRight + + ;
}
}
if ( tr - > GetOffset ( ) < earliestBegin ) {
earliestBegin = tr - > GetOffset ( ) ;
}
if ( tr - > GetEndTime ( ) > latestEnd ) {
latestEnd = tr - > GetEndTime ( ) ;
}
}
}
tr = iter1 . Next ( ) ;
}
if ( mNumSelected = = 0 ) {
wxString message ;
if ( mSelectedOnly )
2013-01-08 00:44:57 +00:00
message = _ ( " All selected audio is muted. " ) ;
2010-01-23 19:44:49 +00:00
else
2013-01-08 00:44:57 +00:00
message = _ ( " All audio is muted. " ) ;
2010-01-23 19:44:49 +00:00
wxMessageBox ( message ,
_ ( " Unable to export " ) ,
wxOK | wxICON_INFORMATION ) ;
return false ;
}
if ( mT0 < earliestBegin )
mT0 = earliestBegin ;
if ( mT1 > latestEnd )
mT1 = latestEnd ;
return true ;
}
bool Exporter : : GetFilename ( )
{
mFormat = - 1 ;
wxString maskString ;
wxString defaultFormat = gPrefs - > Read ( wxT ( " /Export/Format " ) ,
wxT ( " WAV " ) ) ;
mFilterIndex = 0 ;
2016-03-31 04:46:22 +00:00
{
int i = - 1 ;
for ( const auto & pPlugin : mPlugins ) {
+ + i ;
for ( int j = 0 ; j < pPlugin - > GetFormatCount ( ) ; j + + )
{
maskString + = pPlugin - > GetMask ( j ) + wxT ( " | " ) ;
if ( mPlugins [ i ] - > GetFormat ( j ) = = defaultFormat ) {
mFormat = i ;
mSubFormat = j ;
}
if ( mFormat = = - 1 ) mFilterIndex + + ;
2010-01-23 19:44:49 +00:00
}
}
}
if ( mFormat = = - 1 )
{
mFormat = 0 ;
mFilterIndex = 0 ;
}
maskString . RemoveLast ( ) ;
mFilename . SetPath ( gPrefs - > Read ( wxT ( " /Export/Path " ) , : : wxGetCwd ( ) ) ) ;
mFilename . SetName ( mProject - > GetName ( ) ) ;
while ( true ) {
2015-09-30 15:16:33 +00:00
// Must reset each iteration
mBook = NULL ;
2010-01-23 19:44:49 +00:00
FileDialog fd ( mProject ,
2013-10-22 21:11:58 +00:00
mFileDialogTitle ,
2010-01-23 19:44:49 +00:00
mFilename . GetPath ( ) ,
mFilename . GetFullName ( ) ,
maskString ,
2015-07-16 06:12:09 +00:00
wxFD_SAVE | wxRESIZE_BORDER ) ;
2010-01-23 19:44:49 +00:00
mDialog = & fd ;
2015-07-13 17:36:40 +00:00
mDialog - > PushEventHandler ( this ) ;
2010-01-23 19:44:49 +00:00
2015-07-13 17:36:40 +00:00
fd . SetUserPaneCreator ( CreateUserPaneCallback , ( wxUIntPtr ) this ) ;
2010-01-23 19:44:49 +00:00
fd . SetFilterIndex ( mFilterIndex ) ;
2015-07-13 21:38:24 +00:00
int result = fd . ShowModal ( ) ;
mDialog - > PopEventHandler ( ) ;
2010-01-23 19:44:49 +00:00
2015-07-13 21:38:24 +00:00
if ( result = = wxID_CANCEL ) {
2010-01-23 19:44:49 +00:00
return false ;
}
mFilename = fd . GetPath ( ) ;
2015-07-16 06:12:09 +00:00
if ( mFilename = = wxT ( " " ) ) {
return false ;
}
2010-01-23 19:44:49 +00:00
mFormat = fd . GetFilterIndex ( ) ;
mFilterIndex = fd . GetFilterIndex ( ) ;
int c = 0 ;
2016-03-31 04:46:22 +00:00
int i = - 1 ;
for ( const auto & pPlugin : mPlugins )
2010-01-23 19:44:49 +00:00
{
2016-03-31 04:46:22 +00:00
+ + i ;
for ( int j = 0 ; j < pPlugin - > GetFormatCount ( ) ; j + + )
2010-01-23 19:44:49 +00:00
{
if ( mFilterIndex = = c )
{
mFormat = i ;
mSubFormat = j ;
}
c + + ;
}
}
wxString ext = mFilename . GetExt ( ) ;
wxString defext = mPlugins [ mFormat ] - > GetExtension ( mSubFormat ) . Lower ( ) ;
//
// Check the extension - add the default if it's not there,
// and warn user if it's abnormal.
//
if ( ext . IsEmpty ( ) ) {
//
// Make sure the user doesn't accidentally save the file
// as an extension with no name, like just plain ".wav".
//
if ( mFilename . GetName ( ) . Left ( 1 ) = = wxT ( " . " ) ) {
2013-01-03 23:59:00 +00:00
wxString prompt = _ ( " Are you sure you want to export the file as \" " ) +
2010-01-23 19:44:49 +00:00
mFilename . GetFullName ( ) +
wxT ( " \" ? \n " ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
int action = wxMessageBox ( prompt ,
_ ( " Warning " ) ,
wxYES_NO | wxICON_EXCLAMATION ) ;
if ( action ! = wxYES ) {
continue ;
}
}
mFilename . SetExt ( defext ) ;
}
else if ( ! mPlugins [ mFormat ] - > CheckFileName ( mFilename , mSubFormat ) )
{
continue ;
}
else if ( ! ext . IsEmpty ( ) & & ! mPlugins [ mFormat ] - > IsExtension ( ext , mSubFormat ) & & ext . CmpNoCase ( defext ) ) {
wxString prompt ;
2013-01-03 23:59:00 +00:00
prompt . Printf ( _ ( " You are about to export a %s file with the name \" %s \" . \n \n Normally these files end in \" .%s \" , and some programs will not open files with nonstandard extensions. \n \n Are you sure you want to export the file under this name? " ) ,
2010-01-23 19:44:49 +00:00
mPlugins [ mFormat ] - > GetFormat ( mSubFormat ) . c_str ( ) ,
mFilename . GetFullName ( ) . c_str ( ) ,
defext . c_str ( ) ) ;
int action = wxMessageBox ( prompt ,
_ ( " Warning " ) ,
wxYES_NO | wxICON_EXCLAMATION ) ;
if ( action ! = wxYES ) {
continue ;
}
}
if ( mFilename . GetFullPath ( ) . Length ( ) > = 256 ) {
wxMessageBox ( _ ( " Sorry, pathnames longer than 256 characters not supported. " ) ) ;
continue ;
}
2011-04-02 23:56:02 +00:00
// Check to see if we are writing to a path that a missing aliased file existed at.
// This causes problems for the exporter, so we don't allow it.
// Overwritting non-missing aliased files is okay.
// Also, this can only happen for uncompressed audio.
bool overwritingMissingAlias ;
overwritingMissingAlias = false ;
2012-02-08 05:09:14 +00:00
for ( size_t i = 0 ; i < gAudacityProjects . GetCount ( ) ; i + + ) {
2011-04-02 23:56:02 +00:00
AliasedFileArray aliasedFiles ;
2016-04-17 06:40:51 +00:00
FindDependencies ( gAudacityProjects [ i ] , aliasedFiles ) ;
for ( const auto & aliasedFile : aliasedFiles ) {
if ( mFilename . GetFullPath ( ) = = aliasedFile . mFileName . GetFullPath ( ) & &
2011-04-03 16:43:24 +00:00
! mFilename . FileExists ( ) ) {
// Warn and return to the dialog
wxMessageBox ( _ ( " You are attempting to overwrite an aliased file that is missing. \n \
2016-02-25 13:47:48 +00:00
The file cannot be written because the path is needed to restore the original audio to the project . \ n \
Choose File > Check Dependencies to view the locations of all missing files . \ n \
If you still wish to export , please choose a different filename or folder . " ));
2011-04-03 16:43:24 +00:00
overwritingMissingAlias = true ;
}
2011-04-02 23:56:02 +00:00
}
}
if ( overwritingMissingAlias )
continue ;
2010-01-23 19:44:49 +00:00
if ( mFilename . FileExists ( ) ) {
wxString prompt ;
prompt . Printf ( _ ( " A file named \" %s \" already exists. Replace? " ) ,
mFilename . GetFullPath ( ) . c_str ( ) ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
int action = wxMessageBox ( prompt ,
_ ( " Warning " ) ,
wxYES_NO | wxICON_EXCLAMATION ) ;
if ( action ! = wxYES ) {
continue ;
}
}
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
break ;
}
return true ;
}
//
// For safety, if the file already exists it stores the filename
// the user wants in actualName, and returns a temporary file name.
// The calling function should rename the file when it's successfully
// exported.
//
bool Exporter : : CheckFilename ( )
{
//
// Ensure that exporting a file by this name doesn't overwrite
// one of the existing files in the project. (If it would
// overwrite an existing file, DirManager tries to rename the
// existing file.)
//
if ( ! mProject - > GetDirManager ( ) - > EnsureSafeFilename ( mFilename ) )
return false ;
gPrefs - > Write ( wxT ( " /Export/Format " ) , mPlugins [ mFormat ] - > GetFormat ( mSubFormat ) ) ;
gPrefs - > Write ( wxT ( " /Export/Path " ) , mFilename . GetPath ( ) ) ;
2012-08-02 06:03:19 +00:00
gPrefs - > Flush ( ) ;
2010-01-23 19:44:49 +00:00
//
// To be even safer, return a temporary file name based
// on this one...
//
mActualName = mFilename ;
int suffix = 0 ;
while ( mFilename . FileExists ( ) ) {
mFilename . SetName ( mActualName . GetName ( ) +
wxString : : Format ( wxT ( " %d " ) , suffix ) ) ;
suffix + + ;
}
return true ;
}
void Exporter : : DisplayOptions ( int index )
{
int c = 0 ;
int mf = - 1 , msf = - 1 ;
2016-03-31 04:46:22 +00:00
int i = - 1 ;
for ( const auto & pPlugin : mPlugins )
2010-01-23 19:44:49 +00:00
{
2016-03-31 04:46:22 +00:00
+ + i ;
for ( int j = 0 ; j < pPlugin - > GetFormatCount ( ) ; j + + )
2010-01-23 19:44:49 +00:00
{
if ( index = = c )
{
mf = i ;
msf = j ;
}
c + + ;
}
}
// This shouldn't happen...
if ( index > = c ) {
return ;
}
# if defined(__WXMSW__)
mPlugins [ mf ] - > DisplayOptions ( mProject , msf ) ;
# else
mPlugins [ mf ] - > DisplayOptions ( mDialog , msf ) ;
# endif
}
bool Exporter : : CheckMix ( )
{
// Clean up ... should never happen
if ( mMixerSpec ) {
delete mMixerSpec ;
mMixerSpec = NULL ;
}
// Detemine if exported file will be stereo or mono or multichannel,
// and if mixing will occur.
int downMix = gPrefs - > Read ( wxT ( " /FileFormats/ExportDownMix " ) , true ) ;
2016-04-12 20:58:08 +00:00
int exportedChannels = mPlugins [ mFormat ] - > SetNumExportChannels ( ) ;
2010-01-23 19:44:49 +00:00
if ( downMix ) {
if ( mNumRight > 0 | | mNumLeft > 0 ) {
mChannels = 2 ;
}
else {
mChannels = 1 ;
}
if ( mChannels > mPlugins [ mFormat ] - > GetMaxChannels ( mSubFormat ) )
mChannels = mPlugins [ mFormat ] - > GetMaxChannels ( mSubFormat ) ;
int numLeft = mNumLeft + mNumMono ;
int numRight = mNumRight + mNumMono ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
if ( numLeft > 1 | | numRight > 1 | | mNumLeft + mNumRight + mNumMono > mChannels ) {
2016-04-12 20:58:08 +00:00
wxString exportFormat = mPlugins [ mFormat ] - > GetFormat ( mSubFormat ) ;
if ( exportFormat ! = wxT ( " CL " ) & & exportFormat ! = wxT ( " FFMPEG " ) & & exportedChannels = = - 1 )
exportedChannels = mChannels ;
if ( exportedChannels = = 1 ) {
if ( ShowWarningDialog ( mProject ,
wxT ( " MixMono " ) ,
_ ( " Your tracks will be mixed down to a single mono channel in the exported file. " ) ,
true ) = = wxID_CANCEL )
return false ;
}
else if ( exportedChannels = = 2 ) {
2012-12-17 02:00:32 +00:00
if ( ShowWarningDialog ( mProject ,
wxT ( " MixStereo " ) ,
_ ( " Your tracks will be mixed down to two stereo channels in the exported file. " ) ,
true ) = = wxID_CANCEL )
return false ;
2010-01-23 19:44:49 +00:00
}
else {
2012-12-17 02:00:32 +00:00
if ( ShowWarningDialog ( mProject ,
2016-04-12 20:58:08 +00:00
wxT ( " MixUnknownChannels " ) ,
_ ( " Your tracks will be mixed down to one exported file according to the encoder settings. " ) ,
2012-12-17 02:00:32 +00:00
true ) = = wxID_CANCEL )
return false ;
2010-01-23 19:44:49 +00:00
}
}
}
else
{
2016-04-12 20:58:08 +00:00
if ( exportedChannels = = - 1 )
exportedChannels = mPlugins [ mFormat ] - > GetMaxChannels ( mSubFormat ) ;
2010-01-23 19:44:49 +00:00
ExportMixerDialog md ( mProject - > GetTracks ( ) ,
mSelectedOnly ,
2016-04-12 20:58:08 +00:00
exportedChannels ,
2014-06-03 20:30:19 +00:00
NULL ,
2010-01-23 19:44:49 +00:00
1 ,
_ ( " Advanced Mixing Options " ) ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
if ( md . ShowModal ( ) ! = wxID_OK ) {
return false ;
}
mMixerSpec = new MixerSpec ( * ( md . GetMixerSpec ( ) ) ) ;
mChannels = mMixerSpec - > GetNumChannels ( ) ;
}
return true ;
}
bool Exporter : : ExportTracks ( )
{
int success ;
// Keep original in case of failure
if ( mActualName ! = mFilename ) {
: : wxRenameFile ( mActualName . GetFullPath ( ) , mFilename . GetFullPath ( ) ) ;
}
success = mPlugins [ mFormat ] - > Export ( mProject ,
mChannels ,
mActualName . GetFullPath ( ) ,
mSelectedOnly ,
mT0 ,
mT1 ,
mMixerSpec ,
NULL ,
mSubFormat ) ;
if ( mActualName ! = mFilename ) {
// Remove backup
if ( success = = eProgressSuccess | | success = = eProgressStopped ) {
: : wxRemoveFile ( mFilename . GetFullPath ( ) ) ;
}
else {
// Restore original, if needed
: : wxRemoveFile ( mActualName . GetFullPath ( ) ) ;
: : wxRenameFile ( mFilename . GetFullPath ( ) , mActualName . GetFullPath ( ) ) ;
}
}
return ( success = = eProgressSuccess | | success = = eProgressStopped ) ;
}
2015-07-13 17:36:40 +00:00
void Exporter : : CreateUserPaneCallback ( wxWindow * parent , wxUIntPtr userdata )
{
Exporter * self = ( Exporter * ) userdata ;
if ( self )
{
self - > CreateUserPane ( parent ) ;
}
}
void Exporter : : CreateUserPane ( wxWindow * parent )
{
2015-08-10 04:28:13 +00:00
ShuttleGui S ( parent , eIsCreating ) ;
2015-07-13 17:36:40 +00:00
S . StartVerticalLay ( ) ;
{
S . StartHorizontalLay ( wxEXPAND ) ;
{
S . StartStatic ( _ ( " Format Options " ) , 1 ) ;
{
2016-02-13 23:06:49 +00:00
mBook = safenew wxSimplebook ( S . GetParent ( ) ) ;
2015-08-05 07:28:42 +00:00
S . AddWindow ( mBook , wxEXPAND ) ;
2016-03-31 04:46:22 +00:00
for ( const auto & pPlugin : mPlugins )
2015-07-13 17:36:40 +00:00
{
2016-03-31 04:46:22 +00:00
for ( int j = 0 ; j < pPlugin - > GetFormatCount ( ) ; j + + )
2015-07-13 17:36:40 +00:00
{
2016-03-31 04:46:22 +00:00
mBook - > AddPage ( pPlugin - > OptionsCreate ( mBook , j ) , wxEmptyString ) ;
2015-07-13 17:36:40 +00:00
}
}
}
S . EndStatic ( ) ;
}
S . EndHorizontalLay ( ) ;
}
2015-08-10 04:28:13 +00:00
S . EndVerticalLay ( ) ;
2015-07-13 17:36:40 +00:00
return ;
}
void Exporter : : OnFilterChanged ( wxFileCtrlEvent & evt )
{
int index = evt . GetFilterIndex ( ) ;
2015-07-15 06:12:41 +00:00
2015-08-10 02:35:14 +00:00
// On GTK, this event can fire before the userpane is created
if ( mBook = = NULL | | index < 0 | | index > = ( int ) mBook - > GetPageCount ( ) )
2015-07-15 04:33:53 +00:00
{
return ;
}
2015-07-13 17:36:40 +00:00
2015-08-05 07:28:42 +00:00
mBook - > ChangeSelection ( index ) ;
2015-07-13 17:36:40 +00:00
}
2016-02-25 13:47:48 +00:00
bool Exporter : : ProcessFromTimerRecording ( AudacityProject * project ,
bool selectedOnly ,
double t0 ,
double t1 ,
wxFileName fnFile ,
int iFormat ,
int iSubFormat ,
int iFilterIndex )
{
// Save parms
mProject = project ;
mSelectedOnly = selectedOnly ;
mT0 = t0 ;
mT1 = t1 ;
// Auto Export Parameters
mFilename = fnFile ;
mFormat = iFormat ;
mSubFormat = iSubFormat ;
mFilterIndex = iFilterIndex ;
// Gather track information
if ( ! ExamineTracks ( ) ) {
return false ;
}
// Check for down mixing
if ( ! CheckMix ( ) ) {
return false ;
}
// Ensure filename doesn't interfere with project files.
if ( ! CheckFilename ( ) ) {
return false ;
}
// Export the tracks
bool success = ExportTracks ( ) ;
// Get rid of mixerspec
if ( mMixerSpec ) {
delete mMixerSpec ;
mMixerSpec = NULL ;
}
return success ;
}
int Exporter : : GetAutoExportFormat ( ) {
return mFormat ;
}
int Exporter : : GetAutoExportSubFormat ( ) {
return mSubFormat ;
}
int Exporter : : GetAutoExportFilterIndex ( ) {
return mFormat ;
}
wxFileName Exporter : : GetAutoExportFileName ( ) {
return mFilename ;
}
bool Exporter : : SetAutoExportOptions ( AudacityProject * project ) {
mFormat = - 1 ;
mProject = project ;
2016-04-01 10:13:32 +00:00
if ( GetFilename ( ) = = false )
return false ;
2016-02-25 13:47:48 +00:00
// Let user edit MetaData
if ( mPlugins [ mFormat ] - > GetCanMetaData ( mSubFormat ) ) {
if ( ! ( project - > DoEditMetadata ( _ ( " Edit Metadata Tags for Export " ) ,
_ ( " Exported Tags " ) , mProject - > GetShowId3Dialog ( ) ) ) ) {
return false ;
}
}
return true ;
}
2010-01-23 19:44:49 +00:00
//----------------------------------------------------------------------------
// ExportMixerPanel
//----------------------------------------------------------------------------
2016-06-25 18:18:23 +00:00
BEGIN_EVENT_TABLE ( ExportMixerPanel , wxPanelWrapper )
2010-01-23 19:44:49 +00:00
EVT_PAINT ( ExportMixerPanel : : OnPaint )
EVT_MOUSE_EVENTS ( ExportMixerPanel : : OnMouseEvent )
END_EVENT_TABLE ( )
2014-06-03 20:30:19 +00:00
ExportMixerPanel : : ExportMixerPanel ( MixerSpec * mixerSpec ,
wxArrayString trackNames , wxWindow * parent , wxWindowID id ,
2010-01-23 19:44:49 +00:00
const wxPoint & pos , const wxSize & size ) :
2016-06-25 18:18:23 +00:00
wxPanelWrapper ( parent , id , pos , size )
2010-01-23 19:44:49 +00:00
{
mBitmap = NULL ;
mWidth = 0 ;
mHeight = 0 ;
mMixerSpec = mixerSpec ;
mSelectedTrack = mSelectedChannel = - 1 ;
mTrackRects = new wxRect [ mMixerSpec - > GetNumTracks ( ) ] ;
mChannelRects = new wxRect [ mMixerSpec - > GetMaxNumChannels ( ) ] ;
mTrackNames = trackNames ;
}
ExportMixerPanel : : ~ ExportMixerPanel ( )
{
delete [ ] mTrackRects ;
delete [ ] mChannelRects ;
if ( mBitmap ) {
delete mBitmap ;
}
}
//set the font on memDC such that text can fit in specified width and height
2016-02-23 02:17:04 +00:00
void ExportMixerPanel : : SetFont ( wxMemoryDC & memDC , const wxString & text , int width ,
2010-01-23 19:44:49 +00:00
int height )
{
int l = 0 , u = 13 , m , w , h ;
wxFont font = memDC . GetFont ( ) ;
while ( l < u - 1 )
{
m = ( l + u ) / 2 ;
font . SetPointSize ( m ) ;
memDC . SetFont ( font ) ;
memDC . GetTextExtent ( text , & w , & h ) ;
if ( w < width & & h < height )
l = m ;
else
u = m ;
}
font . SetPointSize ( l ) ;
memDC . SetFont ( font ) ;
}
2013-08-25 21:51:26 +00:00
void ExportMixerPanel : : OnPaint ( wxPaintEvent & WXUNUSED ( event ) )
2010-01-23 19:44:49 +00:00
{
wxPaintDC dc ( this ) ;
int width , height ;
GetSize ( & width , & height ) ;
2014-06-03 20:30:19 +00:00
if ( ! mBitmap | | mWidth ! = width | | mHeight ! = height )
2010-01-23 19:44:49 +00:00
{
if ( mBitmap )
delete mBitmap ;
mWidth = width ;
mHeight = height ;
mBitmap = new wxBitmap ( mWidth , mHeight ) ;
}
wxColour bkgnd = GetBackgroundColour ( ) ;
wxBrush bkgndBrush ( bkgnd , wxSOLID ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
wxMemoryDC memDC ;
memDC . SelectObject ( * mBitmap ) ;
//draw background
wxRect bkgndRect ;
bkgndRect . x = 0 ;
bkgndRect . y = 0 ;
bkgndRect . width = mWidth ;
bkgndRect . height = mHeight ;
memDC . SetBrush ( * wxWHITE_BRUSH ) ;
memDC . SetPen ( * wxBLACK_PEN ) ;
memDC . DrawRectangle ( bkgndRect ) ;
//box dimensions
mBoxWidth = mWidth / 6 ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
mTrackHeight = ( mHeight * 3 ) / ( mMixerSpec - > GetNumTracks ( ) * 4 ) ;
if ( mTrackHeight > 30 )
mTrackHeight = 30 ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
mChannelHeight = ( mHeight * 3 ) / ( mMixerSpec - > GetNumChannels ( ) * 4 ) ;
if ( mChannelHeight > 30 )
mChannelHeight = 30 ;
static double PI = 2 * acos ( 0.0 ) ;
double angle = atan ( ( 3.0 * mHeight ) / mWidth ) ;
double radius = mHeight / ( 2.0 * sin ( PI - 2.0 * angle ) ) ;
double totAngle = ( asin ( mHeight / ( 2.0 * radius ) ) * 2.0 ) ;
//draw tracks
memDC . SetBrush ( AColor : : envelopeBrush ) ;
angle = totAngle / ( mMixerSpec - > GetNumTracks ( ) + 1 ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
int max = 0 , w , h ;
for ( int i = 1 ; i < mMixerSpec - > GetNumTracks ( ) ; i + + )
if ( mTrackNames [ i ] . length ( ) > mTrackNames [ max ] . length ( ) )
max = i ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
SetFont ( memDC , mTrackNames [ max ] , mBoxWidth , mTrackHeight ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
for ( int i = 0 ; i < mMixerSpec - > GetNumTracks ( ) ; i + + )
{
2014-06-03 20:30:19 +00:00
mTrackRects [ i ] . x = ( int ) ( mBoxWidth * 2 + radius - radius *
2010-01-23 19:44:49 +00:00
cos ( totAngle / 2.0 - angle * ( i + 1 ) ) - mBoxWidth + 0.5 ) ;
2014-06-03 20:30:19 +00:00
mTrackRects [ i ] . y = ( int ) ( mHeight * 0.5 - radius *
sin ( totAngle * 0.5 - angle * ( i + 1.0 ) ) -
2010-01-23 19:44:49 +00:00
0.5 * mTrackHeight + 0.5 ) ;
mTrackRects [ i ] . width = mBoxWidth ;
mTrackRects [ i ] . height = mTrackHeight ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
memDC . SetPen ( mSelectedTrack = = i ? * wxRED_PEN : * wxBLACK_PEN ) ;
memDC . DrawRectangle ( mTrackRects [ i ] ) ;
memDC . GetTextExtent ( mTrackNames [ i ] , & w , & h ) ;
2014-06-03 20:30:19 +00:00
memDC . DrawText ( mTrackNames [ i ] ,
mTrackRects [ i ] . x + ( mBoxWidth - w ) / 2 ,
2010-01-23 19:44:49 +00:00
mTrackRects [ i ] . y + ( mTrackHeight - h ) / 2 ) ;
}
//draw channels
memDC . SetBrush ( AColor : : playRegionBrush [ 0 ] ) ;
2014-06-03 20:30:19 +00:00
angle = ( asin ( mHeight / ( 2.0 * radius ) ) * 2.0 ) /
2010-01-23 19:44:49 +00:00
( mMixerSpec - > GetNumChannels ( ) + 1 ) ;
SetFont ( memDC , wxT ( " Channel: XX " ) , mBoxWidth , mChannelHeight ) ;
memDC . GetTextExtent ( wxT ( " Channel: XX " ) , & w , & h ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
for ( int i = 0 ; i < mMixerSpec - > GetNumChannels ( ) ; i + + )
{
2014-06-03 20:30:19 +00:00
mChannelRects [ i ] . x = ( int ) ( mBoxWidth * 4 - radius + radius *
2010-01-23 19:44:49 +00:00
cos ( totAngle * 0.5 - angle * ( i + 1 ) ) + 0.5 ) ;
2014-06-03 20:30:19 +00:00
mChannelRects [ i ] . y = ( int ) ( mHeight * 0.5 - radius *
sin ( totAngle * 0.5 - angle * ( i + 1 ) ) -
2010-01-23 19:44:49 +00:00
0.5 * mChannelHeight + 0.5 ) ;
mChannelRects [ i ] . width = mBoxWidth ;
mChannelRects [ i ] . height = mChannelHeight ;
memDC . SetPen ( mSelectedChannel = = i ? * wxRED_PEN : * wxBLACK_PEN ) ;
memDC . DrawRectangle ( mChannelRects [ i ] ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
memDC . DrawText ( wxString : : Format ( _ ( " Channel: %2d " ) , i + 1 ) ,
mChannelRects [ i ] . x + ( mBoxWidth - w ) / 2 ,
mChannelRects [ i ] . y + ( mChannelHeight - h ) / 2 ) ;
}
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
//draw links
memDC . SetPen ( wxPen ( * wxBLACK , mHeight / 200 ) ) ;
for ( int i = 0 ; i < mMixerSpec - > GetNumTracks ( ) ; i + + )
for ( int j = 0 ; j < mMixerSpec - > GetNumChannels ( ) ; j + + )
if ( mMixerSpec - > mMap [ i ] [ j ] )
2014-06-03 20:30:19 +00:00
AColor : : Line ( memDC , mTrackRects [ i ] . x + mBoxWidth ,
2010-01-23 19:44:49 +00:00
mTrackRects [ i ] . y + mTrackHeight / 2 , mChannelRects [ j ] . x ,
mChannelRects [ j ] . y + mChannelHeight / 2 ) ;
2014-06-03 20:30:19 +00:00
2010-01-23 19:44:49 +00:00
dc . Blit ( 0 , 0 , mWidth , mHeight , & memDC , 0 , 0 , wxCOPY , FALSE ) ;
}
double ExportMixerPanel : : Distance ( wxPoint & a , wxPoint & b )
{
return sqrt ( pow ( a . x - b . x , 2.0 ) + pow ( a . y - b . y , 2.0 ) ) ;
}
//checks if p is on the line connecting la, lb with tolerence
bool ExportMixerPanel : : IsOnLine ( wxPoint p , wxPoint la , wxPoint lb )
{
return Distance ( p , la ) + Distance ( p , lb ) - Distance ( la , lb ) < 0.1 ;
}
void ExportMixerPanel : : OnMouseEvent ( wxMouseEvent & event )
{
2014-06-03 20:30:19 +00:00
if ( event . ButtonDown ( ) )
2010-01-23 19:44:49 +00:00
{
bool reset = true ;
2014-06-03 20:30:19 +00:00
//check tracks
2010-01-23 19:44:49 +00:00
for ( int i = 0 ; i < mMixerSpec - > GetNumTracks ( ) ; i + + )
if ( mTrackRects [ i ] . Contains ( event . m_x , event . m_y ) )
{
reset = false ;
if ( mSelectedTrack = = i )
mSelectedTrack = - 1 ;
else
{
mSelectedTrack = i ;
if ( mSelectedChannel ! = - 1 )
2014-06-03 20:30:19 +00:00
mMixerSpec - > mMap [ mSelectedTrack ] [ mSelectedChannel ] =
2010-01-23 19:44:49 +00:00
! mMixerSpec - > mMap [ mSelectedTrack ] [ mSelectedChannel ] ;
}
goto found ;
}
//check channels
for ( int i = 0 ; i < mMixerSpec - > GetNumChannels ( ) ; i + + )
if ( mChannelRects [ i ] . Contains ( event . m_x , event . m_y ) )
{
reset = false ;
if ( mSelectedChannel = = i )
mSelectedChannel = - 1 ;
else
{
mSelectedChannel = i ;
if ( mSelectedTrack ! = - 1 )
2014-06-03 20:30:19 +00:00
mMixerSpec - > mMap [ mSelectedTrack ] [ mSelectedChannel ] =
2010-01-23 19:44:49 +00:00
! mMixerSpec - > mMap [ mSelectedTrack ] [ mSelectedChannel ] ;
}
goto found ;
}
//check links
for ( int i = 0 ; i < mMixerSpec - > GetNumTracks ( ) ; i + + )
for ( int j = 0 ; j < mMixerSpec - > GetNumChannels ( ) ; j + + )
if ( mMixerSpec - > mMap [ i ] [ j ] & & IsOnLine ( wxPoint ( event . m_x ,
2014-06-03 20:30:19 +00:00
event . m_y ) , wxPoint ( mTrackRects [ i ] . x + mBoxWidth ,
2010-01-23 19:44:49 +00:00
mTrackRects [ i ] . y + mTrackHeight / 2 ) ,
2014-06-03 20:30:19 +00:00
wxPoint ( mChannelRects [ j ] . x , mChannelRects [ j ] . y +
2010-01-23 19:44:49 +00:00
mChannelHeight / 2 ) ) )
mMixerSpec - > mMap [ i ] [ j ] = false ;
found :
if ( reset )
mSelectedTrack = mSelectedChannel = - 1 ;
Refresh ( false ) ;
}
}
//----------------------------------------------------------------------------
// ExportMixerDialog
//----------------------------------------------------------------------------
2013-02-23 04:33:20 +00:00
enum
2010-01-23 19:44:49 +00:00
{
2013-02-23 04:33:20 +00:00
ID_MIXERPANEL = 10001 ,
ID_SLIDER_CHANNEL
2010-01-23 19:44:49 +00:00
} ;
2016-07-10 21:10:50 +00:00
BEGIN_EVENT_TABLE ( ExportMixerDialog , wxDialogWrapper )
2010-01-23 19:44:49 +00:00
EVT_BUTTON ( wxID_OK , ExportMixerDialog : : OnOk )
EVT_BUTTON ( wxID_CANCEL , ExportMixerDialog : : OnCancel )
EVT_SIZE ( ExportMixerDialog : : OnSize )
EVT_SLIDER ( ID_SLIDER_CHANNEL , ExportMixerDialog : : OnSlider )
END_EVENT_TABLE ( )
2016-02-26 23:10:45 +00:00
ExportMixerDialog : : ExportMixerDialog ( const TrackList * tracks , bool selectedOnly ,
2014-06-03 20:30:19 +00:00
int maxNumChannels , wxWindow * parent , wxWindowID id , const wxString & title ,
2010-01-23 19:44:49 +00:00
const wxPoint & position , const wxSize & size , long style ) :
2016-07-10 21:10:50 +00:00
wxDialogWrapper ( parent , id , title , position , size , style | wxRESIZE_BORDER )
2010-01-23 19:44:49 +00:00
{
2015-05-18 12:57:05 +00:00
SetName ( GetTitle ( ) ) ;
2010-01-23 19:44:49 +00:00
int numTracks = 0 ;
2016-02-26 23:10:45 +00:00
TrackListConstIterator iter ( tracks ) ;
2010-01-23 19:44:49 +00:00
2016-02-26 23:10:45 +00:00
for ( const Track * t = iter . First ( ) ; t ; t = iter . Next ( ) )
2010-01-23 19:44:49 +00:00
{
if ( t - > GetKind ( ) = = Track : : Wave & & ( t - > GetSelected ( ) | | ! selectedOnly ) & & ! t - > GetMute ( ) )
{
numTracks + + ;
2013-03-08 03:49:39 +00:00
const wxString sTrackName = ( t - > GetName ( ) ) . Left ( 20 ) ;
2010-01-23 19:44:49 +00:00
if ( t - > GetChannel ( ) = = Track : : LeftChannel )
2013-03-08 03:43:21 +00:00
mTrackNames . Add ( sTrackName + _ ( " - L " ) ) ;
2010-01-23 19:44:49 +00:00
else if ( t - > GetChannel ( ) = = Track : : RightChannel )
2013-03-08 03:43:21 +00:00
mTrackNames . Add ( sTrackName + _ ( " - R " ) ) ;
2010-01-23 19:44:49 +00:00
else
2013-03-08 03:43:21 +00:00
mTrackNames . Add ( sTrackName ) ;
2010-01-23 19:44:49 +00:00
}
}
// JKC: This is an attempt to fix a 'watching brief' issue, where the slider is
// sometimes not slidable. My suspicion is that a mixer may incorrectly
// state the number of channels - so we assume there are always at least two.
// The downside is that if someone is exporting to a mono device, the dialog
// will allow them to output to two channels. Hmm. We may need to revisit this.
2016-04-12 20:58:08 +00:00
2010-01-23 19:44:49 +00:00
if ( maxNumChannels < 2 )
2016-04-12 20:58:08 +00:00
// STF (April 2016): AMR (narrowband) and MP3 may export 1 channel.
// maxNumChannels = 2;
maxNumChannels = 1 ;
2010-01-23 19:44:49 +00:00
if ( maxNumChannels > 32 )
maxNumChannels = 32 ;
2016-02-18 19:53:43 +00:00
mMixerSpec = new MixerSpec ( numTracks , maxNumChannels ) ;
wxBoxSizer * vertSizer ;
{
auto uVertSizer = std : : make_unique < wxBoxSizer > ( wxVERTICAL ) ;
vertSizer = uVertSizer . get ( ) ;
2010-01-23 19:44:49 +00:00
2016-02-18 19:53:43 +00:00
wxWindow * mixerPanel = safenew ExportMixerPanel ( mMixerSpec , mTrackNames , this ,
ID_MIXERPANEL , wxDefaultPosition , wxSize ( 400 , - 1 ) ) ;
mixerPanel - > SetName ( _ ( " Mixer Panel " ) ) ;
vertSizer - > Add ( mixerPanel , 1 , wxEXPAND | wxALIGN_CENTRE | wxALL , 5 ) ;
2010-01-23 19:44:49 +00:00
2016-02-18 19:53:43 +00:00
{
auto horSizer = std : : make_unique < wxBoxSizer > ( wxHORIZONTAL ) ;
2010-01-23 19:44:49 +00:00
2016-02-18 19:53:43 +00:00
wxString label ;
label . Printf ( _ ( " Output Channels: %2d " ) , mMixerSpec - > GetNumChannels ( ) ) ;
mChannelsText = safenew wxStaticText ( this , - 1 , label ) ;
horSizer - > Add ( mChannelsText , 0 , wxALIGN_LEFT | wxALL , 5 ) ;
2010-01-23 19:44:49 +00:00
2016-02-18 19:53:43 +00:00
wxSlider * channels = safenew wxSlider ( this , ID_SLIDER_CHANNEL ,
mMixerSpec - > GetNumChannels ( ) , 1 , mMixerSpec - > GetMaxNumChannels ( ) ,
wxDefaultPosition , wxSize ( 300 , - 1 ) ) ;
channels - > SetName ( label ) ;
horSizer - > Add ( channels , 0 , wxEXPAND | wxALL , 5 ) ;
2010-01-23 19:44:49 +00:00
2016-02-18 19:53:43 +00:00
vertSizer - > Add ( horSizer . release ( ) , 0 , wxALIGN_CENTRE | wxALL , 5 ) ;
}
2014-06-03 20:30:19 +00:00
2016-02-18 19:53:43 +00:00
vertSizer - > Add ( CreateStdButtonSizer ( this , eCancelButton | eOkButton ) . release ( ) , 0 , wxEXPAND ) ;
2010-01-23 19:44:49 +00:00
2016-02-18 19:53:43 +00:00
SetAutoLayout ( true ) ;
SetSizer ( uVertSizer . release ( ) ) ;
}
2010-01-23 19:44:49 +00:00
vertSizer - > Fit ( this ) ;
vertSizer - > SetSizeHints ( this ) ;
SetSizeHints ( 640 , 480 , 20000 , 20000 ) ;
SetSize ( 640 , 480 ) ;
}
ExportMixerDialog : : ~ ExportMixerDialog ( )
{
if ( mMixerSpec )
{
delete mMixerSpec ;
mMixerSpec = NULL ;
}
}
void ExportMixerDialog : : OnSize ( wxSizeEvent & event )
{
ExportMixerPanel * pnl = ( ( ExportMixerPanel * ) FindWindow ( ID_MIXERPANEL ) ) ;
pnl - > Refresh ( false ) ;
event . Skip ( ) ;
}
2013-08-25 21:51:26 +00:00
void ExportMixerDialog : : OnSlider ( wxCommandEvent & WXUNUSED ( event ) )
2010-01-23 19:44:49 +00:00
{
wxSlider * channels = ( wxSlider * ) FindWindow ( ID_SLIDER_CHANNEL ) ;
ExportMixerPanel * pnl = ( ( ExportMixerPanel * ) FindWindow ( ID_MIXERPANEL ) ) ;
mMixerSpec - > SetNumChannels ( channels - > GetValue ( ) ) ;
pnl - > Refresh ( false ) ;
wxString label ;
label . Printf ( _ ( " Output Channels: %2d " ) , mMixerSpec - > GetNumChannels ( ) ) ;
mChannelsText - > SetLabel ( label ) ;
channels - > SetName ( label ) ;
}
2013-08-25 21:51:26 +00:00
void ExportMixerDialog : : OnOk ( wxCommandEvent & WXUNUSED ( event ) )
2010-01-23 19:44:49 +00:00
{
EndModal ( wxID_OK ) ;
}
2013-08-25 21:51:26 +00:00
void ExportMixerDialog : : OnCancel ( wxCommandEvent & WXUNUSED ( event ) )
2010-01-23 19:44:49 +00:00
{
EndModal ( wxID_CANCEL ) ;
}