Audacity 3.2.0
Public Member Functions | Private Member Functions | Private Attributes | List of all members
LOFImportFileHandle Class Referencefinal

An ImportFileHandle for LOF data. More...

Inheritance diagram for LOFImportFileHandle:
[legend]
Collaboration diagram for LOFImportFileHandle:
[legend]

Public Member Functions

 LOFImportFileHandle (AudacityProject *pProject, const FilePath &name, std::unique_ptr< wxTextFile > &&file)
 
 ~LOFImportFileHandle ()
 
TranslatableString GetFileDescription () override
 
ByteCount GetFileUncompressedBytes () override
 
void Import (ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags) override
 
FilePath GetFilename () const override
 
void Cancel () override
 
void Stop () override
 
wxInt32 GetStreamCount () override
 
const TranslatableStringsGetStreamInfo () override
 
void SetStreamUsage (wxInt32 WXUNUSED(StreamID), bool WXUNUSED(Use)) override
 
- Public Member Functions inherited from ImportFileHandle
virtual ~ImportFileHandle ()
 
virtual FilePath GetFilename () const =0
 
virtual TranslatableString GetErrorMessage () const
 
virtual TranslatableString GetFileDescription ()=0
 
virtual ByteCount GetFileUncompressedBytes ()=0
 
virtual wxInt32 GetStreamCount ()=0
 
virtual const TranslatableStringsGetStreamInfo ()=0
 
virtual void SetStreamUsage (wxInt32 StreamID, bool Use)=0
 
virtual void Import (ImportProgressListener &progressListener, WaveTrackFactory *trackFactory, TrackHolders &outTracks, Tags *tags)=0
 
virtual void Cancel ()=0
 
virtual void Stop ()=0
 

Private Member Functions

void lofOpenFiles (wxString *ln)
 Processes a single line from a LOF text file, doing whatever is indicated on the line. More...
 
void doDurationAndScrollOffset ()
 

Private Attributes

std::unique_ptr< wxTextFile > mTextFile
 
const wxFileName mLOFFileName
 
AudacityProjectmProject {}
 
int nFilesInGroup { 0 }
 
bool callDurationFactor { false }
 
double durationFactor { 1 }
 
bool callScrollOffset { false }
 
double scrollOffset { 0 }
 

Additional Inherited Members

- Public Types inherited from ImportFileHandle
using ByteCount = unsigned long long
 

Detailed Description

An ImportFileHandle for LOF data.

Supports the opening of ".lof" files which are text files that contain a list of individual files to open in audacity in specific formats. Files may be file names (in the same directory as the LOF file), absolute paths or relative paths relative to the directory of the LOF file.

