1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-06 14:52:34 +02:00
audacity/src/NoteTrack.cpp
businessmanprogrammersteve a55c20be66 Fix most of the compile warnings I get on Linux (but not the Audacity Logo
xpm stuff or a few things in FFMPEG export)
2010-02-12 21:36:20 +00:00

378 lines
9.6 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
NoteTrack.cpp
Dominic Mazzoni
*******************************************************************//*!
\class NoteTrack
\brief A Track that is used for Midi notes. (Somewhat old code).
*//*******************************************************************/
#include <wx/dc.h>
#include <wx/brush.h>
#include <wx/pen.h>
#include <wx/intl.h>
#include "Audacity.h"
#if defined(USE_MIDI)
#include "allegro.h"
/* REQUIRES PORTMIDI */
//#include "portmidi.h"
//#include "porttime.h"
#include "AColor.h"
#include "NoteTrack.h"
#include "DirManager.h"
NoteTrack *TrackFactory::NewNoteTrack()
{
return new NoteTrack(mDirManager);
}
NoteTrack::NoteTrack(DirManager * projDirManager):
Track(projDirManager)
{
SetDefaultName(_("Note Track"));
SetName(GetDefaultName());
mSeq = NULL;
mLen = 0.0;
mSerializationBuffer = NULL;
mSerializationLength = 0;
mDirManager = projDirManager;
mBottomNote = 24;
mVisibleChannels = 0xFFFF;
mLastMidiPosition = 0;
}
NoteTrack::~NoteTrack()
{
if (mSerializationBuffer) {
delete [] mSerializationBuffer;
}
if (mSeq) {
delete mSeq;
}
}
Track *NoteTrack::Duplicate()
{
NoteTrack *duplicate = new NoteTrack(mDirManager);
// Duplicate on NoteTrack moves data from mSeq to mSerializationBuffer
// and from mSerializationBuffer to mSeq on alternate calls. Duplicate
// to the undo stack and Duplicate back to the project should result
// in serialized blobs on the undo stack and traversable data in the
// project object.
if (mSeq) {
assert(!mSerializationBuffer);
// serialize from this to duplicate's mSerializationBuffer
mSeq->serialize((void**)&duplicate->mSerializationBuffer,
&duplicate->mSerializationLength);
} else if (mSerializationBuffer) {
assert(!mSeq);
Alg_track_ptr alg_track = Alg_seq::unserialize(mSerializationBuffer,
mSerializationLength);
assert(alg_track->get_type() == 's');
duplicate->mSeq = (Alg_seq_ptr) alg_track;
} else assert(false); // bug if neither mSeq nor mSerializationBuffer
// copy some other fields here
duplicate->mBottomNote = mBottomNote;
duplicate->mLastMidiPosition = mLastMidiPosition;
duplicate->mLen = mLen;
duplicate->mVisibleChannels = mVisibleChannels;
return duplicate;
}
void NoteTrack::DrawLabelControls(wxDC & dc, wxRect & r)
{
int wid = 23;
int ht = 16;
if (r.height < ht * 4) {
return;
}
int x = r.x + (r.width / 2 - wid * 2) + 2;
int y = r.y + 5;
for (int row = 0; row < 4; row++) {
for (int col = 0; col < 4; col++) {
int channel = row * 4 + col + 1;
wxRect box;
box.x = x + col * wid;
box.y = y + row * ht;
box.width = wid;
box.height = ht;
if (mVisibleChannels & (1 << (channel - 1))) {
AColor::MIDIChannel(&dc, channel);
dc.DrawRectangle(box);
AColor::LightMIDIChannel(&dc, channel);
AColor::Line(dc, box.x, box.y, box.x + box.width - 1, box.y);
AColor::Line(dc, box.x, box.y, box.x, box.y + box.height - 1);
AColor::DarkMIDIChannel(&dc, channel);
AColor::Line(dc,
box.x + box.width - 1, box.y,
box.x + box.width - 1, box.y + box.height - 1);
AColor::Line(dc,
box.x, box.y + box.height - 1,
box.x + box.width - 1, box.y + box.height - 1);
} else {
AColor::MIDIChannel(&dc, 0);
dc.DrawRectangle(box);
}
wxString t;
long w;
long h;
t.Printf(wxT("%d"), channel);
dc.GetTextExtent(t, &w, &h);
dc.DrawText(t, box.x + (box.width - w) / 2, box.y + (box.height - h) / 2);
}
}
}
bool NoteTrack::LabelClick(wxRect & r, int mx, int my, bool right)
{
int wid = 23;
int ht = 16;
if (r.height < ht * 4)
return false;
int x = r.x + (r.width / 2 - wid * 2);
int y = r.y + 1;
int col = (mx - x) / wid;
int row = (my - y) / ht;
if (row < 0 || row >= 4 || col < 0 || col >= 4)
return false;
int channel = row * 4 + col;
if (right) {
if (mVisibleChannels == (1 << channel))
mVisibleChannels = 0xFFFF;
else
mVisibleChannels = (1 << channel);
} else
mVisibleChannels ^= (1 << channel);
return true;
}
void NoteTrack::SetSequence(Alg_seq_ptr seq)
{
if (mSeq)
delete mSeq;
mSeq = seq;
mLen = (seq ? seq->get_real_dur() : 0.0);
}
Alg_seq* NoteTrack::GetSequence()
{
return mSeq;
}
void NoteTrack::PrintSequence()
{
FILE *debugOutput;
debugOutput = fopen("debugOutput.txt", "wt");
fprintf(debugOutput, "Importing MIDI...\n");
if (mSeq) {
int i = 0;
while(i < mSeq->length()) {
fprintf(debugOutput, "--\n");
fprintf(debugOutput, "type: %c\n",
((Alg_event_ptr)mSeq->track_list.tracks[i])->get_type());
fprintf(debugOutput, "time: %f\n",
((Alg_event_ptr)mSeq->track_list.tracks[i])->time);
fprintf(debugOutput, "channel: %li\n",
((Alg_event_ptr)mSeq->track_list.tracks[i])->chan);
if(((Alg_event_ptr)mSeq->track_list.tracks[i])->get_type() == wxT('n'))
{
fprintf(debugOutput, "pitch: %f\n",
((Alg_note_ptr)mSeq->track_list.tracks[i])->pitch);
fprintf(debugOutput, "duration: %f\n",
((Alg_note_ptr)mSeq->track_list.tracks[i])->dur);
fprintf(debugOutput, "velocity: %f\n",
((Alg_note_ptr)mSeq->track_list.tracks[i])->loud);
}
else if(((Alg_event_ptr)mSeq->track_list.tracks[i])->get_type() == wxT('n'))
{
fprintf(debugOutput, "key: %li\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->get_identifier());
fprintf(debugOutput, "attribute type: %c\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type());
fprintf(debugOutput, "attribute: %s\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_name());
if(((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type() == wxT('r'))
{
fprintf(debugOutput, "value: %f\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.r);
}
else if(((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type() == wxT('i')) {
fprintf(debugOutput, "value: %li\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.i);
}
else if(((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.attr_type() == wxT('s')) {
fprintf(debugOutput, "value: %s\n", ((Alg_update_ptr)mSeq->track_list.tracks[i])->parameter.s);
}
else {}
}
i++;
}
}
else {
fprintf(debugOutput, "No sequence defined!\n");
}
fclose(debugOutput);
}
int NoteTrack::GetVisibleChannels()
{
return mVisibleChannels;
}
bool NoteTrack::Cut(double t0, double t1, Track **dest){
//dest goes onto clipboard
*dest = NULL; // This is redundant
if (t1 <= t0)
return false;
double len = t1-t0;
NoteTrack *newTrack = new NoteTrack(mDirManager);
newTrack->Init(*this);
mSeq->convert_to_seconds();
newTrack->mSeq = mSeq->cut(t0, len, false);
mLen = (mLen <= len ? 0.0 : mLen - len);
newTrack->mLen = len;
// What should be done with the rest of newTrack's members?
//(mBottomNote, mDirManager, mLastMidiPosition,
// mSerializationBuffer, mSerializationLength, mVisibleChannels)
*dest = newTrack;
return true;
}
bool NoteTrack::Copy(double t0, double t1, Track **dest){
//dest goes onto clipboard
*dest = NULL; // This is redundant and matches WaveTrack::Copy
if (t1 <= t0)
return false;
double len = t1-t0;
NoteTrack *newTrack = new NoteTrack(mDirManager);
newTrack->Init(*this);
mSeq->convert_to_seconds();
newTrack->mSeq = mSeq->copy(t0, len, false);
newTrack->mLen = len;
// What should be done with the rest of newTrack's members?
//(mBottomNote, mDirManager, mLastMidiPosition,
// mSerializationBuffer, mSerializationLength, mVisibleChannels)
*dest = newTrack;
return true;
}
bool NoteTrack::Clear(double t0, double t1){
// If t1 = t0, should Clear return true?
if (t1 <= t0)
return false;
double len = t1-t0;
mSeq->clear(t0, len, false);
return true;
}
bool NoteTrack::Paste(double t, Track *src){
//Check that src is a non-NULL NoteTrack
if (src == NULL || src->GetKind() != Track::Note)
return false;
NoteTrack* other = (NoteTrack*)src;
if (other->mSeq == NULL)
return false;
if(!mSeq)
mSeq = new Alg_seq();
mSeq->paste(t, other->mSeq);
mLen = mSeq->get_real_dur();
return true;
}
bool NoteTrack::ExportMIDI(wxString f)
{
return mSeq->smf_write(f.mb_str());
}
bool NoteTrack::ExportAllegro(wxString f)
{
return mSeq->write(f.mb_str());
}
bool NoteTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
{
return false;
}
XMLTagHandler *NoteTrack::HandleXMLChild(const wxChar *tag)
{
return NULL;
}
void NoteTrack::WriteXML(XMLWriter &xmlFile)
{
}
#endif // USE_MIDI
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
// version control system. Please do not modify past this point.
//
// Local Variables:
// c-basic-offset: 3
// indent-tabs-mode: nil
// End:
//
// vim: et sts=3 sw=3
// arch-tag: ecfdee12-5b16-4f27-84d1-4a3800d07d1e