From e1a3d5b87883b5faadbd43326326d4c5aadc871d Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Sun, 30 Sep 2012 21:53:03 +0000 Subject: various fixes and changes --- muse2/ChangeLog | 6 +++ muse2/muse/arranger/pcanvas.cpp | 41 +++------------- muse2/muse/arranger/tlist.cpp | 40 +++++++++++++++- muse2/muse/audiotrack.cpp | 42 +++++++++++++++-- muse2/muse/functions.cpp | 97 +++++++++++++++++++++++++++----------- muse2/muse/functions.h | 6 +++ muse2/muse/mixer/astrip.cpp | 6 ++- muse2/muse/mixer/strip.cpp | 6 ++- muse2/muse/song.h | 1 + muse2/muse/track.h | 3 ++ muse2/muse/waveedit/wavecanvas.cpp | 43 ++++++++++++++++- muse2/muse/waveedit/wavecanvas.h | 1 + muse2/muse/waveedit/waveedit.cpp | 4 ++ muse2/muse/waveedit/waveedit.h | 1 + 14 files changed, 228 insertions(+), 69 deletions(-) diff --git a/muse2/ChangeLog b/muse2/ChangeLog index a8b29d58..a7c185c1 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,9 @@ +30.09.2012: + - Added part creation from wave editor - to make this really usable + more functions to set tempo etc, are needed (rj) + - Fixed name length of Aux ports and added index (rj) + - Fixed issue with moving aux:es in the track list causing the auxes + to be mixed up (rj) 29.09.2012: - Added handling of missing soundfonts in fluidsynth load so a dialog asking for replacement soundfont pops up (rj) diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 1afea012..3c3e6116 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -2829,40 +2829,13 @@ void PartCanvas::copy(MusECore::PartList* pl) } MusECore::Pos p(tick, true); MusEGlobal::song->setPos(0, p); - - //--------------------------------------------------- - // read tmp file into QTextDrag Object - //--------------------------------------------------- - - fflush(tmp); - struct stat f_stat; - if (fstat(fileno(tmp), &f_stat) == -1) { - fprintf(stderr, "PartCanvas::copy() fstat failed:<%s>\n", - strerror(errno)); - fclose(tmp); - return; - } - int n = f_stat.st_size; - char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE, - MAP_PRIVATE, fileno(tmp), 0); - fbuf[n] = 0; - - QByteArray data(fbuf); - QMimeData* md = new QMimeData(); - - - if(midi && wave) - md->setData("text/x-muse-mixedpartlist", data); // By T356. Support mixed .mpt files. - else - if(midi) - md->setData("text/x-muse-midipartlist", data); - else - if(wave) - md->setData("text/x-muse-wavepartlist", data); - - QApplication::clipboard()->setMimeData(md, QClipboard::Clipboard); - - munmap(fbuf, n); + QString mimeString = "text/x-muse-mixedpartlist"; + if (!midi) + mimeString = "text/x-muse-wavepartlist"; + else if (!wave) + mimeString = "text/x-muse-midipartlist"; + QMimeData *mimeData = MusECore::file_to_mimedata(tmp, mimeString ); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); fclose(tmp); } diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index 76dd18ff..d16a8d29 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -378,7 +378,11 @@ void TList::paint(const QRect& r) } break; case COL_NAME: - p.drawText(r, Qt::AlignVCenter|Qt::AlignLeft, track->name()); + if (track->type() == MusECore::Track::AUDIO_AUX) { + p.drawText(r, Qt::AlignVCenter|Qt::AlignLeft, ((MusECore::AudioAux *)track)->auxName()); + } else { + p.drawText(r, Qt::AlignVCenter|Qt::AlignLeft, track->name()); + } break; case COL_OCHANNEL: { @@ -2435,8 +2439,42 @@ void TList::mouseReleaseEvent(QMouseEvent* ev) if (t) { int dTrack = MusEGlobal::song->tracks()->index(t); MusEGlobal::audio->msgMoveTrack(sTrack, dTrack); + MusECore::TrackList *tracks = MusEGlobal::song->tracks(); + if ( tracks->at(dTrack)->type() == MusECore::Track::AUDIO_AUX) { + + MusECore::AuxList auxCopy; // = *MusEGlobal::song->auxs(); + //MusEGlobal::song->auxs()->clear(); + std::vector oldAuxIndex; + + for (MusECore::iTrack t = tracks->begin(); t != tracks->end(); ++t) { + if ((*t)->type() == MusECore::Track::AUDIO_AUX) { + MusECore::AudioAux *ax = (MusECore::AudioAux*)*t; + auxCopy.push_back(ax); + oldAuxIndex.push_back(MusEGlobal::song->auxs()->index(ax)); // store old index + } + } + // loop through all tracks and set the levels for all tracks + for (MusECore::iTrack t = tracks->begin(); t != tracks->end(); ++t) { + MusECore::AudioTrack *trk = (MusECore::AudioTrack*)*t; + if (trk->hasAuxSend()) + { + std::vector oldAuxValue; + for (unsigned i = 0 ; i < auxCopy.size(); i++) + oldAuxValue.push_back(trk->auxSend(i)); + for (unsigned i = 0 ; i < auxCopy.size(); i++) + trk->setAuxSend(i, oldAuxValue[oldAuxIndex[i]] ); + } + MusEGlobal::song->auxs()->clear(); + for (MusECore::iAudioAux t = auxCopy.begin(); t != auxCopy.end(); ++t) { + MusEGlobal::song->auxs()->push_back(*t); + } + } + + MusEGlobal::song->update(SC_EVERYTHING); + } } + } if (mode != NORMAL) { mode = NORMAL; setCursor(QCursor(Qt::ArrowCursor)); diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp index b9e245d2..f9c298a6 100644 --- a/muse2/muse/audiotrack.cpp +++ b/muse2/muse/audiotrack.cpp @@ -1710,9 +1710,32 @@ void AudioAux::write(int level, Xml& xml) const { xml.tag(level++, "AudioAux"); AudioTrack::writeProperties(level, xml); + xml.intTag(level, "index", _index); xml.etag(level, "AudioAux"); } + +//--------------------------------------------------------- +// getNextAuxIndex +//--------------------------------------------------------- +int getNextAuxIndex() +{ + printf("getNextAuxIndex!\n"); + int curAux=0; + AuxList * al = MusEGlobal::song->auxs(); + for (MusECore::iAudioAux i = al->begin(); i != al->end(); ++i) + { + MusECore::AudioAux* ax = *i; + printf("ax index %d\n", ax->index()); + if (ax->index() > curAux) + { + printf("found new index! %d\n", ax->index()); + curAux = ax->index(); + } + } + return curAux+1; +} + //--------------------------------------------------------- // AudioAux //--------------------------------------------------------- @@ -1720,25 +1743,27 @@ void AudioAux::write(int level, Xml& xml) const AudioAux::AudioAux() : AudioTrack(AUDIO_AUX) { + _index = getNextAuxIndex(); for(int i = 0; i < MAX_CHANNELS; ++i) { if(i < channels()) posix_memalign((void**)(buffer + i), 16, sizeof(float) * MusEGlobal::segmentSize); else buffer[i] = 0; - } + } } AudioAux::AudioAux(const AudioAux& t, int flags) : AudioTrack(t, flags) { + _index = getNextAuxIndex(); for(int i = 0; i < MAX_CHANNELS; ++i) { if(i < channels()) posix_memalign((void**)(buffer + i), 16, sizeof(float) * MusEGlobal::segmentSize); else buffer[i] = 0; - } + } } //--------------------------------------------------------- // AudioAux @@ -1766,7 +1791,9 @@ void AudioAux::read(Xml& xml) case Xml::End: return; case Xml::TagStart: - if (AudioTrack::readProperties(xml, tag)) + if (tag == "index") + _index = xml.parseInt(); + else if (AudioTrack::readProperties(xml, tag)) xml.unknown("AudioAux"); break; case Xml::Attribut: @@ -1838,6 +1865,15 @@ void AudioAux::setChannels(int n) AudioTrack::setChannels(n); } +//--------------------------------------------------------- +// setName +//--------------------------------------------------------- + +QString AudioAux::auxName() +{ + return QString("%1:").arg(index())+ name(); +} + //--------------------------------------------------------- // setRecordFlag1 // gui part (executed in gui thread) diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index da5826e5..fa53f5d4 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -950,20 +950,51 @@ void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Pa paste_at(s, MusEGlobal::song->cpos(), max_distance, always_new_part, never_new_part, paste_into_part, amount, raster); } - // if nothing is selected/relevant, this function returns NULL QMimeData* selected_events_to_mime(const set& parts, int range) { - unsigned start_tick = INT_MAX; //will be the tick of the first event or INT_MAX if no events are there - - for (set::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++) - if (is_relevant(ev->second, *part, range)) - if (ev->second.tick() < start_tick) - start_tick=ev->second.tick(); - - if (start_tick == INT_MAX) - return NULL; + unsigned start_tick = INT_MAX; //will be the tick of the first event or INT_MAX if no events are there + + for (set::iterator part=parts.begin(); part!=parts.end(); part++) + for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++) + if (is_relevant(ev->second, *part, range)) + if (ev->second.tick() < start_tick) + start_tick=ev->second.tick(); + + if (start_tick == INT_MAX) + return NULL; + + //--------------------------------------------------- + // write events as XML into tmp file + //--------------------------------------------------- + + FILE* tmp = tmpfile(); + if (tmp == 0) + { + fprintf(stderr, "EventCanvas::getTextDrag() fopen failed: %s\n", strerror(errno)); + return 0; + } + + Xml xml(tmp); + int level = 0; + + for (set::iterator part=parts.begin(); part!=parts.end(); part++) + { + xml.tag(level++, "eventlist part_id=\"%d\"", (*part)->sn()); + for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++) + if (is_relevant(ev->second, *part, range)) + ev->second.write(level, xml, -start_tick); + xml.etag(--level, "eventlist"); + } + + QMimeData *mimeData = file_to_mimedata(tmp, "text/x-muse-groupedeventlists" ); + fclose(tmp); + return mimeData; +} + +// if nothing is selected/relevant, this function returns NULL +QMimeData* parts_to_mime(const set& parts) +{ //--------------------------------------------------- // write events as XML into tmp file @@ -979,40 +1010,52 @@ QMimeData* selected_events_to_mime(const set& parts, int range) Xml xml(tmp); int level = 0; + bool midi=false; + bool wave=false; for (set::iterator part=parts.begin(); part!=parts.end(); part++) { - xml.tag(level++, "eventlist part_id=\"%d\"", (*part)->sn()); - for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++) - if (is_relevant(ev->second, *part, range)) - ev->second.write(level, xml, -start_tick); - xml.etag(--level, "eventlist"); - } + if ((*part)->track()->type() == MusECore::Track::MIDI) + midi=true; + else + wave=true; + (*part)->write(level, xml, true, true); + } + QString mimeString = "text/x-muse-mixedpartlist"; + if (!midi) + mimeString = "text/x-muse-wavepartlist"; + else if (!wave) + mimeString = "text/x-muse-midipartlist"; + QMimeData *mimeData = file_to_mimedata(tmp, mimeString ); + fclose(tmp); + return mimeData; +} - //--------------------------------------------------- - // read tmp file into drag Object - //--------------------------------------------------- +//--------------------------------------------------- +// read datafile into mime Object +//--------------------------------------------------- +QMimeData* file_to_mimedata(FILE *datafile, QString mimeType) +{ - fflush(tmp); + fflush(datafile); struct stat f_stat; - if (fstat(fileno(tmp), &f_stat) == -1) + if (fstat(fileno(datafile), &f_stat) == -1) { fprintf(stderr, "copy_notes() fstat failed:<%s>\n", strerror(errno)); - fclose(tmp); + fclose(datafile); return 0; } int n = f_stat.st_size; char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE, - MAP_PRIVATE, fileno(tmp), 0); + MAP_PRIVATE, fileno(datafile), 0); fbuf[n] = 0; QByteArray data(fbuf); - QMimeData* md = new QMimeData(); - md->setData("text/x-muse-groupedeventlists", data); + QMimeData* md = new QMimeData(); + md->setData(mimeType, data); munmap(fbuf, n); - fclose(tmp); return md; } diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h index c81dd2bc..31c91fe4 100644 --- a/muse2/muse/functions.h +++ b/muse2/muse/functions.h @@ -88,6 +88,9 @@ void copy_notes(const std::set& parts, int range); bool paste_notes(Part* paste_into_part=NULL); // shows a dialog void paste_notes(int max_distance=3072, bool always_new_part=false, bool never_new_part=false, Part* paste_into_part=NULL, int amount=1, int raster=3072); QMimeData* selected_events_to_mime(const std::set& parts, int range); +QMimeData* parts_to_mime(const std::set& parts); + + void paste_at(const QString& pt, int pos, int max_distance=3072, bool always_new_part=false, bool never_new_part=false, Part* paste_into_part=NULL, int amount=1, int raster=3072); //functions for selections @@ -105,6 +108,9 @@ void clean_parts(); bool merge_selected_parts(); bool merge_parts(const std::set& parts); +// internal +QMimeData* file_to_mimedata(FILE *datafile, QString mimeType); + } // namespace MusECore #endif diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp index a75968a1..530ca7e2 100644 --- a/muse2/muse/mixer/astrip.cpp +++ b/muse2/muse/mixer/astrip.cpp @@ -821,7 +821,11 @@ AudioStrip::AudioStrip(QWidget* parent, MusECore::AudioTrack* at) for (int idx = 0; idx < auxsSize; ++idx) { MusEGui::DoubleLabel* al; // the thought was to aquire the correct Aux name for each Aux // now they are only called Aux1, Aux2, which isn't too usable. - QLabel *name = new QLabel(((MusECore::Track*)(MusEGlobal::song->auxs()->at(idx)))->name(),this); + QString title = ((MusECore::AudioAux*)(MusEGlobal::song->auxs()->at(idx)))->auxName(); + if (title.length() > 8) { // shorten name + title = title.mid(0,8) + "."; + } + QLabel *name = new QLabel(title,this); MusEGui::Knob* ak = addKnob(1, idx, &al, name); auxKnob.push_back(ak); diff --git a/muse2/muse/mixer/strip.cpp b/muse2/muse/mixer/strip.cpp index f34d5320..06ee9443 100644 --- a/muse2/muse/mixer/strip.cpp +++ b/muse2/muse/mixer/strip.cpp @@ -159,7 +159,11 @@ void Strip::setLabelText() return; } - label->setText(track->name()); + if (track->type() == MusECore::Track::AUDIO_AUX) { + label->setText(((MusECore::AudioAux*)track)->auxName()); + } else { + label->setText(track->name()); + } QPalette palette; //palette.setColor(label->backgroundRole(), c); QLinearGradient gradient(label->geometry().topLeft(), label->geometry().bottomLeft()); diff --git a/muse2/muse/song.h b/muse2/muse/song.h index 9a314533..e9e893f1 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -99,6 +99,7 @@ class AudioDevice; #define SC_MIDI_TRACK_PROP 0x10000000 // a midi track's properties changed (channel, compression etc) #define SC_SONG_TYPE 0x20000000 // the midi song type (mtype) changed #define SC_KEY 0x40000000 // key map changed +#define SC_EVERYTHING -1 // global update #define REC_NOTE_FIFO_SIZE 16 diff --git a/muse2/muse/track.h b/muse2/muse/track.h index 3efc6912..c7423ed2 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -560,6 +560,7 @@ class AudioGroup : public AudioTrack { class AudioAux : public AudioTrack { float* buffer[MAX_CHANNELS]; static bool _isVisible; + int _index; public: AudioAux(); AudioAux(const AudioAux& t, int flags); @@ -575,6 +576,8 @@ class AudioAux : public AudioTrack { static void setVisible(bool t) { _isVisible = t; } virtual int height() const; static bool visible() { return _isVisible; } + virtual QString auxName(); + virtual int index() { return _index; } }; diff --git a/muse2/muse/waveedit/wavecanvas.cpp b/muse2/muse/waveedit/wavecanvas.cpp index 8c1b0012..1fa070ec 100644 --- a/muse2/muse/waveedit/wavecanvas.cpp +++ b/muse2/muse/waveedit/wavecanvas.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include "app.h" #include "xml.h" @@ -1862,8 +1863,46 @@ void WaveCanvas::cmd(int cmd) paramA = 0.25; break; - - + case CMD_CREATE_PART_REGION: + { + // create a new part and put in the copy buffer + MusECore::Part* pt = editor->curCanvasPart(); + if (pt == 0 || pt->track()->type() != MusECore::Track::WAVE) + return; + MusECore::WavePart *origPart = (MusECore::WavePart*)pt; + if (MusEGlobal::song->lpos() < origPart->tick() || MusEGlobal::song->rpos() > origPart->endTick()) + { + QMessageBox::warning(this, tr("Part creation failed"), + tr("Left and right position markers must be placed inside the current part."), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + MusECore::WavePart *tempPart = new MusECore::WavePart(origPart->track()); + unsigned origFrame = origPart->frame(); + unsigned frameDistance = MusEGlobal::song->lPos().frame() - origFrame; + tempPart->setPos(MusEGlobal::song->lpos()); + tempPart->setLenTick(MusEGlobal::song->rpos() - MusEGlobal::song->lpos()); + // loop through the events and set them accordingly + for (MusECore::iEvent iWaveEvent = origPart->events()->begin(); iWaveEvent != origPart->events()->end(); iWaveEvent++) + { + // TODO: handle multiple events correctly, + // the math for subsequent events isn't correct + MusECore::Event &ev = iWaveEvent->second; + MusECore::Event *newEvent = new MusECore::Event(ev.clone()); + newEvent->setSpos(ev.spos() + frameDistance); + newEvent->setLenTick(MusEGlobal::song->rpos() - MusEGlobal::song->lpos()); + tempPart->addEvent(*newEvent); + } + std::set partList; + partList.insert(tempPart); + + QMimeData *mimeData = MusECore::parts_to_mime(partList); + QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); + QMessageBox::information(this, tr("Part created"), + tr("The selected region has been copied to the clipboard and can be pasted in the arranger."), + QMessageBox::Ok, QMessageBox::Ok); + } + break; case CMD_ERASE_MEASURE: case CMD_DELETE_MEASURE: case CMD_CREATE_MEASURE: diff --git a/muse2/muse/waveedit/wavecanvas.h b/muse2/muse/waveedit/wavecanvas.h index f9553845..5ad836bc 100644 --- a/muse2/muse/waveedit/wavecanvas.h +++ b/muse2/muse/waveedit/wavecanvas.h @@ -154,6 +154,7 @@ class WaveCanvas : public EventCanvas { enum { CMD_MUTE=0, CMD_NORMALIZE, CMD_FADE_IN, CMD_FADE_OUT, CMD_REVERSE, CMD_GAIN_FREE, CMD_GAIN_200, CMD_GAIN_150, CMD_GAIN_75, CMD_GAIN_50, CMD_GAIN_25, CMD_EDIT_COPY, CMD_EDIT_CUT, CMD_EDIT_PASTE, CMD_PASTE_DIALOG, CMD_DEL, + CMD_CREATE_PART_REGION, CMD_EDIT_EXTERNAL, CMD_QUANTIZE, CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT, diff --git a/muse2/muse/waveedit/waveedit.cpp b/muse2/muse/waveedit/waveedit.cpp index 56185a83..ca98e380 100644 --- a/muse2/muse/waveedit/waveedit.cpp +++ b/muse2/muse/waveedit/waveedit.cpp @@ -139,6 +139,10 @@ WaveEdit::WaveEdit(MusECore::PartList* pl) mapper->setMapping(copyAction, WaveCanvas::CMD_EDIT_COPY); connect(copyAction, SIGNAL(triggered()), mapper, SLOT(map())); + copyPartRegionAction = menuEdit->addAction(tr("&Create Part from Region")); + mapper->setMapping(copyPartRegionAction, WaveCanvas::CMD_CREATE_PART_REGION); + connect(copyPartRegionAction, SIGNAL(triggered()), mapper, SLOT(map())); + cutAction = menuEdit->addAction(tr("C&ut")); mapper->setMapping(cutAction, WaveCanvas::CMD_EDIT_CUT); connect(cutAction, SIGNAL(triggered()), mapper, SLOT(map())); diff --git a/muse2/muse/waveedit/waveedit.h b/muse2/muse/waveedit/waveedit.h index 7165a63a..f0bcf199 100644 --- a/muse2/muse/waveedit/waveedit.h +++ b/muse2/muse/waveedit/waveedit.h @@ -68,6 +68,7 @@ class WaveEdit : public MidiEditor { QAction* selectNoneAction; QAction* cutAction; QAction* copyAction; + QAction* copyPartRegionAction; QAction* pasteAction; QAction* selectPrevPartAction; QAction* selectNextPartAction; -- cgit v1.2.3