Audacity 3.2.0
ImportMIDI.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ImportMIDI.cpp
6
7 Dominic Mazzoni
8
9**********************************************************************/
10
11
12#include "ImportMIDI.h"
13
14#include <wx/defs.h>
15#include <wx/ffile.h>
16#include <wx/frame.h>
17
18#if defined(USE_MIDI)
19
20
21#include "../lib-src/header-substitutes/allegro.h"
22
23//#include "strparse.h"
24//#include "mfmidi.h"
25
26#include "FileNames.h"
27#include "../NoteTrack.h"
28#include "Project.h"
29#include "ProjectFileIO.h"
30#include "ProjectHistory.h"
31#include "../ProjectWindow.h"
32#include "ProjectWindows.h"
33#include "SelectFile.h"
34#include "../SelectUtilities.h"
35#include "AudacityMessageBox.h"
36#include "../widgets/FileHistory.h"
37
38// Given an existing project, try to import into it, return true on success
40{
41 auto &projectFileIO = ProjectFileIO::Get( project );
42 auto &tracks = TrackList::Get( project );
43 auto newTrack = std::make_shared<NoteTrack>();
44 bool initiallyEmpty = tracks.empty();
45
46 if (::ImportMIDI(fileName, newTrack.get())) {
47
49 auto pTrack = tracks.Add( newTrack );
50 pTrack->SetSelected(true);
51
52 // Fix the bug 2109.
53 // In case the project had soloed tracks before importing,
54 // the newly imported track is muted.
55 const bool projectHasSolo =
56 !(tracks.Any<PlayableTrack>() + &PlayableTrack::GetSolo).empty();
57#ifdef EXPERIMENTAL_MIDI_OUT
58 if (projectHasSolo)
59 pTrack->SetMute(true);
60#endif
61
63 .PushState(
64 XO("Imported MIDI from '%s'").Format( fileName ),
65 XO("Import MIDI")
66 );
67
69 FileHistory::Global().Append(fileName);
70
71 // If the project was clean and temporary (not permanently saved), then set
72 // the filename to the just imported path.
73 if (initiallyEmpty && projectFileIO.IsTemporary()) {
74 wxFileName fn(fileName);
75 project.SetProjectName(fn.GetName());
76 project.SetInitialImportPath(fn.GetPath());
77 projectFileIO.SetProjectTitle();
78 }
79 return true;
80 }
81 else
82 return false;
83}
84
85bool ImportMIDI(const FilePath &fName, NoteTrack * dest)
86{
87 if (fName.length() <= 4){
89 XO("Could not open file %s: Filename too short.").Format( fName ) );
90 return false;
91 }
92
93 bool is_midi = false;
94 if (fName.Right(4).CmpNoCase(wxT(".mid")) == 0 || fName.Right(5).CmpNoCase(wxT(".midi")) == 0)
95 is_midi = true;
96 else if(fName.Right(4).CmpNoCase(wxT(".gro")) != 0) {
98 XO("Could not open file %s: Incorrect filetype.").Format( fName ) );
99 return false;
100 }
101
102 wxFFile mf(fName, wxT("rb"));
103 if (!mf.IsOpened()) {
105 XO("Could not open file %s.").Format( fName ) );
106 return false;
107 }
108
109 double offset = 0.0;
110 auto new_seq = std::make_unique<Alg_seq>(fName.mb_str(), is_midi, &offset);
111
112 //Should we also check if(seq->tracks() == 0) ?
113 if(new_seq->get_read_error() == alg_error_open){
115 XO("Could not open file %s.").Format( fName ) );
116 mf.Close();
117 return false;
118 }
119
120 dest->SetSequence(std::move(new_seq));
121 dest->MoveTo(offset);
122 wxString trackNameBase = fName.AfterLast(wxFILE_SEP_PATH).BeforeLast('.');
123 dest->SetName(trackNameBase);
124 mf.Close();
125
126 dest->ZoomAllNotes();
127 return true;
128}
129
130// Insert a menu item
131#include "../commands/CommandContext.h"
132#include "../commands/CommandManager.h"
133#include "../CommonCommandFlags.h"
134
135namespace {
136using namespace MenuTable;
137
138void OnImportMIDI(const CommandContext &context)
139{
140 auto &project = context.project;
141 auto &window = GetProjectFrame( project );
142
143 wxString fileName = SelectFile(FileNames::Operation::Open,
144 XO("Select a MIDI file"),
145 wxEmptyString, // Path
146 wxT(""), // Name
147 wxT(""), // Extension
148 {
149 { XO("MIDI and Allegro files"),
150 { wxT("mid"), wxT("midi"), wxT("gro"), }, true },
151 { XO("MIDI files"),
152 { wxT("mid"), wxT("midi"), }, true },
153 { XO("Allegro files"),
154 { wxT("gro"), }, true },
156 },
157 wxRESIZE_BORDER, // Flags
158 &window); // Parent
159
160 if (!fileName.empty())
161 DoImportMIDI(project, fileName);
162}
163
165 { wxT("File/Import-Export/Import"),
166 { OrderingHint::After, {"ImportAudio"} } },
167 Command( wxT("ImportMIDI"), XXO("&MIDI..."), OnImportMIDI,
169};
170
171}
172#endif
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
const ReservedCommandFlag & AudioIONotBusyFlag()
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
bool DoImportMIDI(AudacityProject &project, const FilePath &fileName)
Definition: ImportMIDI.cpp:39
bool ImportMIDI(const FilePath &fName, NoteTrack *dest)
Definition: ImportMIDI.cpp:85
wxString FilePath
Definition: Project.h:21
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
const auto tracks
const auto project
static const auto fn
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
void Append(const FilePath &file)
Definition: FileHistory.h:46
static FileHistory & Global()
Definition: FileHistory.cpp:39
FILES_API const FileType AllFiles
Definition: FileNames.h:70
Abstract base class used in importing a file.
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:65
void SetSequence(std::unique_ptr< Alg_seq > &&seq)
Definition: NoteTrack.cpp:388
void MoveTo(double origin) override
Change start time to given time point.
Definition: NoteTrack.h:81
void ZoomAllNotes()
Zooms so that all notes are visible.
Definition: NoteTrack.cpp:1106
AudioTrack subclass that can also be audibly replayed by the program.
Definition: PlayableTrack.h:40
bool GetSolo() const
Definition: PlayableTrack.h:48
static ProjectFileIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
void ZoomAfterImport(Track *pTrack)
static ProjectWindow & Get(AudacityProject &project)
void SetName(const wxString &n)
Definition: Track.cpp:61
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:354
constexpr auto Command
void SelectNone(AudacityProject &project)
void OnImportMIDI(const CommandContext &context)
Definition: ImportMIDI.cpp:138