(In BNF) The syntax for an LOF file, denoted by <lof>:

  <lof> ::= [<window> | <file> | <#>]*
  <window> ::= window [<window-parameter>]* <newline>
  <window-parameter> ::= offset <time> | duration <time>
  <time> ::= [<digit>]+ [ . [<digit>]* ]
  <file> ::= file [<file-parameter>]* <newline>
  <file-parameter> ::= offset <time>
  <#> ::= <comment> <newline>

EXAMPLE LOF file:

  # everything following the hash character is ignored
  window # an initial window command is implicit and optional
  file "C:\folder1\sample1.wav"    # sample1.wav is displayed
  file "C:\sample2.wav" offset 5   # sample2 is displayed with a 5s offset
  File "C:\sample3.wav"            # sample3 is displayed with no offset
  File "foo.aiff" # foo is loaded from the same directory as the LOF file
  window offset 5 duration 10      # open a NEW window, zoom to display
  # 10 seconds total starting at 5 (ending at 15) seconds
  file "C:\sample3.wav" offset 2.5

SEMANTICS:

There are two commands: "window" creates a NEW window, and "file" appends a track to the current window and displays the file there. The first file is always placed in a NEW window, whether or not an initial "window" command is given.

Commands have optional keyword parameters that may be listed in any order. A parameter should only occur once per command. The "offset" parameter specifies a time offset. For windows, this is the leftmost time displayed in the window. For files, the offset is an amount by which the file is shifted in time before display (only enabled for audio; not midi). The offset is specified as an integer or decimal number of seconds, and the default value is zero.

Windows may also have a "duration" parameter, which specifies how much time should be displayed in the window. The default duration is equal to the duration of the longest track currently displayed.

Definition at line 117 of file ImportLOF.cpp.

Constructor & Destructor Documentation

◆ LOFImportFileHandle()

LOFImportFileHandle::LOFImportFileHandle ( AudacityProject pProject,
const FilePath name,
std::unique_ptr< wxTextFile > &&  file 
)

Definition at line 170 of file ImportLOF.cpp.

172: mTextFile(std::move(file))
174 , mProject{ pProject }
175{
176}
const TranslatableString name
Definition: Distortion.cpp:76
const wxFileName mLOFFileName
Definition: ImportLOF.cpp:154
std::unique_ptr< wxTextFile > mTextFile
Definition: ImportLOF.cpp:153
AudacityProject * mProject
Definition: ImportLOF.cpp:156

◆ ~LOFImportFileHandle()

LOFImportFileHandle::~LOFImportFileHandle ( )

Definition at line 576 of file ImportLOF.cpp.

577{
578}

Member Function Documentation

◆ Cancel()

void LOFImportFileHandle::Cancel ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 329 of file ImportLOF.cpp.

330{
331 //LOFImport delegates import to other plugins
332}

◆ doDurationAndScrollOffset()

void LOFImportFileHandle::doDurationAndScrollOffset ( )
private

Definition at line 550 of file ImportLOF.cpp.

551{
552 if (!mProject)
553 return;
554
556 bool doSomething = callDurationFactor || callScrollOffset;
557
559 {
560 double longestDuration = TrackList::Get(*mProject).GetEndTime();
561 ProjectWindow::Get( *mProject ).ZoomBy(longestDuration / durationFactor);
562 callDurationFactor = false;
563 }
564
566 {
568 callScrollOffset = false;
569 }
570
571 if (doSomething)
572 // Amend last undo state
573 ProjectHistory::Get( *mProject ).ModifyState(false);
574}
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
void ZoomBy(double multiplier)
static ProjectWindow & Get(AudacityProject &project)
void TP_ScrollWindow(double scrollto) override
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
Definition: Track.cpp:1008
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:354

References callDurationFactor, callScrollOffset, durationFactor, ProjectHistory::Get(), TrackList::Get(), ProjectWindow::Get(), TrackList::GetEndTime(), ProjectHistory::ModifyState(), mProject, scrollOffset, ProjectWindow::TP_ScrollWindow(), and ProjectWindow::ZoomBy().

Referenced by Import(), and lofOpenFiles().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFileDescription()

TranslatableString LOFImportFileHandle::GetFileDescription ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 265 of file ImportLOF.cpp.

266{
267 return DESC;
268}
#define DESC
Definition: ImportLOF.cpp:94

References DESC.

◆ GetFilename()

FilePath LOFImportFileHandle::GetFilename ( ) const
overridevirtual

Implements ImportFileHandle.

Definition at line 324 of file ImportLOF.cpp.

325{
326 return mLOFFileName.GetFullPath();
327}

References mLOFFileName.

◆ GetFileUncompressedBytes()

auto LOFImportFileHandle::GetFileUncompressedBytes ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 270 of file ImportLOF.cpp.

271{
272 return 0;
273}

◆ GetStreamCount()

wxInt32 LOFImportFileHandle::GetStreamCount ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 137 of file ImportLOF.cpp.

137{ return 1; }

◆ GetStreamInfo()

const TranslatableStrings & LOFImportFileHandle::GetStreamInfo ( )
inlineoverridevirtual

Implements ImportFileHandle.

Definition at line 139 of file ImportLOF.cpp.

140 {
141 static TranslatableStrings empty;
142 return empty;
143 }
std::vector< TranslatableString > TranslatableStrings

◆ Import()

void LOFImportFileHandle::Import ( ImportProgressListener progressListener,
WaveTrackFactory trackFactory,
TrackHolders outTracks,
Tags tags 
)
overridevirtual

Implements ImportFileHandle.

Definition at line 275 of file ImportLOF.cpp.

279{
280 // Unlike other ImportFileHandle subclasses, this one never gives any tracks
281 // back to the caller.
282 // Instead, it recursively calls AudacityProject::Import for each file listed
283 // in the .lof file.
284 // Each importation creates a NEW undo state.
285 // If there is an error or exception during one of them, only that one's
286 // side effects are rolled back, and the rest of the import list is skipped.
287 // The file may have "window" directives that cause NEW AudacityProjects
288 // to be created, and the undo states are pushed onto the latest project.
289 // If a project is created but the first file import into it fails, destroy
290 // the project.
291
292 outTracks.clear();
293
294 wxASSERT(mTextFile->IsOpened());
295
296 if(mTextFile->Eof())
297 {
298 mTextFile->Close();
300 return;
301 }
302
303 wxString line = mTextFile->GetFirstLine();
304
305 while (!mTextFile->Eof())
306 {
307 lofOpenFiles(&line);
308 line = mTextFile->GetNextLine();
309 }
310
311 // for last line
312 lofOpenFiles(&line);
313
314 if(!mTextFile->Close())
315 {
317 return;
318 }
319 // set any duration/offset factors for last window, as all files were called
322}
virtual void OnImportResult(ImportResult result)=0
Used to report on import result for file handle passed as argument to OnImportFileOpened.
void lofOpenFiles(wxString *ln)
Processes a single line from a LOF text file, doing whatever is indicated on the line.
Definition: ImportLOF.cpp:370
void doDurationAndScrollOffset()
Definition: ImportLOF.cpp:550

References doDurationAndScrollOffset(), ImportProgressListener::Error, lofOpenFiles(), mTextFile, ImportProgressListener::OnImportResult(), and ImportProgressListener::Success.

Here is the call graph for this function:

◆ lofOpenFiles()

void LOFImportFileHandle::lofOpenFiles ( wxString *  ln)
private

Processes a single line from a LOF text file, doing whatever is indicated on the line.

This function should just return for lines it cannot deal with, and the caller will continue to the next line of the input file

Definition at line 370 of file ImportLOF.cpp.

371{
372 wxStringTokenizer tok(*ln, wxT(" "));
373 wxStringTokenizer temptok1(*ln, wxT("\""));
374 wxStringTokenizer temptok2(*ln, wxT(" "));
375 int tokenplace = 0;
376
377 wxString targetfile;
378 wxString tokenholder = tok.GetNextToken();
379
380
381 if (tokenholder.IsSameAs(wxT("window"), false))
382 {
383 // set any duration/offset factors for last window, as all files were called
385
386 if (nFilesInGroup > 0 )
387 // Cause a project to be created with the next import
388 mProject = nullptr;
389
390 nFilesInGroup = 0;
391
392 while (tok.HasMoreTokens())
393 {
394 tokenholder = tok.GetNextToken();
395
396 if (tokenholder.IsSameAs(wxT("offset"), false))
397 {
398 if (tok.HasMoreTokens())
399 tokenholder = tok.GetNextToken();
400
402 {
403 callScrollOffset = true;
404 }
405 else
406 {
408 /* i18n-hint: You do not need to translate "LOF" */
409 XO("Invalid window offset in LOF file."));
410 }
411
412 if (tok.HasMoreTokens())
413 tokenholder = tok.GetNextToken();
414 }
415
416 if (tokenholder.IsSameAs(wxT("duration"), false))
417 {
418 if (tok.HasMoreTokens())
419 tokenholder = tok.GetNextToken();
420
422 {
423 callDurationFactor = true;
424 }
425 else
426 {
428 /* i18n-hint: You do not need to translate "LOF" */
429 XO("Invalid duration in LOF file."));
430 }
431 } // End if statement
432
433 if (tokenholder == wxT("#"))
434 {
435 // # indicates comments; ignore line
436 tok = wxStringTokenizer(wxT(""), wxT(" "));
437 }
438 } // End while loop
439 } // End if statement handling "window" lines
440
441 else if (tokenholder.IsSameAs(wxT("file"), false))
442 {
444 // To identify filename and open it
445 tokenholder = temptok1.GetNextToken();
446 wxString targettoken = temptok1.GetNextToken();
447 targetfile = targettoken;
448
449 // If path is relative, make absolute path from LOF path
450 if(!wxIsAbsolutePath(targetfile)) {
451 wxFileName fName(targetfile);
452 fName.Normalize(wxPATH_NORM_ALL, mLOFFileName.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
453 if(fName.FileExists()) {
454 targetfile = fName.GetFullPath();
455 }
456 }
457
458 // Do recursive call to import
459
460#ifdef USE_MIDI
461 // If file is a midi
462 if (FileNames::IsMidi(targetfile))
463 {
465 }
466
467 // If not a midi, open audio file
468 else
469
470#else // !USE_MIDI
471 /* if we don't have midi support, go straight on to opening as an
472 * audio file. TODO: Some sort of message here? */
473
474#endif // USE_MIDI
476 true /* addtohistory */, true /* reuseNonemptyProject */ );
477
478 // Set tok to right after filename
479 temptok2.SetString(targettoken);
480 tokenplace = temptok2.CountTokens();
481
482 for (int i = 0; i < tokenplace; i++)
483 tokenholder = tok.GetNextToken();
484
485 if (tok.HasMoreTokens())
486 {
487 tokenholder = tok.GetNextToken();
488
489 if (tokenholder == wxT("#"))
490 {
491 // # indicates comments; ignore line
492 tok = wxStringTokenizer(wxT(""), wxT(" "));
493 }
494
495 if (tokenholder.IsSameAs(wxT("offset"), false))
496 {
497 if (tok.HasMoreTokens())
498 tokenholder = tok.GetNextToken();
499 double offset;
500
501 // handle an "offset" specifier
502 if (!mProject)
503 // there was an import error,
504 // presumably with its own error message
505 ;
506 else if (Internat::CompatibleToDouble(tokenholder, &offset))
507 {
508 auto &tracks = TrackList::Get( *mProject );
509 auto t = *tracks.rbegin();
510
511 // t is now the last track in the project, unless the import of
512 // all tracks failed, in which case it will be null. In that
513 // case we return because we cannot offset a non-existent track.
514 if (t == NULL)
515 return;
516#ifdef USE_MIDI
517 if (targetfile.AfterLast(wxT('.')).IsSameAs(wxT("mid"), false) ||
518 targetfile.AfterLast(wxT('.')).IsSameAs(wxT("midi"), false))
519 {
520 ImportUtils::ShowMessageBox(XO("MIDI tracks cannot be offset individually, only audio files can be."));
521 }
522 else
523#endif
524 t->MoveTo(offset);
525
526 // Amend the undo transaction made by import
527 ProjectHistory::Get( *mProject ).ModifyState(false);
528 } // end of converting "offset" argument
529 else
530 {
532 /* i18n-hint: You do not need to translate "LOF" */
533 XO("Invalid track offset in LOF file."));
534 }
535 } // End if statement for "offset" parameters
536 } // End if statement (more tokens after file name)
537 } // End if statement "file" lines
538
539 else if (tokenholder == wxT("#"))
540 {
541 // # indicates comments; ignore line
542 tok = wxStringTokenizer(wxT(""), wxT(" "));
543 }
544 else
545 {
546 // Couldn't parse a line
547 }
548}
wxT("CloseDown"))
XO("Cut/Copy/Paste")
static AudacityProject * DoImportMIDIProject(AudacityProject *pProject, const FilePath &fileName)
Definition: ImportLOF.cpp:346
const auto tracks
static void ShowMessageBox(const TranslatableString &message, const TranslatableString &caption=XO("Import Project"))
Definition: ImportUtils.cpp:43
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:133
static AudacityProject * OpenProject(AudacityProject *pGivenProject, const FilePath &fileNameArg, bool addtohistory, bool reuseNonemptyProject)
Open a file into an AudacityProject, returning the project, or nullptr for failure.
FILES_API bool IsMidi(const FilePath &fName)

