1
//=========================================================
4
// $Id: functions.cpp,v 1.20.2.19 2011/05/05 20:10 flo93 Exp $
5
// (C) Copyright 2011 Florian Jung (flo93@sourceforge.net)
7
// This program is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU General Public License
9
// as published by the Free Software Foundation; version 2 of
10
// the License, or (at your option) any later version.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
// You should have received a copy of the GNU General Public License
18
// along with this program; if not, write to the Free Software
19
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
//=========================================================
23
#include "functions.h"
32
#include "widgets/function_dialogs/velocity.h"
33
#include "widgets/function_dialogs/quantize.h"
34
#include "widgets/function_dialogs/crescendo.h"
35
#include "widgets/function_dialogs/gatetime.h"
36
#include "widgets/function_dialogs/remove.h"
37
#include "widgets/function_dialogs/transpose.h"
38
#include "widgets/function_dialogs/setlen.h"
39
#include "widgets/function_dialogs/move.h"
40
#include "widgets/function_dialogs/deloverlaps.h"
41
#include "widgets/function_dialogs/legato.h"
42
#include "widgets/pasteeventsdialog.h"
49
#include <sys/types.h>
56
#include <QMessageBox>
63
using MusEGlobal::config;
67
// unit private functions:
69
bool read_eventlist_and_part(Xml& xml, EventList* el, int* part_id);
71
// -----------------------
75
set<Part*> partlist_to_set(PartList* pl)
79
for (PartList::iterator it=pl->begin(); it!=pl->end(); it++)
80
result.insert(it->second);
85
set<Part*> part_to_set(Part* p)
92
set<Part*> get_all_parts()
96
TrackList* tracks=MusEGlobal::song->tracks();
97
for (TrackList::const_iterator t_it=tracks->begin(); t_it!=tracks->end(); t_it++)
99
const PartList* parts=(*t_it)->cparts();
100
for (ciPart p_it=parts->begin(); p_it!=parts->end(); p_it++)
101
result.insert(p_it->second);
107
set<Part*> get_all_selected_parts()
111
TrackList* tracks=MusEGlobal::song->tracks();
112
for (TrackList::const_iterator t_it=tracks->begin(); t_it!=tracks->end(); t_it++)
114
const PartList* parts=(*t_it)->cparts();
115
for (ciPart p_it=parts->begin(); p_it!=parts->end(); p_it++)
116
if (p_it->second->selected())
117
result.insert(p_it->second);
123
bool is_relevant(const Event& event, const Part* part, int range)
127
if (event.type()!=Note) return false;
132
case 1: return event.selected();
133
case 2: tick=event.tick()+part->tick(); return (tick >= MusEGlobal::song->lpos()) && (tick < MusEGlobal::song->rpos());
134
case 3: return is_relevant(event,part,1) && is_relevant(event,part,2);
135
default: cout << "ERROR: ILLEGAL FUNCTION CALL in is_relevant: range is illegal: "<<range<<endl;
141
map<Event*, Part*> get_events(const set<Part*>& parts, int range)
143
map<Event*, Part*> events;
145
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
146
for (iEvent event=(*part)->events()->begin(); event!=(*part)->events()->end(); event++)
147
if (is_relevant(event->second, *part, range))
148
events.insert(pair<Event*, Part*>(&event->second, *part));
156
bool modify_notelen(const set<Part*>& parts)
158
if (!MusEGui::gatetime_dialog->exec())
161
modify_notelen(parts,MusEGui::gatetime_dialog->range,MusEGui::gatetime_dialog->rateVal,MusEGui::gatetime_dialog->offsetVal);
166
bool modify_velocity(const set<Part*>& parts)
168
if (!MusEGui::velocity_dialog->exec())
171
modify_velocity(parts,MusEGui::velocity_dialog->range,MusEGui::velocity_dialog->rateVal,MusEGui::velocity_dialog->offsetVal);
176
bool quantize_notes(const set<Part*>& parts)
178
if (!MusEGui::quantize_dialog->exec())
180
// (1<<MusEGui::quantize_dialog->raster_power2)
181
int raster = MusEGui::rasterVals[MusEGui::quantize_dialog->raster_index];
182
quantize_notes(parts, MusEGui::quantize_dialog->range, (MusEGlobal::config.division*4)/raster,
183
MusEGui::quantize_dialog->quant_len, MusEGui::quantize_dialog->strength, MusEGui::quantize_dialog->swing,
184
MusEGui::quantize_dialog->threshold);
189
bool erase_notes(const set<Part*>& parts)
191
if (!MusEGui::erase_dialog->exec())
194
erase_notes(parts,MusEGui::erase_dialog->range, MusEGui::erase_dialog->velo_threshold, MusEGui::erase_dialog->velo_thres_used,
195
MusEGui::erase_dialog->len_threshold, MusEGui::erase_dialog->len_thres_used );
200
bool delete_overlaps(const set<Part*>& parts)
202
if (!MusEGui::del_overlaps_dialog->exec())
205
delete_overlaps(parts,MusEGui::erase_dialog->range);
210
bool set_notelen(const set<Part*>& parts)
212
if (!MusEGui::set_notelen_dialog->exec())
215
set_notelen(parts,MusEGui::set_notelen_dialog->range,MusEGui::set_notelen_dialog->len);
220
bool move_notes(const set<Part*>& parts)
222
if (!MusEGui::move_notes_dialog->exec())
225
move_notes(parts,MusEGui::move_notes_dialog->range,MusEGui::move_notes_dialog->amount);
230
bool transpose_notes(const set<Part*>& parts)
232
if (!MusEGui::transpose_dialog->exec())
235
transpose_notes(parts,MusEGui::transpose_dialog->range,MusEGui::transpose_dialog->amount);
240
bool crescendo(const set<Part*>& parts)
242
if (MusEGlobal::song->rpos() <= MusEGlobal::song->lpos())
244
QMessageBox::warning(NULL, QObject::tr("Error"), QObject::tr("Please first select the range for crescendo with the loop markers."));
248
if (!MusEGui::crescendo_dialog->exec())
251
crescendo(parts,MusEGui::crescendo_dialog->range,MusEGui::crescendo_dialog->start_val,MusEGui::crescendo_dialog->end_val,MusEGui::crescendo_dialog->absolute);
256
bool legato(const set<Part*>& parts)
258
if (!MusEGui::legato_dialog->exec())
261
legato(parts,MusEGui::legato_dialog->range, MusEGui::legato_dialog->min_len, !MusEGui::legato_dialog->allow_shortening);
268
bool modify_notelen()
270
if (!MusEGui::gatetime_dialog->exec())
274
if (MusEGui::gatetime_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
275
parts=get_all_selected_parts();
277
parts=get_all_parts();
279
modify_notelen(parts,MusEGui::gatetime_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::gatetime_dialog->rateVal,MusEGui::gatetime_dialog->offsetVal);
284
bool modify_velocity()
286
if (!MusEGui::velocity_dialog->exec())
290
if (MusEGui::velocity_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
291
parts=get_all_selected_parts();
293
parts=get_all_parts();
295
modify_velocity(parts,MusEGui::velocity_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS,MusEGui::velocity_dialog->rateVal,MusEGui::velocity_dialog->offsetVal);
300
bool quantize_notes()
302
if (!MusEGui::quantize_dialog->exec())
306
if (MusEGui::quantize_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
307
parts=get_all_selected_parts();
309
parts=get_all_parts();
311
int raster = MusEGui::rasterVals[MusEGui::quantize_dialog->raster_index];
312
quantize_notes(parts, MusEGui::quantize_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, (config.division*4)/raster,
313
MusEGui::quantize_dialog->quant_len, MusEGui::quantize_dialog->strength, MusEGui::quantize_dialog->swing,
314
MusEGui::quantize_dialog->threshold);
321
if (!MusEGui::erase_dialog->exec())
325
if (MusEGui::erase_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
326
parts=get_all_selected_parts();
328
parts=get_all_parts();
330
erase_notes(parts,MusEGui::erase_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::erase_dialog->velo_threshold, MusEGui::erase_dialog->velo_thres_used,
331
MusEGui::erase_dialog->len_threshold, MusEGui::erase_dialog->len_thres_used );
336
bool delete_overlaps()
338
if (!MusEGui::del_overlaps_dialog->exec())
342
if (MusEGui::del_overlaps_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
343
parts=get_all_selected_parts();
345
parts=get_all_parts();
347
delete_overlaps(parts,MusEGui::erase_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS);
354
if (!MusEGui::set_notelen_dialog->exec())
358
if (MusEGui::set_notelen_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
359
parts=get_all_selected_parts();
361
parts=get_all_parts();
363
set_notelen(parts,MusEGui::set_notelen_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::set_notelen_dialog->len);
370
if (!MusEGui::move_notes_dialog->exec())
374
if (MusEGui::move_notes_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
375
parts=get_all_selected_parts();
377
parts=get_all_parts();
379
move_notes(parts,MusEGui::move_notes_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::move_notes_dialog->amount);
384
bool transpose_notes()
386
if (!MusEGui::transpose_dialog->exec())
390
if (MusEGui::transpose_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
391
parts=get_all_selected_parts();
393
parts=get_all_parts();
395
transpose_notes(parts,MusEGui::transpose_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::transpose_dialog->amount);
402
if (MusEGlobal::song->rpos() <= MusEGlobal::song->lpos())
404
QMessageBox::warning(NULL, QObject::tr("Error"), QObject::tr("Please first select the range for crescendo with the loop markers."));
408
if (!MusEGui::crescendo_dialog->exec())
412
if (MusEGui::crescendo_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
413
parts=get_all_selected_parts();
415
parts=get_all_parts();
417
crescendo(parts,MusEGui::crescendo_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::crescendo_dialog->start_val,MusEGui::crescendo_dialog->end_val,MusEGui::crescendo_dialog->absolute);
424
if (!MusEGui::legato_dialog->exec())
428
if (MusEGui::legato_dialog->range & FUNCTION_RANGE_ONLY_SELECTED)
429
parts=get_all_selected_parts();
431
parts=get_all_parts();
433
legato(parts,MusEGui::legato_dialog->range & FUNCTION_RANGE_ONLY_BETWEEN_MARKERS, MusEGui::legato_dialog->min_len, !MusEGui::legato_dialog->allow_shortening);
443
bool modify_velocity(const set<Part*>& parts, int range, int rate, int offset)
445
map<Event*, Part*> events = get_events(parts, range);
448
if ( (!events.empty()) && ((rate!=100) || (offset!=0)) )
450
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
452
Event& event=*(it->first);
453
Part* part=it->second;
455
int velo = event.velo();
457
velo = (velo * rate) / 100;
465
if (event.velo() != velo)
467
Event newEvent = event.clone();
468
newEvent.setVelo(velo);
469
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
473
return MusEGlobal::song->applyOperationGroup(operations);
479
bool modify_off_velocity(const set<Part*>& parts, int range, int rate, int offset)
481
map<Event*, Part*> events = get_events(parts, range);
484
if ( (!events.empty()) && ((rate!=100) || (offset!=0)) )
486
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
488
Event& event=*(it->first);
489
Part* part=it->second;
491
int velo = event.veloOff();
493
velo = (velo * rate) / 100;
501
if (event.veloOff() != velo)
503
Event newEvent = event.clone();
504
newEvent.setVeloOff(velo);
505
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
509
return MusEGlobal::song->applyOperationGroup(operations);
515
bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset)
517
map<Event*, Part*> events = get_events(parts, range);
519
map<Part*, int> partlen;
521
if ( (!events.empty()) && ((rate!=100) || (offset!=0)) )
523
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
525
Event& event=*(it->first);
526
Part* part=it->second;
528
unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned
530
len = (len * rate) / 100;
536
if ((event.tick()+len > part->lenTick()) && (!part->hasHiddenEvents()))
537
partlen[part]=event.tick()+len; // schedule auto-expanding
539
if (event.lenTick() != len)
541
Event newEvent = event.clone();
542
newEvent.setLenTick(len);
543
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
547
for (map<Part*, int>::iterator it=partlen.begin(); it!=partlen.end(); it++)
548
schedule_resize_all_same_len_clone_parts(it->first, it->second, operations);
550
return MusEGlobal::song->applyOperationGroup(operations);
556
bool set_notelen(const set<Part*>& parts, int range, int len)
558
return modify_notelen(parts, range, 0, len);
561
unsigned quantize_tick(unsigned tick, unsigned raster, int swing)
563
//find out the nearest tick and the distance to it:
564
//this is so complicated because this function supports
565
//swing: if swing is 50, the resulting rhythm is not
566
//"daa daa daa daa" but "daaaa da daaaa da"...
567
int tick_dest1 = AL::sigmap.raster1(tick, raster*2); //round down
568
int tick_dest2 = tick_dest1 + raster + raster*swing/100;
569
int tick_dest3 = tick_dest1 + raster*2;
571
int tick_diff1 = tick_dest1 - tick;
572
int tick_diff2 = tick_dest2 - tick;
573
int tick_diff3 = tick_dest3 - tick;
575
if ((abs(tick_diff1) <= abs(tick_diff2)) && (abs(tick_diff1) <= abs(tick_diff3))) //tick_dest1 is the nearest tick
577
else if ((abs(tick_diff2) <= abs(tick_diff1)) && (abs(tick_diff2) <= abs(tick_diff3))) //tick_dest2 is the nearest tick
583
bool quantize_notes(const set<Part*>& parts, int range, int raster, bool quant_len, int strength, int swing, int threshold)
585
map<Event*, Part*> events = get_events(parts, range);
590
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
592
Event& event=*(it->first);
593
Part* part=it->second;
595
unsigned begin_tick = event.tick() + part->tick();
596
int begin_diff = quantize_tick(begin_tick, raster, swing) - begin_tick;
598
if (abs(begin_diff) > threshold)
599
begin_tick = begin_tick + begin_diff*strength/100;
602
unsigned len=event.lenTick();
604
unsigned end_tick = begin_tick + len;
605
int len_diff = quantize_tick(end_tick, raster, swing) - end_tick;
607
if ((abs(len_diff) > threshold) && quant_len)
608
len = len + len_diff*strength/100;
614
if ( (event.lenTick() != len) || (event.tick() + part->tick() != begin_tick) )
616
Event newEvent = event.clone();
617
newEvent.setTick(begin_tick - part->tick());
618
newEvent.setLenTick(len);
619
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
623
return MusEGlobal::song->applyOperationGroup(operations);
629
bool erase_notes(const set<Part*>& parts, int range, int velo_threshold, bool velo_thres_used, int len_threshold, bool len_thres_used)
631
map<Event*, Part*> events = get_events(parts, range);
636
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
638
Event& event=*(it->first);
639
Part* part=it->second;
641
if ( (!velo_thres_used && !len_thres_used) ||
642
(velo_thres_used && event.velo() < velo_threshold) ||
643
(len_thres_used && int(event.lenTick()) < len_threshold) )
644
operations.push_back(UndoOp(UndoOp::DeleteEvent, event, part, false, false));
647
return MusEGlobal::song->applyOperationGroup(operations);
653
bool transpose_notes(const set<Part*>& parts, int range, signed int halftonesteps)
655
map<Event*, Part*> events = get_events(parts, range);
658
if ( (!events.empty()) && (halftonesteps!=0) )
660
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
662
Event& event=*(it->first);
663
Part* part=it->second;
665
Event newEvent = event.clone();
666
int pitch = event.pitch()+halftonesteps;
667
if (pitch > 127) pitch=127;
668
if (pitch < 0) pitch=0;
669
newEvent.setPitch(pitch);
670
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
673
return MusEGlobal::song->applyOperationGroup(operations);
679
bool crescendo(const set<Part*>& parts, int range, int start_val, int end_val, bool absolute)
681
map<Event*, Part*> events = get_events(parts, range);
684
int from=MusEGlobal::song->lpos();
685
int to=MusEGlobal::song->rpos();
687
if ( (!events.empty()) && (to>from) )
689
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
691
Event& event=*(it->first);
692
Part* part=it->second;
694
unsigned tick = event.tick() + part->tick();
695
float curr_val= (float)start_val + (float)(end_val-start_val) * (tick-from) / (to-from);
697
Event newEvent = event.clone();
698
int velo = event.velo();
703
velo=curr_val*velo/100;
705
if (velo > 127) velo=127;
706
if (velo <= 0) velo=1;
707
newEvent.setVelo(velo);
708
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
711
return MusEGlobal::song->applyOperationGroup(operations);
717
bool move_notes(const set<Part*>& parts, int range, signed int ticks)
719
map<Event*, Part*> events = get_events(parts, range);
721
map<Part*, int> partlen;
723
if ( (!events.empty()) && (ticks!=0) )
725
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
727
Event& event=*(it->first);
728
Part* part=it->second;
731
Event newEvent = event.clone();
732
if ((signed)event.tick()+ticks < 0) //don't allow moving before the part's begin
735
newEvent.setTick(event.tick()+ticks);
737
if (newEvent.endTick() > part->lenTick()) //if exceeding the part's end:
739
if (part->hasHiddenEvents()) // auto-expanding is forbidden, clip
741
if (part->lenTick() > newEvent.tick())
742
newEvent.setLenTick(part->lenTick() - newEvent.tick());
744
del=true; //if the new length would be <= 0, erase the note
747
partlen[part]=newEvent.endTick(); // schedule auto-expanding
751
operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
753
operations.push_back(UndoOp(UndoOp::DeleteEvent, event, part, false, false));
756
for (map<Part*, int>::iterator it=partlen.begin(); it!=partlen.end(); it++)
757
schedule_resize_all_same_len_clone_parts(it->first, it->second, operations);
759
return MusEGlobal::song->applyOperationGroup(operations);
766
bool delete_overlaps(const set<Part*>& parts, int range)
768
map<Event*, Part*> events = get_events(parts, range);
771
set<Event*> deleted_events;
775
for (map<Event*, Part*>::iterator it1=events.begin(); it1!=events.end(); it1++)
777
Event& event1=*(it1->first);
778
Part* part1=it1->second;
780
// we may NOT optimize by letting it2 start at (it1 +1); this optimisation
781
// is only allowed when events was sorted by time. it is, however, sorted
782
// randomly by pointer.
783
for (map<Event*, Part*>::iterator it2=events.begin(); it2!=events.end(); it2++)
785
Event& event2=*(it2->first);
786
Part* part2=it2->second;
788
if ( (part1->events()==part2->events()) && // part1 and part2 are the same or are duplicates
789
(&event1 != &event2) && // and event1 and event2 aren't the same
790
(deleted_events.find(&event2) == deleted_events.end()) ) //and event2 hasn't been deleted before
792
if ( (event1.pitch() == event2.pitch()) &&
793
(event1.tick() <= event2.tick()) &&
794
(event1.endTick() > event2.tick()) ) //they overlap
796
int new_len = event2.tick() - event1.tick();
800
operations.push_back(UndoOp(UndoOp::DeleteEvent, event1, part1, false, false));
801
deleted_events.insert(&event1);
805
Event new_event1 = event1.clone();
806
new_event1.setLenTick(new_len);
808
operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event1, event1, part1, false, false));
815
return MusEGlobal::song->applyOperationGroup(operations);
821
bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten)
823
map<Event*, Part*> events = get_events(parts, range);
826
if (min_len<=0) min_len=1;
830
for (map<Event*, Part*>::iterator it1=events.begin(); it1!=events.end(); it1++)
832
Event& event1=*(it1->first);
833
Part* part1=it1->second;
836
// we may NOT optimize by letting it2 start at (it1 +1); this optimisation
837
// is only allowed when events was sorted by time. it is, however, sorted
838
// randomly by pointer.
839
for (map<Event*, Part*>::iterator it2=events.begin(); it2!=events.end(); it2++)
841
Event& event2=*(it2->first);
842
Part* part2=it2->second;
844
bool relevant = (event2.tick() >= event1.tick() + min_len);
846
relevant = relevant && (event2.tick() >= event1.endTick());
848
if ( (part1->events()==part2->events()) && // part1 and part2 are the same or are duplicates
849
relevant && // they're not too near (respect min_len and dont_shorten)
850
(event2.tick()-event1.tick() < len ) ) // that's the nearest relevant following note
851
len=event2.tick()-event1.tick();
854
if (len==MAXINT) len=event1.lenTick(); // if no following note was found, keep the length
856
if (event1.lenTick() != len)
858
Event new_event1 = event1.clone();
859
new_event1.setLenTick(len);
861
operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event1, event1, part1, false, false));
865
return MusEGlobal::song->applyOperationGroup(operations);
873
void copy_notes(const set<Part*>& parts, int range)
875
QMimeData* drag = selected_events_to_mime(parts,range);
878
QApplication::clipboard()->setMimeData(drag, QClipboard::Clipboard);
881
unsigned get_groupedevents_len(const QString& pt)
885
QByteArray pt_= pt.toLatin1();
886
Xml xml(pt_.constData());
889
Xml::Token token = xml.parse();
890
const QString& tag = xml.s1();
898
if (tag == "eventlist")
902
if (read_eventlist_and_part(xml, &el, &part_id))
904
unsigned len = el.rbegin()->first;
905
if (len > maxlen) maxlen=len;
909
xml.unknown("get_clipboard_len");
919
return maxlen; // see also the return statement above!
922
unsigned get_clipboard_len()
924
QString tmp="x-muse-groupedeventlists"; // QClipboard::text() expects a QString&, not a QString :(
925
QString s = QApplication::clipboard()->text(tmp, QClipboard::Clipboard); // TODO CHECK Tim.
927
return get_groupedevents_len(s);
930
bool paste_notes(Part* paste_into_part)
932
unsigned temp_begin = AL::sigmap.raster1(MusEGlobal::song->cpos(),0);
933
unsigned temp_end = AL::sigmap.raster2(temp_begin + get_clipboard_len(), 0);
934
MusEGui::paste_events_dialog->raster = temp_end - temp_begin;
935
MusEGui::paste_events_dialog->into_single_part_allowed = (paste_into_part!=NULL);
937
if (!MusEGui::paste_events_dialog->exec())
940
paste_notes(MusEGui::paste_events_dialog->max_distance, MusEGui::paste_events_dialog->always_new_part,
941
MusEGui::paste_events_dialog->never_new_part, MusEGui::paste_events_dialog->into_single_part ? paste_into_part : NULL,
942
MusEGui::paste_events_dialog->number, MusEGui::paste_events_dialog->raster);
947
void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part, int amount, int raster)
949
QString tmp="x-muse-groupedeventlists"; // QClipboard::text() expects a QString&, not a QString :(
950
QString s = QApplication::clipboard()->text(tmp, QClipboard::Clipboard); // TODO CHECK Tim.
951
paste_at(s, MusEGlobal::song->cpos(), max_distance, always_new_part, never_new_part, paste_into_part, amount, raster);
955
// if nothing is selected/relevant, this function returns NULL
956
QMimeData* selected_events_to_mime(const set<Part*>& parts, int range)
958
unsigned start_tick = MAXINT; //will be the tick of the first event or MAXINT if no events are there
960
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
961
for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++)
962
if (is_relevant(ev->second, *part, range))
963
if (ev->second.tick() < start_tick)
964
start_tick=ev->second.tick();
966
if (start_tick == MAXINT)
969
//---------------------------------------------------
970
// write events as XML into tmp file
971
//---------------------------------------------------
973
FILE* tmp = tmpfile();
976
fprintf(stderr, "EventCanvas::getTextDrag() fopen failed: %s\n", strerror(errno));
983
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
985
xml.tag(level++, "eventlist part_id=\"%d\"", (*part)->sn());
986
for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++)
987
if (is_relevant(ev->second, *part, range))
988
ev->second.write(level, xml, -start_tick);
989
xml.etag(--level, "eventlist");
992
//---------------------------------------------------
993
// read tmp file into drag Object
994
//---------------------------------------------------
998
if (fstat(fileno(tmp), &f_stat) == -1)
1000
fprintf(stderr, "copy_notes() fstat failed:<%s>\n",
1005
int n = f_stat.st_size;
1006
char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE,
1007
MAP_PRIVATE, fileno(tmp), 0);
1010
QByteArray data(fbuf);
1011
QMimeData* md = new QMimeData();
1013
md->setData("text/x-muse-groupedeventlists", data);
1021
bool read_eventlist_and_part(Xml& xml, EventList* el, int* part_id) // true on success, false on failure
1027
Xml::Token token = xml.parse();
1028
const QString& tag = xml.s1();
1036
if (tag == "part_id")
1037
*part_id = xml.s2().toInt();
1039
printf("unknown attribute '%s' in read_eventlist_and_part(), ignoring it...\n", tag.toAscii().data());
1050
xml.unknown("read_eventlist_and_part");
1054
if (tag == "eventlist")
1063
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)
1066
map<Part*, unsigned> expand_map;
1067
map<Part*, set<Part*> > new_part_map;
1069
QByteArray pt_= pt.toLatin1();
1070
Xml xml(pt_.constData());
1073
Xml::Token token = xml.parse();
1074
const QString& tag = xml.s1();
1079
goto out_of_paste_at_for;
1082
if (tag == "eventlist")
1087
if (read_eventlist_and_part(xml, &el, &part_id))
1091
Part* old_dest_part;
1093
if (paste_into_part == NULL)
1094
dest_part = partFromSerialNumber(part_id);
1096
dest_part=paste_into_part;
1098
if (dest_part == NULL)
1100
printf("ERROR: destination part wasn't found. ignoring these events\n");
1104
dest_track=dest_part->track();
1105
old_dest_part=dest_part;
1106
unsigned first_paste_tick = el.begin()->first + pos;
1107
bool create_new_part = ( (dest_part->tick() > first_paste_tick) || // dest_part begins too late
1108
( ( (dest_part->endTick() + max_distance < first_paste_tick) || // dest_part is too far away
1109
always_new_part ) && !never_new_part ) ); // respect function arguments
1111
for (int i=0;i<amount;i++)
1113
unsigned curr_pos = pos + i*raster;
1114
first_paste_tick = el.begin()->first + curr_pos;
1116
if (create_new_part)
1118
dest_part = dest_track->newPart();
1119
dest_part->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it
1120
// so we must decrement it first :/
1121
dest_part->setTick(AL::sigmap.raster1(first_paste_tick, config.division));
1123
new_part_map[old_dest_part].insert(dest_part);
1124
operations.push_back(UndoOp(UndoOp::AddPart, dest_part));
1127
for (iEvent i = el.begin(); i != el.end(); ++i)
1129
Event e = i->second.clone();
1130
int tick = e.tick() + curr_pos - dest_part->tick();
1133
printf("ERROR: trying to add event before current part! ignoring this event\n");
1138
e.setSelected(true);
1140
if (e.endTick() > dest_part->lenTick()) // event exceeds part?
1142
if (dest_part->hasHiddenEvents()) // auto-expanding is forbidden?
1144
if (e.tick() < dest_part->lenTick())
1145
e.setLenTick(dest_part->lenTick() - e.tick()); // clip
1147
e.setLenTick(0); // don't insert that note at all
1151
if (e.endTick() > expand_map[dest_part])
1152
expand_map[dest_part]=e.endTick();
1156
if (e.lenTick() != 0) operations.push_back(UndoOp(UndoOp::AddEvent,e, dest_part, false, false));
1163
printf("ERROR: reading eventlist from clipboard failed. ignoring this one...\n");
1167
xml.unknown("paste_at");
1177
out_of_paste_at_for:
1179
for (map<Part*, unsigned>::iterator it = expand_map.begin(); it!=expand_map.end(); it++)
1180
if (it->second != it->first->lenTick())
1181
schedule_resize_all_same_len_clone_parts(it->first, it->second, operations);
1183
MusEGlobal::song->informAboutNewParts(new_part_map); // must be called before apply. otherwise
1184
// pointer changes (by resize) screw it up
1185
MusEGlobal::song->applyOperationGroup(operations);
1186
MusEGlobal::song->update(SC_SELECTION);
1189
void select_all(const std::set<Part*>& parts)
1191
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
1192
for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++)
1194
Event& event=ev_it->second;
1195
event.setSelected(true);
1197
MusEGlobal::song->update(SC_SELECTION);
1200
void select_none(const std::set<Part*>& parts)
1202
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
1203
for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++)
1205
Event& event=ev_it->second;
1206
event.setSelected(false);
1208
MusEGlobal::song->update(SC_SELECTION);
1211
void select_invert(const std::set<Part*>& parts)
1213
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
1214
for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++)
1216
Event& event=ev_it->second;
1217
event.setSelected(!event.selected());
1219
MusEGlobal::song->update(SC_SELECTION);
1222
void select_in_loop(const std::set<Part*>& parts)
1225
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
1226
for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++)
1228
Event& event=ev_it->second;
1229
event.setSelected((event.tick()>=MusEGlobal::song->lpos() && event.endTick()<=MusEGlobal::song->rpos()));
1231
MusEGlobal::song->update(SC_SELECTION);
1234
void select_not_in_loop(const std::set<Part*>& parts)
1237
for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++)
1238
for (iEvent ev_it=(*part)->events()->begin(); ev_it!=(*part)->events()->end(); ev_it++)
1240
Event& event=ev_it->second;
1241
event.setSelected(!(event.tick()>=MusEGlobal::song->lpos() && event.endTick()<=MusEGlobal::song->rpos()));
1243
MusEGlobal::song->update(SC_SELECTION);
1247
void shrink_parts(int raster)
1252
if (raster<0) raster=MusEGlobal::config.division;
1253
if (raster>=0) min_len=raster; else min_len=MusEGlobal::config.division;
1255
TrackList* tracks = MusEGlobal::song->tracks();
1256
for (iTrack track = tracks->begin(); track != tracks->end(); track++)
1257
for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
1258
if (part->second->selected())
1260
EventList* events=part->second->events();
1263
for (iEvent ev=events->begin(); ev!=events->end(); ev++)
1264
if (ev->second.endTick() > len)
1265
len=ev->second.endTick();
1267
if (raster) len=ceil((float)len/raster)*raster;
1268
if (len<min_len) len=min_len;
1270
if (len < part->second->lenTick())
1272
MidiPart* new_part = new MidiPart(*(MidiPart*)part->second);
1273
new_part->setLenTick(len);
1274
operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false));
1278
MusEGlobal::song->applyOperationGroup(operations);
1282
void schedule_resize_all_same_len_clone_parts(Part* part, unsigned new_len, Undo& operations)
1284
QSet<const Part*> already_done;
1286
for (Undo::iterator op_it=operations.begin(); op_it!=operations.end();op_it++)
1287
if (op_it->type==UndoOp::ModifyPart || op_it->type==UndoOp::DeletePart)
1288
already_done.insert(op_it->nPart);
1290
unsigned old_len=part->lenTick();
1291
if (old_len!=new_len)
1296
if (part_it->lenTick()==old_len && !already_done.contains(part_it))
1298
MidiPart* new_part = new MidiPart(*(MidiPart*)part_it);
1299
new_part->setLenTick(new_len);
1300
operations.push_back(UndoOp(UndoOp::ModifyPart, part_it, new_part, true, false));
1303
part_it=part_it->nextClone();
1304
} while (part_it!=part);
1308
void expand_parts(int raster)
1313
if (raster<0) raster=MusEGlobal::config.division;
1314
if (raster>=0) min_len=raster; else min_len=MusEGlobal::config.division;
1316
TrackList* tracks = MusEGlobal::song->tracks();
1317
for (iTrack track = tracks->begin(); track != tracks->end(); track++)
1318
for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
1319
if (part->second->selected())
1321
EventList* events=part->second->events();
1322
unsigned len=part->second->lenTick();
1324
for (iEvent ev=events->begin(); ev!=events->end(); ev++)
1325
if (ev->second.endTick() > len)
1326
len=ev->second.endTick();
1328
if (raster) len=ceil((float)len/raster)*raster;
1329
if (len<min_len) len=min_len;
1331
if (len > part->second->lenTick())
1333
MidiPart* new_part = new MidiPart(*(MidiPart*)part->second);
1334
new_part->setLenTick(len);
1335
operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false));
1339
MusEGlobal::song->applyOperationGroup(operations);
1345
set<Part*> already_processed;
1347
TrackList* tracks = MusEGlobal::song->tracks();
1348
for (iTrack track = tracks->begin(); track != tracks->end(); track++)
1349
for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
1350
if ((part->second->selected()) && (already_processed.find(part->second)==already_processed.end()))
1352
// find out the length of the longest clone of this part;
1353
// avoid processing eventlist multiple times (because of
1357
Part* part_it=part->second;
1360
if (part_it->lenTick() > len)
1361
len=part_it->lenTick();
1363
already_processed.insert(part_it);
1364
part_it=part_it->nextClone();
1365
} while ((part_it!=part->second) && (part_it!=NULL));
1368
// erase all events exceeding the longest clone of this part
1369
// (i.e., erase all hidden events) or shorten them
1370
EventList* el = part->second->events();
1371
for (iEvent ev=el->begin(); ev!=el->end(); ev++)
1372
if (ev->second.tick() >= len)
1373
operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, part->second, true, true));
1374
else if (ev->second.endTick() > len)
1376
Event new_event = ev->second.clone();
1377
new_event.setLenTick(len - ev->second.tick());
1379
operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event, ev->second, part->second, true, true));
1383
MusEGlobal::song->applyOperationGroup(operations);
1386
} // namespace MusECore