diff options
Diffstat (limited to 'muse2/muse/functions.cpp')
-rw-r--r-- | muse2/muse/functions.cpp | 469 |
1 files changed, 270 insertions, 199 deletions
diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index fa53f5d4..7569cc95 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -2,7 +2,7 @@ // MusE // Linux Music Editor // $Id: functions.cpp,v 1.20.2.19 2011/05/05 20:10 flo93 Exp $ -// (C) Copyright 2011 Florian Jung (flo93@sourceforge.net) +// (C) Copyright 2011,2013 Florian Jung (flo93@sourceforge.net) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -71,9 +71,9 @@ bool read_eventlist_and_part(Xml& xml, EventList* el, int* part_id); -set<Part*> partlist_to_set(PartList* pl) +set<const Part*> partlist_to_set(PartList* pl) { - set<Part*> result; + set<const Part*> result; for (PartList::iterator it=pl->begin(); it!=pl->end(); it++) result.insert(it->second); @@ -81,16 +81,16 @@ set<Part*> partlist_to_set(PartList* pl) return result; } -set<Part*> part_to_set(Part* p) +set<const Part*> part_to_set(const Part* p) { - set<Part*> result; + set<const Part*> result; result.insert(p); return result; } -set<Part*> get_all_parts() +set<const Part*> get_all_parts() { - set<Part*> result; + set<const Part*> result; TrackList* tracks=MusEGlobal::song->tracks(); for (TrackList::const_iterator t_it=tracks->begin(); t_it!=tracks->end(); t_it++) @@ -103,9 +103,9 @@ set<Part*> get_all_parts() return result; } -set<Part*> get_all_selected_parts() +set<const Part*> get_all_selected_parts() { - set<Part*> result; + set<const Part*> result; TrackList* tracks=MusEGlobal::song->tracks(); for (TrackList::const_iterator t_it=tracks->begin(); t_it!=tracks->end(); t_it++) @@ -137,14 +137,14 @@ bool is_relevant(const Event& event, const Part* part, int range) } -map<Event*, Part*> get_events(const set<Part*>& parts, int range) +map<const Event*, const Part*> get_events(const set<const Part*>& parts, int range) { - map<Event*, Part*> events; + map<const Event*, const Part*> events; - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent event=(*part)->events()->begin(); event!=(*part)->events()->end(); event++) + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent event=(*part)->events().begin(); event!=(*part)->events().end(); event++) if (is_relevant(event->second, *part, range)) - events.insert(pair<Event*, Part*>(&event->second, *part)); + events.insert(pair<const Event*, const Part*>(&event->second, *part)); return events; } @@ -152,7 +152,7 @@ map<Event*, Part*> get_events(const set<Part*>& parts, int range) -bool modify_notelen(const set<Part*>& parts) +bool modify_notelen(const set<const Part*>& parts) { if (!MusEGui::gatetime_dialog->exec()) return false; @@ -162,7 +162,7 @@ bool modify_notelen(const set<Part*>& parts) return true; } -bool modify_velocity(const set<Part*>& parts) +bool modify_velocity(const set<const Part*>& parts) { if (!MusEGui::velocity_dialog->exec()) return false; @@ -172,7 +172,7 @@ bool modify_velocity(const set<Part*>& parts) return true; } -bool quantize_notes(const set<Part*>& parts) +bool quantize_notes(const set<const Part*>& parts) { if (!MusEGui::quantize_dialog->exec()) return false; @@ -185,7 +185,7 @@ bool quantize_notes(const set<Part*>& parts) return true; } -bool erase_notes(const set<Part*>& parts) +bool erase_notes(const set<const Part*>& parts) { if (!MusEGui::erase_dialog->exec()) return false; @@ -196,7 +196,7 @@ bool erase_notes(const set<Part*>& parts) return true; } -bool delete_overlaps(const set<Part*>& parts) +bool delete_overlaps(const set<const Part*>& parts) { if (!MusEGui::del_overlaps_dialog->exec()) return false; @@ -206,7 +206,7 @@ bool delete_overlaps(const set<Part*>& parts) return true; } -bool set_notelen(const set<Part*>& parts) +bool set_notelen(const set<const Part*>& parts) { if (!MusEGui::set_notelen_dialog->exec()) return false; @@ -216,7 +216,7 @@ bool set_notelen(const set<Part*>& parts) return true; } -bool move_notes(const set<Part*>& parts) +bool move_notes(const set<const Part*>& parts) { if (!MusEGui::move_notes_dialog->exec()) return false; @@ -226,7 +226,7 @@ bool move_notes(const set<Part*>& parts) return true; } -bool transpose_notes(const set<Part*>& parts) +bool transpose_notes(const set<const Part*>& parts) { if (!MusEGui::transpose_dialog->exec()) return false; @@ -236,7 +236,7 @@ bool transpose_notes(const set<Part*>& parts) return true; } -bool crescendo(const set<Part*>& parts) +bool crescendo(const set<const Part*>& parts) { if (MusEGlobal::song->rpos() <= MusEGlobal::song->lpos()) { @@ -252,7 +252,7 @@ bool crescendo(const set<Part*>& parts) return true; } -bool legato(const set<Part*>& parts) +bool legato(const set<const Part*>& parts) { if (!MusEGui::legato_dialog->exec()) return false; @@ -269,7 +269,7 @@ bool modify_notelen() if (!MusEGui::gatetime_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::gatetime_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -285,7 +285,7 @@ bool modify_velocity() if (!MusEGui::velocity_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::velocity_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -301,7 +301,7 @@ bool quantize_notes() if (!MusEGui::quantize_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::quantize_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -320,7 +320,7 @@ bool erase_notes() if (!MusEGui::erase_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::erase_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -337,7 +337,7 @@ bool delete_overlaps() if (!MusEGui::del_overlaps_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::del_overlaps_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -353,7 +353,7 @@ bool set_notelen() if (!MusEGui::set_notelen_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::set_notelen_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -369,7 +369,7 @@ bool move_notes() if (!MusEGui::move_notes_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::move_notes_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -385,7 +385,7 @@ bool transpose_notes() if (!MusEGui::transpose_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::transpose_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -407,7 +407,7 @@ bool crescendo() if (!MusEGui::crescendo_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::crescendo_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -423,7 +423,7 @@ bool legato() if (!MusEGui::legato_dialog->exec()) return false; - set<Part*> parts; + set<const Part*> parts; if (MusEGui::legato_dialog->range & FUNCTION_RANGE_ONLY_SELECTED) parts=get_all_selected_parts(); else @@ -439,17 +439,17 @@ bool legato() -bool modify_velocity(const set<Part*>& parts, int range, int rate, int offset) +bool modify_velocity(const set<const Part*>& parts, int range, int rate, int offset) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; if ( (!events.empty()) && ((rate!=100) || (offset!=0)) ) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; int velo = event.velo(); @@ -475,17 +475,17 @@ bool modify_velocity(const set<Part*>& parts, int range, int rate, int offset) return false; } -bool modify_off_velocity(const set<Part*>& parts, int range, int rate, int offset) +bool modify_off_velocity(const set<const Part*>& parts, int range, int rate, int offset) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; if ( (!events.empty()) && ((rate!=100) || (offset!=0)) ) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; int velo = event.veloOff(); @@ -511,18 +511,18 @@ bool modify_off_velocity(const set<Part*>& parts, int range, int rate, int offse return false; } -bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset) +bool modify_notelen(const set<const Part*>& parts, int range, int rate, int offset) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; - map<Part*, int> partlen; + map<const Part*, int> partlen; if ( (!events.empty()) && ((rate!=100) || (offset!=0)) ) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned @@ -543,7 +543,7 @@ bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset) } } - for (map<Part*, int>::iterator it=partlen.begin(); it!=partlen.end(); it++) + for (map<const Part*, int>::iterator it=partlen.begin(); it!=partlen.end(); it++) schedule_resize_all_same_len_clone_parts(it->first, it->second, operations); return MusEGlobal::song->applyOperationGroup(operations); @@ -552,7 +552,7 @@ bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset) return false; } -bool set_notelen(const set<Part*>& parts, int range, int len) +bool set_notelen(const set<const Part*>& parts, int range, int len) { return modify_notelen(parts, range, 0, len); } @@ -579,17 +579,17 @@ unsigned quantize_tick(unsigned tick, unsigned raster, int swing) return tick_dest1; } -bool quantize_notes(const set<Part*>& parts, int range, int raster, bool quant_len, int strength, int swing, int threshold) +bool quantize_notes(const set<const Part*>& parts, int range, int raster, bool quant_len, int strength, int swing, int threshold) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; if (!events.empty()) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; unsigned begin_tick = event.tick() + part->tick(); int begin_diff = quantize_tick(begin_tick, raster, swing) - begin_tick; @@ -625,17 +625,17 @@ bool quantize_notes(const set<Part*>& parts, int range, int raster, bool quant_l return false; } -bool erase_notes(const set<Part*>& parts, int range, int velo_threshold, bool velo_thres_used, int len_threshold, bool len_thres_used) +bool erase_notes(const set<const Part*>& parts, int range, int velo_threshold, bool velo_thres_used, int len_threshold, bool len_thres_used) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; if (!events.empty()) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; if ( (!velo_thres_used && !len_thres_used) || (velo_thres_used && event.velo() < velo_threshold) || @@ -649,17 +649,17 @@ bool erase_notes(const set<Part*>& parts, int range, int velo_threshold, bool ve return false; } -bool transpose_notes(const set<Part*>& parts, int range, signed int halftonesteps) +bool transpose_notes(const set<const Part*>& parts, int range, signed int halftonesteps) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; if ( (!events.empty()) && (halftonesteps!=0) ) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; Event newEvent = event.clone(); int pitch = event.pitch()+halftonesteps; @@ -675,9 +675,9 @@ bool transpose_notes(const set<Part*>& parts, int range, signed int halftonestep return false; } -bool crescendo(const set<Part*>& parts, int range, int start_val, int end_val, bool absolute) +bool crescendo(const set<const Part*>& parts, int range, int start_val, int end_val, bool absolute) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; int from=MusEGlobal::song->lpos(); @@ -685,10 +685,10 @@ bool crescendo(const set<Part*>& parts, int range, int start_val, int end_val, b if ( (!events.empty()) && (to>from) ) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; unsigned tick = event.tick() + part->tick(); float curr_val= (float)start_val + (float)(end_val-start_val) * (tick-from) / (to-from); @@ -713,18 +713,18 @@ bool crescendo(const set<Part*>& parts, int range, int start_val, int end_val, b return false; } -bool move_notes(const set<Part*>& parts, int range, signed int ticks) +bool move_notes(const set<const Part*>& parts, int range, signed int ticks) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; - map<Part*, int> partlen; + map<const Part*, int> partlen; if ( (!events.empty()) && (ticks!=0) ) { - for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++) + for (map<const Event*, const Part*>::iterator it=events.begin(); it!=events.end(); it++) { - Event& event=*(it->first); - Part* part=it->second; + const Event& event=*(it->first); + const Part* part=it->second; bool del=false; Event newEvent = event.clone(); @@ -752,7 +752,7 @@ bool move_notes(const set<Part*>& parts, int range, signed int ticks) operations.push_back(UndoOp(UndoOp::DeleteEvent, event, part, false, false)); } - for (map<Part*, int>::iterator it=partlen.begin(); it!=partlen.end(); it++) + for (map<const Part*, int>::iterator it=partlen.begin(); it!=partlen.end(); it++) schedule_resize_all_same_len_clone_parts(it->first, it->second, operations); return MusEGlobal::song->applyOperationGroup(operations); @@ -762,29 +762,29 @@ bool move_notes(const set<Part*>& parts, int range, signed int ticks) } -bool delete_overlaps(const set<Part*>& parts, int range) +bool delete_overlaps(const set<const Part*>& parts, int range) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; - set<Event*> deleted_events; + set<const Event*> deleted_events; if (!events.empty()) { - for (map<Event*, Part*>::iterator it1=events.begin(); it1!=events.end(); it1++) + for (map<const Event*, const Part*>::iterator it1=events.begin(); it1!=events.end(); it1++) { - Event& event1=*(it1->first); - Part* part1=it1->second; + const Event& event1=*(it1->first); + const Part* part1=it1->second; // we may NOT optimize by letting it2 start at (it1 +1); this optimisation // is only allowed when events was sorted by time. it is, however, sorted // randomly by pointer. - for (map<Event*, Part*>::iterator it2=events.begin(); it2!=events.end(); it2++) + for (map<const Event*, const Part*>::iterator it2=events.begin(); it2!=events.end(); it2++) { - Event& event2=*(it2->first); - Part* part2=it2->second; + const Event& event2=*(it2->first); + const Part* part2=it2->second; - if ( (part1->events()==part2->events()) && // part1 and part2 are the same or are duplicates + if ( (part1->isCloneOf(part2)) && // part1 and part2 are the same or are duplicates (&event1 != &event2) && // and event1 and event2 aren't the same (deleted_events.find(&event2) == deleted_events.end()) ) //and event2 hasn't been deleted before { @@ -817,34 +817,34 @@ bool delete_overlaps(const set<Part*>& parts, int range) return false; } -bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten) +bool legato(const set<const Part*>& parts, int range, int min_len, bool dont_shorten) { - map<Event*, Part*> events = get_events(parts, range); + map<const Event*, const Part*> events = get_events(parts, range); Undo operations; if (min_len<=0) min_len=1; if (!events.empty()) { - for (map<Event*, Part*>::iterator it1=events.begin(); it1!=events.end(); it1++) + for (map<const Event*, const Part*>::iterator it1=events.begin(); it1!=events.end(); it1++) { - Event& event1=*(it1->first); - Part* part1=it1->second; + const Event& event1=*(it1->first); + const Part* part1=it1->second; unsigned len=INT_MAX; // we may NOT optimize by letting it2 start at (it1 +1); this optimisation // is only allowed when events was sorted by time. it is, however, sorted // randomly by pointer. - for (map<Event*, Part*>::iterator it2=events.begin(); it2!=events.end(); it2++) + for (map<const Event*, const Part*>::iterator it2=events.begin(); it2!=events.end(); it2++) { - Event& event2=*(it2->first); - Part* part2=it2->second; + const Event& event2=*(it2->first); + const Part* part2=it2->second; bool relevant = (event2.tick() >= event1.tick() + min_len); if (dont_shorten) relevant = relevant && (event2.tick() >= event1.endTick()); - if ( (part1->events()==part2->events()) && // part1 and part2 are the same or are duplicates + if ( (part1->isCloneOf(part2)) && // part1 and part2 are the same or are duplicates relevant && // they're not too near (respect min_len and dont_shorten) (event2.tick()-event1.tick() < len ) ) // that's the nearest relevant following note len=event2.tick()-event1.tick(); @@ -869,7 +869,7 @@ bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten) -void copy_notes(const set<Part*>& parts, int range) +void copy_notes(const set<const Part*>& parts, int range) { QMimeData* drag = selected_events_to_mime(parts,range); @@ -926,7 +926,7 @@ unsigned get_clipboard_len() return get_groupedevents_len(s); } -bool paste_notes(Part* paste_into_part) +bool paste_notes(const Part* paste_into_part) { unsigned temp_begin = AL::sigmap.raster1(MusEGlobal::song->cpos(),0); unsigned temp_end = AL::sigmap.raster2(temp_begin + get_clipboard_len(), 0); @@ -943,7 +943,7 @@ bool paste_notes(Part* paste_into_part) return true; } -void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part, int amount, int raster) +void paste_notes(int max_distance, bool always_new_part, bool never_new_part, const Part* paste_into_part, int amount, int raster) { QString tmp="x-muse-groupedeventlists"; // QClipboard::text() expects a QString&, not a QString :( QString s = QApplication::clipboard()->text(tmp, QClipboard::Clipboard); // TODO CHECK Tim. @@ -951,12 +951,12 @@ void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Pa } // if nothing is selected/relevant, this function returns NULL -QMimeData* selected_events_to_mime(const set<Part*>& parts, int range) +QMimeData* selected_events_to_mime(const set<const Part*>& 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<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++) + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent 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(); @@ -978,10 +978,10 @@ QMimeData* selected_events_to_mime(const set<Part*>& parts, int range) Xml xml(tmp); int level = 0; - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (set<const Part*>::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++) + for (ciEvent 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"); @@ -993,7 +993,7 @@ QMimeData* selected_events_to_mime(const set<Part*>& parts, int range) } // if nothing is selected/relevant, this function returns NULL -QMimeData* parts_to_mime(const set<Part*>& parts) +QMimeData* parts_to_mime(const set<const Part*>& parts) { //--------------------------------------------------- @@ -1012,7 +1012,7 @@ QMimeData* parts_to_mime(const set<Part*>& parts) bool midi=false; bool wave=false; - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) { if ((*part)->track()->type() == MusECore::Track::MIDI) midi=true; @@ -1102,11 +1102,11 @@ bool read_eventlist_and_part(Xml& xml, EventList* el, int* part_id) // true on s } } -void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part, int amount, int raster) +void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part, bool never_new_part, const Part* paste_into_part, int amount, int raster) { Undo operations; - map<Part*, unsigned> expand_map; - map<Part*, set<Part*> > new_part_map; + map<const Part*, unsigned> expand_map; + map<const Part*, set<const Part*> > new_part_map; QByteArray pt_= pt.toLatin1(); Xml xml(pt_.constData()); @@ -1128,9 +1128,9 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part if (read_eventlist_and_part(xml, &el, &part_id)) { - Part* dest_part; + const Part* dest_part; Track* dest_track; - Part* old_dest_part; + const Part* old_dest_part; if (paste_into_part == NULL) dest_part = partFromSerialNumber(part_id); @@ -1157,13 +1157,12 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part if (create_new_part) { - dest_part = dest_track->newPart(); - dest_part->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it - // so we must decrement it first :/ - dest_part->setTick(AL::sigmap.raster1(first_paste_tick, config.division)); + Part* newpart = dest_track->newPart(); + newpart->setTick(AL::sigmap.raster1(first_paste_tick, config.division)); new_part_map[old_dest_part].insert(dest_part); operations.push_back(UndoOp(UndoOp::AddPart, dest_part)); + dest_part = newpart; } for (iEvent i = el.begin(); i != el.end(); ++i) @@ -1218,7 +1217,7 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part out_of_paste_at_for: - for (map<Part*, unsigned>::iterator it = expand_map.begin(); it!=expand_map.end(); it++) + for (map<const Part*, unsigned>::iterator it = expand_map.begin(); it!=expand_map.end(); it++) if (it->second != it->first->lenTick()) schedule_resize_all_same_len_clone_parts(it->first, it->second, operations); @@ -1228,61 +1227,76 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part MusEGlobal::song->update(SC_SELECTION); } -void select_all(const std::set<Part*>& parts) +void select_all(const set<const Part*>& parts) { - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++) + Undo operations; + operations.combobreaker=true; + + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent ev_it=(*part)->events().begin(); ev_it!=(*part)->events().end(); ev_it++) { - Event& event=ev_it->second; - event.setSelected(true); + const Event& event=ev_it->second; + operations.push_back(UndoOp(UndoOp::SelectEvent,event, true, event.selected())); } - MusEGlobal::song->update(SC_SELECTION); + MusEGlobal::song->applyOperationGroup(operations); } -void select_none(const std::set<Part*>& parts) +void select_none(const set<const Part*>& parts) { - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++) + Undo operations; + operations.combobreaker=true; + + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent ev_it=(*part)->events().begin(); ev_it!=(*part)->events().end(); ev_it++) { - Event& event=ev_it->second; - event.setSelected(false); + const Event& event=ev_it->second; + operations.push_back(UndoOp(UndoOp::SelectEvent,event, false, event.selected())); } - MusEGlobal::song->update(SC_SELECTION); + MusEGlobal::song->applyOperationGroup(operations); } -void select_invert(const std::set<Part*>& parts) +void select_invert(const set<const Part*>& parts) { - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++) + Undo operations; + operations.combobreaker=true; + + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent ev_it=(*part)->events().begin(); ev_it!=(*part)->events().end(); ev_it++) { - Event& event=ev_it->second; - event.setSelected(!event.selected()); + const Event& event=ev_it->second; + operations.push_back(UndoOp(UndoOp::SelectEvent,event, !event.selected(), event.selected())); } - MusEGlobal::song->update(SC_SELECTION); + MusEGlobal::song->applyOperationGroup(operations); } -void select_in_loop(const std::set<Part*>& parts) +void select_in_loop(const set<const Part*>& parts) { select_none(parts); - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++) + Undo operations; + operations.combobreaker=true; + + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent ev_it=(*part)->events().begin(); ev_it!=(*part)->events().end(); ev_it++) { - Event& event=ev_it->second; - event.setSelected((event.tick()>=MusEGlobal::song->lpos() && event.endTick()<=MusEGlobal::song->rpos())); + const Event& event=ev_it->second; + operations.push_back(UndoOp(UndoOp::SelectEvent,event, (event.tick()>=MusEGlobal::song->lpos() && event.endTick()<=MusEGlobal::song->rpos()), event.selected())); } - MusEGlobal::song->update(SC_SELECTION); + MusEGlobal::song->applyOperationGroup(operations); } -void select_not_in_loop(const std::set<Part*>& parts) +void select_not_in_loop(const set<const Part*>& parts) { select_none(parts); - for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) - for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++) + Undo operations; + operations.combobreaker=true; + + for (set<const Part*>::iterator part=parts.begin(); part!=parts.end(); part++) + for (ciEvent ev_it=(*part)->events().begin(); ev_it!=(*part)->events().end(); ev_it++) { - Event& event=ev_it->second; - event.setSelected(!(event.tick()>=MusEGlobal::song->lpos() && event.endTick()<=MusEGlobal::song->rpos())); + const Event& event=ev_it->second; + operations.push_back(UndoOp(UndoOp::SelectEvent,event, !(event.tick()>=MusEGlobal::song->lpos() && event.endTick()<=MusEGlobal::song->rpos()), event.selected())); } - MusEGlobal::song->update(SC_SELECTION); + MusEGlobal::song->applyOperationGroup(operations); } @@ -1299,10 +1313,9 @@ void shrink_parts(int raster) for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++) if (part->second->selected()) { - EventList* events=part->second->events(); unsigned len=0; - for (iEvent ev=events->begin(); ev!=events->end(); ev++) + for (ciEvent ev=part->second->events().begin(); ev!=part->second->events().end(); ev++) if (ev->second.endTick() > len) len=ev->second.endTick(); @@ -1310,46 +1323,36 @@ void shrink_parts(int raster) if (len<min_len) len=min_len; if (len < part->second->lenTick()) - { - MidiPart* new_part = new MidiPart(*(MidiPart*)part->second); - new_part->setLenTick(len); - operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false)); - } + operations.push_back(UndoOp(UndoOp::ModifyPartLength, part->second, part->second->lenTick(), len, true, false)); } MusEGlobal::song->applyOperationGroup(operations); } -void schedule_resize_all_same_len_clone_parts(Part* part, unsigned new_len, Undo& operations) +void schedule_resize_all_same_len_clone_parts(const Part* part, unsigned new_len, Undo& operations) { QSet<const Part*> already_done; for (Undo::iterator op_it=operations.begin(); op_it!=operations.end();op_it++) - if (op_it->type==UndoOp::ModifyPart || op_it->type==UndoOp::DeletePart) - already_done.insert(op_it->nPart); + if (op_it->type==UndoOp::DeletePart) + already_done.insert(op_it->part); unsigned old_len= part->type() == Pos::FRAMES ? part->lenFrame() : part->lenTick(); if (old_len!=new_len) { - Part* part_it=part; + const Part* part_it=part; do { if (part->type() == Pos::FRAMES) { if (part_it->lenFrame()==old_len && !already_done.contains(part_it)) - { - WavePart* new_part = new WavePart(*(WavePart*)part_it); - new_part->setLenFrame(new_len); - operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, new_part, true, false)); - } + operations.push_back(UndoOp(UndoOp::ModifyPartLengthFrames, part_it, part_it->lenFrame(), new_len, true, false)); // FIXME FINDMICH frames suck :( } else if (part_it->lenTick()==old_len && !already_done.contains(part_it)) { - MidiPart* new_part = new MidiPart(*(MidiPart*)part_it); - new_part->setLenTick(new_len); - operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, new_part, true, false)); + operations.push_back(UndoOp(UndoOp::ModifyPartLength, part_it, part_it->lenTick(), new_len, true, false)); } part_it=part_it->nextClone(); @@ -1370,10 +1373,9 @@ void expand_parts(int raster) for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++) if (part->second->selected()) { - EventList* events=part->second->events(); unsigned len=part->second->lenTick(); - for (iEvent ev=events->begin(); ev!=events->end(); ev++) + for (ciEvent ev=part->second->events().begin(); ev!=part->second->events().end(); ev++) if (ev->second.endTick() > len) len=ev->second.endTick(); @@ -1381,11 +1383,7 @@ void expand_parts(int raster) if (len<min_len) len=min_len; if (len > part->second->lenTick()) - { - MidiPart* new_part = new MidiPart(*(MidiPart*)part->second); - new_part->setLenTick(len); - operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false)); - } + operations.push_back(UndoOp(UndoOp::ModifyPartLength, part->second, part->second->lenTick(), len, true, false)); } MusEGlobal::song->applyOperationGroup(operations); @@ -1394,7 +1392,7 @@ void expand_parts(int raster) void clean_parts() { Undo operations; - set<Part*> already_processed; + set<const Part*> already_processed; TrackList* tracks = MusEGlobal::song->tracks(); for (iTrack track = tracks->begin(); track != tracks->end(); track++) @@ -1406,7 +1404,7 @@ void clean_parts() // multiple clones) unsigned len=0; - Part* part_it=part->second; + const Part* part_it=part->second; do { if (part_it->lenTick() > len) @@ -1419,8 +1417,7 @@ void clean_parts() // erase all events exceeding the longest clone of this part // (i.e., erase all hidden events) or shorten them - EventList* el = part->second->events(); - for (iEvent ev=el->begin(); ev!=el->end(); ev++) + for (ciEvent ev=part->second->events().begin(); ev!=part->second->events().end(); ev++) if (ev->second.tick() >= len) operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, part->second, true, true)); else if (ev->second.endTick() > len) @@ -1435,33 +1432,67 @@ void clean_parts() MusEGlobal::song->applyOperationGroup(operations); } + +bool merge_with_next_part(const Part* oPart) +{ + const Track* track = oPart->track(); + + if(track->type() != Track::WAVE && !track->isMidiTrack()) + return false; + + const PartList* pl = track->cparts(); + const Part* nextPart = 0; + + for (ciPart ip = pl->begin(); ip != pl->end(); ++ip) + { + if (ip->second == oPart) + { + ++ip; + if (ip == pl->end()) + return false; + nextPart = ip->second; + break; + } + } + + if (nextPart) + { + set<const Part*> parts; + parts.insert(oPart); + parts.insert(nextPart); + return merge_parts(parts); + } + else + return false; +} + bool merge_selected_parts() { - set<Part*> temp = get_all_selected_parts(); + set<const Part*> temp = get_all_selected_parts(); return merge_parts(temp); } -bool merge_parts(const set<Part*>& parts) +bool merge_parts(const set<const Part*>& parts) { - set<Track*> tracks; - for (set<Part*>::iterator it=parts.begin(); it!=parts.end(); it++) + set<const Track*> tracks; + for (set<const Part*>::iterator it=parts.begin(); it!=parts.end(); it++) tracks.insert( (*it)->track() ); Undo operations; // process tracks separately - for (set<Track*>::iterator t_it=tracks.begin(); t_it!=tracks.end(); t_it++) + for (set<const Track*>::iterator t_it=tracks.begin(); t_it!=tracks.end(); t_it++) { - Track* track=*t_it; + const Track* track=*t_it; unsigned begin=INT_MAX, end=0; - Part* first_part=NULL; + const Part* first_part=NULL; // find begin of the first and end of the last part - for (set<Part*>::iterator it=parts.begin(); it!=parts.end(); it++) + for (set<const Part*>::iterator it=parts.begin(); it!=parts.end(); it++) if ((*it)->track()==track) { - Part* p=*it; + const Part* p=*it; if (p->tick() < begin) { begin=p->tick(); @@ -1479,30 +1510,25 @@ bool merge_parts(const set<Part*>& parts) } // create and prepare the new part - Part* new_part = track->newPart(first_part); + Part* new_part = first_part->duplicateEmpty(); new_part->setTick(begin); new_part->setLenTick(end-begin); - EventList* new_el = new_part->events(); - new_el->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it - // so we must decrement it first :/ - new_el->clear(); - // copy all events from the source parts into the new part - for (set<Part*>::iterator p_it=parts.begin(); p_it!=parts.end(); p_it++) + for (set<const Part*>::iterator p_it=parts.begin(); p_it!=parts.end(); p_it++) if ((*p_it)->track()==track) { - EventList* old_el= (*p_it)->events(); - for (iEvent ev_it=old_el->begin(); ev_it!=old_el->end(); ev_it++) + const EventList& old_el= (*p_it)->events(); + for (ciEvent ev_it=old_el.begin(); ev_it!=old_el.end(); ev_it++) { - Event new_event=ev_it->second; + Event new_event=ev_it->second.clone(); new_event.setTick( new_event.tick() + (*p_it)->tick() - new_part->tick() ); - new_el->add(new_event); + new_part->nonconst_events().add(new_event); } } // delete all the source parts - for (set<Part*>::iterator it=parts.begin(); it!=parts.end(); it++) + for (set<const Part*>::iterator it=parts.begin(); it!=parts.end(); it++) if ((*it)->track()==track) operations.push_back( UndoOp(UndoOp::DeletePart, *it) ); // and add the new one @@ -1512,4 +1538,49 @@ bool merge_parts(const set<Part*>& parts) return MusEGlobal::song->applyOperationGroup(operations); } +bool split_part(const Part* part, int tick) +{ + int l1 = tick - part->tick(); + int l2 = part->lenTick() - l1; + if (l1 <= 0 || l2 <= 0) + return false; + Part* p1; + Part* p2; + part->splitPart(tick, p1, p2); + + MusEGlobal::song->informAboutNewParts(part, p1); + MusEGlobal::song->informAboutNewParts(part, p2); + + Undo operations; + operations.push_back(UndoOp(UndoOp::DeletePart, part)); + operations.push_back(UndoOp(UndoOp::AddPart, p1)); + operations.push_back(UndoOp(UndoOp::AddPart, p2)); + return MusEGlobal::song->applyOperationGroup(operations); +} + +bool delete_selected_parts() +{ + Undo operations; + bool partSelected = false; + + TrackList* tl = MusEGlobal::song->tracks(); + + for (iTrack it = tl->begin(); it != tl->end(); ++it) + { + PartList* pl = (*it)->parts(); + for (iPart ip = pl->begin(); ip != pl->end(); ++ip) + { + if (ip->second->selected()) + { + operations.push_back(UndoOp(UndoOp::DeletePart,ip->second)); + partSelected = true; + } + } + } + + MusEGlobal::song->applyOperationGroup(operations); + + return partSelected; +} + } // namespace MusECore |