References callDurationFactor, callScrollOffset, Internat::CompatibleToDouble(), doDurationAndScrollOffset(), DoImportMIDIProject(), durationFactor, ProjectHistory::Get(), TrackList::Get(), FileNames::IsMidi(), mLOFFileName, ProjectHistory::ModifyState(), mProject, nFilesInGroup, ProjectManager::OpenProject(), scrollOffset, ImportUtils::ShowMessageBox(), tracks, wxT(), and XO().

Referenced by Import().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetStreamUsage()

void LOFImportFileHandle::SetStreamUsage ( wxInt32   WXUNUSEDStreamID,
bool   WXUNUSEDUse 
)
inlineoverride

Definition at line 145 of file ImportLOF.cpp.

146 {}

◆ Stop()

void LOFImportFileHandle::Stop ( )
overridevirtual

Implements ImportFileHandle.

Definition at line 334 of file ImportLOF.cpp.

335{
336 //LOFImport delegates import to other plugins
337}

Member Data Documentation

◆ callDurationFactor

bool LOFImportFileHandle::callDurationFactor { false }
private

Definition at line 162 of file ImportLOF.cpp.

Referenced by doDurationAndScrollOffset(), and lofOpenFiles().

◆ callScrollOffset

bool LOFImportFileHandle::callScrollOffset { false }
private

Definition at line 166 of file ImportLOF.cpp.

Referenced by doDurationAndScrollOffset(), and lofOpenFiles().

◆ durationFactor

double LOFImportFileHandle::durationFactor { 1 }
private

Definition at line 163 of file ImportLOF.cpp.

Referenced by doDurationAndScrollOffset(), and lofOpenFiles().

◆ mLOFFileName

const wxFileName LOFImportFileHandle::mLOFFileName
private

The name of the LOF file, which is used to interpret relative paths in it

Definition at line 154 of file ImportLOF.cpp.

Referenced by GetFilename(), and lofOpenFiles().

◆ mProject

AudacityProject* LOFImportFileHandle::mProject {}
private

Definition at line 156 of file ImportLOF.cpp.

Referenced by doDurationAndScrollOffset(), and lofOpenFiles().

◆ mTextFile

std::unique_ptr<wxTextFile> LOFImportFileHandle::mTextFile
private

Definition at line 153 of file ImportLOF.cpp.

Referenced by Import().

◆ nFilesInGroup

int LOFImportFileHandle::nFilesInGroup { 0 }
private

Definition at line 159 of file ImportLOF.cpp.

Referenced by lofOpenFiles().

◆ scrollOffset

double LOFImportFileHandle::scrollOffset { 0 }
private

Definition at line 167 of file ImportLOF.cpp.

Referenced by doDurationAndScrollOffset(), and lofOpenFiles().


The documentation for this class was generated from the following file: