~ubuntu-branches/ubuntu/oneiric/tuxguitar/oneiric

« back to all changes in this revision

Viewing changes to TuxGuitar/src/org/herac/tuxguitar/song/managers/TGMeasureManager.java

  • Committer: Bazaar Package Importer
  • Author(s): Philippe Coval
  • Date: 2008-06-19 00:30:30 UTC
  • mto: (5.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20080619003030-h719szrhsngou7c6
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.herac.tuxguitar.song.managers;
 
2
 
 
3
import java.util.ArrayList;
 
4
import java.util.Iterator;
 
5
import java.util.List;
 
6
 
 
7
import org.herac.tuxguitar.song.factory.TGFactory;
 
8
import org.herac.tuxguitar.song.models.TGBeat;
 
9
import org.herac.tuxguitar.song.models.TGChord;
 
10
import org.herac.tuxguitar.song.models.TGDuration;
 
11
import org.herac.tuxguitar.song.models.TGMeasure;
 
12
import org.herac.tuxguitar.song.models.TGNote;
 
13
import org.herac.tuxguitar.song.models.TGString;
 
14
import org.herac.tuxguitar.song.models.TGText;
 
15
import org.herac.tuxguitar.song.models.effects.TGEffectBend;
 
16
import org.herac.tuxguitar.song.models.effects.TGEffectGrace;
 
17
import org.herac.tuxguitar.song.models.effects.TGEffectHarmonic;
 
18
import org.herac.tuxguitar.song.models.effects.TGEffectTremoloBar;
 
19
import org.herac.tuxguitar.song.models.effects.TGEffectTremoloPicking;
 
20
import org.herac.tuxguitar.song.models.effects.TGEffectTrill;
 
21
 
 
22
public class TGMeasureManager {
 
23
        private TGSongManager songManager;
 
24
        
 
25
        public TGMeasureManager(TGSongManager songManager){
 
26
                this.songManager = songManager;
 
27
        }
 
28
        
 
29
        public TGSongManager getSongManager(){
 
30
                return this.songManager;
 
31
        }
 
32
        
 
33
        public void orderBeats(TGMeasure measure){
 
34
                for(int i = 0;i < measure.countBeats();i++){
 
35
                        TGBeat minBeat = null;
 
36
                        for(int j = i;j < measure.countBeats();j++){
 
37
                                TGBeat beat = measure.getBeat(j);
 
38
                                if(minBeat == null || beat.getStart() < minBeat.getStart()){
 
39
                                        minBeat = beat;
 
40
                                }
 
41
                        }
 
42
                        measure.moveBeat(i, minBeat);
 
43
                }
 
44
        }       
 
45
        
 
46
        /**
 
47
         * Agrega un beat al compas
 
48
         */
 
49
        public void addBeat(TGMeasure measure,TGBeat beat){
 
50
                //Verifico si entra en el compas
 
51
                if(validateDuration(measure,beat,false,false)){
 
52
                        
 
53
                        //Agrego el beat
 
54
                        measure.addBeat(beat);
 
55
                }
 
56
        }
 
57
        
 
58
        public void removeBeat(TGBeat beat){
 
59
                beat.getMeasure().removeBeat(beat);
 
60
        }
 
61
        
 
62
        public void removeBeat(TGMeasure measure,long start,boolean moveNextComponents){
 
63
                TGBeat beat = getBeat(measure, start);
 
64
                if(beat != null){
 
65
                        removeBeat(beat, moveNextComponents);
 
66
                }
 
67
        }
 
68
        
 
69
        /**
 
70
         * Elimina un silencio del compas.
 
71
         * si se asigna moveNextComponents = true. los componentes que le siguen
 
72
         * se moveran para completar el espacio vacio que dejo el silencio
 
73
         */
 
74
        public void removeBeat(TGBeat beat,boolean moveNextBeats){
 
75
                TGMeasure measure = beat.getMeasure();
 
76
                
 
77
                removeBeat(beat);
 
78
                if(moveNextBeats){
 
79
                        long start = beat.getStart();
 
80
                        long length = beat.getDuration().getTime();
 
81
                        TGBeat next = getNextBeat(measure.getBeats(),beat);
 
82
                        if(next != null){
 
83
                                length = next.getStart() - start;
 
84
                        }
 
85
                        moveBeats(beat.getMeasure(),start + length,-length,  beat.getDuration());
 
86
                }
 
87
        }
 
88
        
 
89
        public void removeBeatsBeforeEnd(TGMeasure measure,long fromStart){
 
90
                List beats = getBeatsBeforeEnd( measure.getBeats() , fromStart);
 
91
                Iterator it = beats.iterator();
 
92
                while(it.hasNext()){
 
93
                        TGBeat beat = (TGBeat) it.next();
 
94
                        removeBeat(beat);
 
95
                }
 
96
        }
 
97
        
 
98
        public void addNote(TGMeasure measure,long start, TGNote note, TGDuration duration){
 
99
                TGBeat beat = getBeat(measure, start);
 
100
                if(beat != null){
 
101
                        addNote(beat, note, duration);
 
102
                }
 
103
        }
 
104
        
 
105
        public void addNote(TGBeat beat, TGNote note, TGDuration duration){
 
106
                addNote(beat, note, duration, beat.getStart());
 
107
        }
 
108
        
 
109
        public void addNote(TGBeat beat, TGNote note, TGDuration duration, long start){
 
110
                //Verifico si entra en el compas
 
111
                if(validateDuration(beat.getMeasure(),beat, duration,true,true)){
 
112
                        //Borro lo que haya en la misma posicion
 
113
                        removeNote(beat.getMeasure(),beat.getStart(),note.getString());
 
114
                        
 
115
                        duration.copy(beat.getDuration());
 
116
                        
 
117
                        //trato de agregar un silencio similar al lado
 
118
                        tryChangeSilenceAfter(beat.getMeasure(),beat);
 
119
                        
 
120
                        // Despues de cambiar la duracion, verifico si hay un beat mejor para agregar la nota.
 
121
                        TGBeat realBeat = beat;
 
122
                        if(realBeat.getStart() != start){
 
123
                                TGBeat beatIn = getBeatIn(realBeat.getMeasure(), start);
 
124
                                if( beatIn != null ) {
 
125
                                        realBeat = beatIn;
 
126
                                }
 
127
                        }
 
128
                        realBeat.addNote(note);
 
129
                }
 
130
        }
 
131
        
 
132
        public void removeNote(TGNote note){
 
133
                note.getBeat().removeNote(note);
 
134
        }
 
135
        
 
136
        /**
 
137
         * Elimina los Componentes que empiecen en Start y esten en la misma cuerda
 
138
         * Si hay un Silencio lo borra sin importar la cuerda
 
139
         */
 
140
        public void removeNote(TGMeasure measure,long start,int string){
 
141
                TGBeat beat = getBeat(measure, start);
 
142
                if(beat != null){
 
143
                        for( int i = 0; i < beat.countNotes(); i ++){
 
144
                                TGNote note = beat.getNote(i);
 
145
                                if(note.getString() == string){
 
146
                                        removeNote(note);
 
147
                                        
 
148
                                        //si era el unico componente agrego un silencio
 
149
                                        if(beat.isRestBeat()){
 
150
                                                //Borro un posible acorde
 
151
                                                removeChord(measure, beat.getStart());
 
152
                                        }
 
153
                                        return;
 
154
                                }
 
155
                        }
 
156
                }
 
157
        }
 
158
        
 
159
        public void removeNotesAfterString(TGMeasure measure,int string){
 
160
                List notesToRemove = new ArrayList();
 
161
                
 
162
                Iterator beats = measure.getBeats().iterator();
 
163
                while(beats.hasNext()){
 
164
                        TGBeat beat = (TGBeat)beats.next();
 
165
                        Iterator notes = beat.getNotes().iterator();
 
166
                        while(notes.hasNext()){
 
167
                                TGNote note = (TGNote)notes.next();
 
168
                                if(note.getString() > string){
 
169
                                        notesToRemove.add(note);
 
170
                                }
 
171
                        }
 
172
                }
 
173
                Iterator it = notesToRemove.iterator();
 
174
                while(it.hasNext()){
 
175
                        TGNote note = (TGNote)it.next();
 
176
                        removeNote(note);
 
177
                }
 
178
        }
 
179
        
 
180
        /**
 
181
         * Retorna Todas las Notas en la posicion Start
 
182
         */
 
183
        public List getNotes(TGMeasure measure,long start){
 
184
                List notes = new ArrayList();
 
185
                
 
186
                TGBeat beat = getBeat(measure, start);
 
187
                if(beat != null){
 
188
                        Iterator it = beat.getNotes().iterator();
 
189
                        while(it.hasNext()){
 
190
                                TGNote note = (TGNote)it.next();
 
191
                                notes.add(note);
 
192
                        }
 
193
                }
 
194
                return notes;
 
195
        }
 
196
        
 
197
        /**
 
198
         * Retorna la Nota en la posicion y cuerda
 
199
         */
 
200
        public TGNote getNote(TGMeasure measure,long start,int string) {
 
201
                TGBeat beat = getBeat(measure, start);
 
202
                if(beat != null){
 
203
                        return getNote(beat, string);
 
204
                }
 
205
                return null;
 
206
        }
 
207
        
 
208
        /**
 
209
         * Retorna la Nota en la cuerda
 
210
         */
 
211
        public TGNote getNote(TGBeat beat,int string) {
 
212
                Iterator it = beat.getNotes().iterator();
 
213
                while(it.hasNext()){
 
214
                        TGNote note = (TGNote)it.next();
 
215
                        if (note.getString() == string) {
 
216
                                return note;
 
217
                        }
 
218
                }
 
219
                return null;
 
220
        }
 
221
        
 
222
        public TGNote getPreviousNote(TGMeasure measure,long start, int string) {
 
223
                TGBeat beat = getBeat(measure, start);
 
224
                if( beat != null ){
 
225
                        TGBeat previous = getPreviousBeat(measure.getBeats(),beat);
 
226
                        while(previous != null){
 
227
                                for (int i = 0; i < previous.countNotes(); i++) {
 
228
                                        TGNote current = previous.getNote(i);
 
229
                                        if (current.getString() == string) {
 
230
                                                return current;
 
231
                                        }
 
232
                                }
 
233
                                previous = getPreviousBeat(measure.getBeats(),previous);
 
234
                        }
 
235
                }
 
236
                return null;
 
237
        }
 
238
        
 
239
        public TGNote getNextNote(TGMeasure measure,long start, int string) {
 
240
                TGBeat beat = getBeat(measure, start);
 
241
                if( beat != null ){
 
242
                        TGBeat next = getNextBeat(measure.getBeats(),beat);
 
243
                        while(next != null){
 
244
                                for (int i = 0; i < next.countNotes(); i++) {
 
245
                                        TGNote current = next.getNote(i);
 
246
                                        if (current.getString() == string) {
 
247
                                                return current;
 
248
                                        }
 
249
                                }
 
250
                                next = getNextBeat(measure.getBeats(),next);
 
251
                        }
 
252
                }
 
253
                return null;
 
254
        }
 
255
        
 
256
        /**
 
257
         * Retorna las Nota en la posicion y cuerda
 
258
         */
 
259
        public TGBeat getBeat(TGMeasure measure,long start) {
 
260
                Iterator it = measure.getBeats().iterator();
 
261
                while(it.hasNext()){
 
262
                        TGBeat beat = (TGBeat)it.next();
 
263
                        if (beat.getStart() == start) {
 
264
                                return beat;
 
265
                        }
 
266
                }
 
267
                return null;
 
268
        }
 
269
        
 
270
        /**
 
271
         * Retorna las Nota en la posicion y cuerda
 
272
         */
 
273
        public TGBeat getBeatIn(TGMeasure measure,long start) {
 
274
                Iterator it = measure.getBeats().iterator();
 
275
                while(it.hasNext()){
 
276
                        TGBeat beat = (TGBeat)it.next();
 
277
                        if (beat.getStart() <= start && (beat.getStart() + beat.getDuration().getTime() > start)) {
 
278
                                return beat;
 
279
                        }
 
280
                }
 
281
                return null;
 
282
        }
 
283
        
 
284
        /**
 
285
         * Retorna el Siguiente Componente
 
286
         */
 
287
        public TGBeat getNextBeat(List beats,TGBeat beat) {
 
288
                TGBeat next = null;
 
289
                for (int i = 0; i < beats.size(); i++) {
 
290
                        TGBeat current = (TGBeat) beats.get(i);
 
291
                        if (current.getStart() > beat.getStart()) {
 
292
                                if (next == null) {
 
293
                                        next = current;
 
294
                                } else if (current.getStart() < next.getStart()) {
 
295
                                        next = current;
 
296
                                } else if (current.getStart() == next.getStart() && current.getDuration().getTime() <= next.getDuration().getTime()) {
 
297
                                        next = current;
 
298
                                }
 
299
                        }
 
300
                }
 
301
                return next;
 
302
        }
 
303
        
 
304
        /**
 
305
         * Retorna el Componente Anterior
 
306
         */
 
307
        public TGBeat getPreviousBeat(List beats,TGBeat beat) {
 
308
                TGBeat previous = null;
 
309
                for (int i = 0; i < beats.size(); i++) {
 
310
                        TGBeat current = (TGBeat) beats.get(i);
 
311
                        if (current.getStart() < beat.getStart()) {
 
312
                                if (previous == null) {
 
313
                                        previous = current;
 
314
                                } else if (current.getStart() > previous.getStart()) {
 
315
                                        previous = current;
 
316
                                } else if (current.getStart() == previous.getStart() && current.getDuration().getTime() <= previous.getDuration().getTime()) {
 
317
                                        previous = current;
 
318
                                }
 
319
                        }
 
320
                }
 
321
                return previous;
 
322
        }
 
323
        
 
324
        /**
 
325
         * Retorna el Primer Componente
 
326
         */
 
327
        public TGBeat getFirstBeat(List components) {
 
328
                TGBeat first = null;
 
329
                for (int i = 0; i < components.size(); i++) {
 
330
                        TGBeat component = (TGBeat) components.get(i);
 
331
                        if (first == null || component.getStart() < first.getStart()) {
 
332
                                first = component;
 
333
                        }
 
334
                }
 
335
                return first;
 
336
        }
 
337
        
 
338
        /**
 
339
         * Retorna el Ultimo Componente
 
340
         */
 
341
        public TGBeat getLastBeat(List components) {
 
342
                TGBeat last = null;
 
343
                for (int i = 0; i < components.size(); i++) {
 
344
                        TGBeat component = (TGBeat) components.get(i);
 
345
                        if (last == null || last.getStart() < component.getStart()) {
 
346
                                last = component;
 
347
                        }
 
348
                }
 
349
                return last;
 
350
        }
 
351
        
 
352
        /**
 
353
         * Retorna el Siguiente Componente
 
354
         */
 
355
        public TGBeat getNextRestBeat(List beats,TGBeat component) {
 
356
                TGBeat next = getNextBeat(beats, component);
 
357
                while(next != null && !next.isRestBeat()){
 
358
                        next = getNextBeat(beats, next);
 
359
                }
 
360
                return next;
 
361
        }
 
362
        
 
363
        
 
364
        /**
 
365
         * Retorna Todos los desde Start hasta el final del compas
 
366
         */
 
367
        public List getBeatsBeforeEnd(List beats,long fromStart) {
 
368
                List list = new ArrayList();
 
369
                Iterator it = beats.iterator();
 
370
                while(it.hasNext()){
 
371
                        TGBeat current = (TGBeat)it.next();
 
372
                        if (current.getStart() >= fromStart) {
 
373
                                list.add(current);
 
374
                        }
 
375
                }
 
376
                return list;
 
377
        }
 
378
        
 
379
        public void moveAllBeats(TGMeasure measure,long theMove){
 
380
                moveBeats(measure.getBeats(),theMove);
 
381
        }
 
382
        
 
383
        public boolean moveBeats(TGMeasure measure,long start,long theMove, TGDuration fillDuration){
 
384
                if( theMove == 0 ){
 
385
                        return false;
 
386
                }
 
387
                boolean success = true;
 
388
                long measureStart = measure.getStart();
 
389
                long measureEnd =  (measureStart + measure.getLength());
 
390
                
 
391
                // Muevo los componentes
 
392
                List beatsToMove = getBeatsBeforeEnd(measure.getBeats(),start);
 
393
                moveBeats(beatsToMove,theMove);
 
394
                
 
395
                if(success){
 
396
                        List beatsToRemove = new ArrayList();
 
397
                        List beats = new ArrayList(measure.getBeats());
 
398
                        
 
399
                        // Verifica los silencios a eliminar al principio del compas
 
400
                        TGBeat first = getFirstBeat( beats );
 
401
                        while(first != null && first.isRestBeat() && !first.isTextBeat() && first.getStart() < measureStart){
 
402
                                beats.remove(first);
 
403
                                beatsToRemove.add(first);
 
404
                                first = getNextBeat( beats,first);
 
405
                        }
 
406
                        
 
407
                        // Verifica los silencios a eliminar al final del compas
 
408
                        TGBeat last = getLastBeat(beats);
 
409
                        while(last != null && last.isRestBeat() && !last.isTextBeat()  && (last.getStart() + last.getDuration().getTime() ) > measureEnd  ){
 
410
                                beats.remove(last);
 
411
                                beatsToRemove.add(last);
 
412
                                last = getPreviousBeat(beats,last);
 
413
                        }
 
414
                        
 
415
                        // Si el primer o ultimo componente, quedan fuera del compas, entonces el movimiento no es satisfactorio
 
416
                        if(first != null && last != null){
 
417
                                if(first.getStart() < measureStart || (last.getStart() + last.getDuration().getTime()) > measureEnd){
 
418
                                        success = false;
 
419
                                }
 
420
                        }
 
421
                        
 
422
                        if(success){
 
423
                                // Elimino los silencios que quedaron fuera del compas.
 
424
                                Iterator it = beatsToRemove.iterator();
 
425
                                while( it.hasNext() ){
 
426
                                        TGBeat beat = (TGBeat)it.next();
 
427
                                        removeBeat(beat);
 
428
                                }
 
429
                                
 
430
                                // Se crean silencios en los espacios vacios, si la duracion fue especificada.
 
431
                                if( fillDuration != null ){
 
432
                                        if( theMove < 0 ){
 
433
                                                last = getLastBeat(measure.getBeats());
 
434
                                                TGBeat beat = getSongManager().getFactory().newBeat();
 
435
                                                beat.setStart( (last != null ? last.getStart()  + last.getDuration().getTime() : start  )  );
 
436
                                                fillDuration.copy( beat.getDuration() );
 
437
                                                if( (beat.getStart() + beat.getDuration().getTime()) <= measureEnd ){
 
438
                                                        addBeat(measure, beat );
 
439
                                                }
 
440
                                        }
 
441
                                        else{
 
442
                                                first = getFirstBeat(getBeatsBeforeEnd(measure.getBeats(),start));
 
443
                                                TGBeat beat = getSongManager().getFactory().newBeat();
 
444
                                                beat.setStart( start );
 
445
                                                fillDuration.copy( beat.getDuration() );
 
446
                                                if( (beat.getStart() + beat.getDuration().getTime()) <= (first != null ?first.getStart() : measureEnd ) ){
 
447
                                                        addBeat(measure, beat );
 
448
                                                }
 
449
                                        }
 
450
                                }
 
451
                        }
 
452
                }
 
453
                
 
454
                // Si el movimiento no es satisfactorio, regreso todo como estaba
 
455
                if(! success ){
 
456
                        moveBeats(beatsToMove,-theMove);
 
457
                }
 
458
                
 
459
                return success;
 
460
        }
 
461
        
 
462
        /**
 
463
         * Mueve los componentes
 
464
         */
 
465
        private void moveBeats(List beats,long theMove){
 
466
                Iterator it = beats.iterator();
 
467
                while(it.hasNext()){
 
468
                        TGBeat beat = (TGBeat)it.next();
 
469
                        moveBeat(beat,theMove);
 
470
                }
 
471
        }
 
472
        
 
473
        /**
 
474
         * Mueve el componente
 
475
         */
 
476
        private void moveBeat(TGBeat beat,long theMove){
 
477
                //obtengo el start viejo
 
478
                long start = beat.getStart();
 
479
                
 
480
                //asigno el nuevo start
 
481
                beat.setStart(start + theMove);
 
482
        }
 
483
        
 
484
        public void cleanBeat(TGBeat beat){
 
485
                if( beat.getText() != null ){
 
486
                        beat.removeChord();
 
487
                }
 
488
                if( beat.getChord() != null){
 
489
                        beat.removeText();
 
490
                }
 
491
                
 
492
                this.cleanBeatNotes(beat);
 
493
        }
 
494
        
 
495
        public void cleanBeatNotes(TGBeat beat){
 
496
                while(beat.countNotes() > 0 ){
 
497
                        TGNote note = beat.getNote(0);
 
498
                        removeNote(note);
 
499
                }
 
500
        }
 
501
        
 
502
        public void cleanBeatNotes(TGMeasure measure, long start){
 
503
                TGBeat beat = getBeat(measure, start);
 
504
                if(beat != null){
 
505
                        cleanBeatNotes(beat);
 
506
                }
 
507
        }
 
508
        
 
509
        /**
 
510
         * Agrega el acorde al compas
 
511
         */
 
512
        public void addChord(TGMeasure measure,long start, TGChord chord){
 
513
                TGBeat beat = getBeat(measure, start);
 
514
                if(beat != null){
 
515
                        addChord(beat, chord);
 
516
                }
 
517
        }
 
518
        
 
519
        /**
 
520
         * Agrega el acorde al compas
 
521
         */
 
522
        public void addChord(TGBeat beat,TGChord chord){
 
523
                beat.removeChord();
 
524
                beat.setChord(chord);
 
525
        }
 
526
        
 
527
        /**
 
528
         * Retorna el acorde en la position
 
529
         */
 
530
        public TGChord getChord(TGMeasure measure,long start) {
 
531
                TGBeat beat = getBeat(measure, start);
 
532
                if(beat != null){
 
533
                        return beat.getChord();
 
534
                }
 
535
                return null;
 
536
        }
 
537
        
 
538
        /**
 
539
         * Borra el acorde en la position
 
540
         */
 
541
        public void removeChord(TGMeasure measure,long start) {
 
542
                TGBeat beat = getBeat(measure, start);
 
543
                if(beat != null){
 
544
                        beat.removeChord();
 
545
                }
 
546
        }
 
547
        
 
548
        /**
 
549
         * Agrega el texto al compas
 
550
         */
 
551
        public void addText(TGMeasure measure,long start, TGText text){
 
552
                TGBeat beat = getBeat(measure, start);
 
553
                if(beat != null){
 
554
                        addText(beat, text);
 
555
                }
 
556
        }
 
557
        
 
558
        /**
 
559
         * Agrega el texto al compas
 
560
         */
 
561
        public void addText(TGBeat beat,TGText text){
 
562
                beat.removeText();
 
563
                if(!text.isEmpty()){
 
564
                        beat.setText(text);
 
565
                }
 
566
        }
 
567
        
 
568
        /**
 
569
         * Retorna el texto en la position
 
570
         */
 
571
        public TGText getText(TGMeasure measure,long start) {
 
572
                TGBeat beat = getBeat(measure, start);
 
573
                if(beat != null){
 
574
                        return beat.getText();
 
575
                }
 
576
                return null;
 
577
        }
 
578
        
 
579
        /**
 
580
         * Borra el texto en el pulso
 
581
         */
 
582
        public void removeText(TGBeat beat){
 
583
                beat.removeText();
 
584
        }
 
585
        
 
586
        /**
 
587
         * Borra el texto en la position
 
588
         */
 
589
        public boolean removeText(TGMeasure measure,long start) {
 
590
                TGBeat beat = getBeat(measure, start);
 
591
                if(beat != null){
 
592
                        removeText(beat);
 
593
                        return true;
 
594
                }
 
595
                return false;
 
596
        }
 
597
        
 
598
        public void cleanMeasure(TGMeasure measure){
 
599
                while( measure.countBeats() > 0){
 
600
                        removeBeat( measure.getBeat(0));
 
601
                }
 
602
        }
 
603
        
 
604
        /**
 
605
         * Mueve la nota a la cuerda de arriba
 
606
         */
 
607
        public int shiftNoteUp(TGMeasure measure,long start,int string){
 
608
                return shiftNote(measure, start, string,-1);
 
609
        }
 
610
        
 
611
        /**
 
612
         * Mueve la nota a la cuerda de abajo
 
613
         */
 
614
        public int shiftNoteDown(TGMeasure measure,long start,int string){
 
615
                return shiftNote(measure, start, string,1);
 
616
        }
 
617
        
 
618
        /**
 
619
         * Mueve la nota a la siguiente cuerda
 
620
         */
 
621
        private int shiftNote(TGMeasure measure,long start,int string,int move){
 
622
                TGNote note = getNote(measure,start,string);
 
623
                if(note != null){
 
624
                        int nextStringNumber = (note.getString() + move);
 
625
                        while(getNote(measure,start,nextStringNumber) != null){
 
626
                                nextStringNumber += move;
 
627
                        }
 
628
                        if(nextStringNumber >= 1 && nextStringNumber <= measure.getTrack().stringCount()){
 
629
                                TGString currentString = measure.getTrack().getString(note.getString());
 
630
                                TGString nextString = measure.getTrack().getString(nextStringNumber);
 
631
                                int noteValue = (note.getValue() + currentString.getValue());
 
632
                                if(noteValue >= nextString.getValue() && ((nextString.getValue() + 30 > noteValue) || measure.getTrack().isPercussionTrack()) ){
 
633
                                        note.setValue(noteValue - nextString.getValue());
 
634
                                        note.setString(nextString.getNumber());
 
635
                                        return note.getString();
 
636
                                }
 
637
                        }
 
638
                }
 
639
                return 0;
 
640
        }
 
641
        
 
642
        /**
 
643
         * Mueve la nota 1 semitono arriba
 
644
         */
 
645
        public boolean moveSemitoneUp(TGMeasure measure,long start,int string){
 
646
                return moveSemitone(measure, start, string,1);
 
647
        }
 
648
        
 
649
        /**
 
650
         * Mueve la nota 1 semitono abajo
 
651
         */
 
652
        public boolean moveSemitoneDown(TGMeasure measure,long start,int string){
 
653
                return moveSemitone(measure, start, string,-1);
 
654
        }
 
655
        
 
656
        /**
 
657
         * Mueve la nota los semitonos indicados
 
658
         */
 
659
        private boolean moveSemitone(TGMeasure measure,long start,int string,int semitones){
 
660
                TGNote note = getNote(measure,start,string);
 
661
                if(note != null){
 
662
                        int newValue = (note.getValue() + semitones);
 
663
                        if(newValue >= 0 && (newValue < 30 || measure.getTrack().isPercussionTrack()) ){
 
664
                                note.setValue(newValue);
 
665
                                return true;
 
666
                        }
 
667
                }
 
668
                return false;
 
669
        }
 
670
        
 
671
        /**
 
672
         * Verifica si el componente se puede insertar en el compas.
 
673
         * si no puede, con la opcion removeSilences, verifica si el motivo por el
 
674
         * cual no entra es que lo siguen silencios. de ser asi los borra. 
 
675
         */
 
676
        public boolean validateDuration(TGMeasure measure,TGBeat beat,boolean moveNextComponents, boolean setCurrentDuration){
 
677
                return validateDuration(measure, beat, beat.getDuration(),moveNextComponents, setCurrentDuration);
 
678
        }
 
679
        
 
680
        
 
681
        public boolean validateDuration(TGMeasure measure,TGBeat beat,TGDuration duration,boolean moveNextBeats, boolean setCurrentDuration){
 
682
                int errorMargin = 10;
 
683
                this.orderBeats(measure);
 
684
                long measureStart = measure.getStart();
 
685
                long measureEnd =  (measureStart + measure.getLength());
 
686
                long beatStart = beat.getStart();
 
687
                long beatLength = duration.getTime();
 
688
                long beatEnd = (beatStart + beatLength);
 
689
                List beats = measure.getBeats();
 
690
                
 
691
                //Verifico si hay un beat en el mismo lugar, y comparo las duraciones.
 
692
                TGBeat currentBeat = getBeat(measure,beatStart);
 
693
                if(currentBeat != null && beatLength <= currentBeat.getDuration().getTime()){
 
694
                        /*if(componentAtBeat instanceof TGSilence){
 
695
                                removeSilence((TGSilence)componentAtBeat, false);
 
696
                        }*/
 
697
                        return true;
 
698
                }
 
699
                
 
700
                //Verifico si hay lugar para meter el beat
 
701
                TGBeat nextComponent = getNextBeat(beats,beat);
 
702
                if(currentBeat == null){
 
703
                        if(nextComponent == null && beatEnd < (measureEnd + errorMargin)){
 
704
                                return true;
 
705
                        }
 
706
                        if(nextComponent != null && beatEnd < (nextComponent.getStart() + errorMargin)){
 
707
                                return true;
 
708
                        }
 
709
                }
 
710
                
 
711
                // Busca si hay espacio disponible de silencios entre el componente y el el que le sigue.. si encuentra lo borra
 
712
                if(nextComponent != null && nextComponent.isRestBeat()){
 
713
                        //Verifico si lo que sigue es un silencio. y lo borro
 
714
                        long nextBeatEnd = 0;
 
715
                        List nextBeats = new ArrayList();
 
716
                        while(nextComponent != null && nextComponent.isRestBeat() && !nextComponent.isTextBeat()){
 
717
                                nextBeats.add(nextComponent);
 
718
                                nextBeatEnd = nextComponent.getStart() + nextComponent.getDuration().getTime();
 
719
                                nextComponent = getNextBeat(beats,nextComponent);
 
720
                        }
 
721
                        if(nextComponent == null){
 
722
                                nextBeatEnd = measureEnd;
 
723
                        }else if(!nextComponent.isRestBeat() || nextComponent.isTextBeat()){
 
724
                                nextBeatEnd = nextComponent.getStart();
 
725
                        }
 
726
                        if(beatEnd <= (nextBeatEnd + errorMargin)){
 
727
                                while(!nextBeats.isEmpty()){
 
728
                                        TGBeat currBeat = (TGBeat)nextBeats.get(0);
 
729
                                        nextBeats.remove(currBeat);
 
730
                                        removeBeat(currBeat, false);
 
731
                                }
 
732
                                return true;
 
733
                        }
 
734
                }
 
735
                
 
736
                // Busca si hay espacio disponible de silencios entre el componente y el final.. si encuentra mueve todo
 
737
                if(moveNextBeats){
 
738
                        nextComponent = getNextBeat(beats,beat);
 
739
                        if(nextComponent != null){
 
740
                                long requiredLength = (beatLength  - (nextComponent.getStart() - beatStart));
 
741
                                long nextSilenceLength = 0;
 
742
                                TGBeat nextRestBeat = getNextRestBeat(beats, beat);
 
743
                                while(nextRestBeat != null && !nextRestBeat.isTextBeat()){ 
 
744
                                        nextSilenceLength += nextRestBeat.getDuration().getTime();
 
745
                                        nextRestBeat = getNextRestBeat(beats, nextRestBeat);
 
746
                                }
 
747
                                
 
748
                                if(requiredLength <= (nextSilenceLength + errorMargin)){
 
749
                                        beats = getBeatsBeforeEnd(measure.getBeats(),nextComponent.getStart());
 
750
                                        while(!beats.isEmpty()){
 
751
                                                TGBeat current = (TGBeat)beats.get(0);
 
752
                                                if(current.isRestBeat() && !current.isTextBeat()){
 
753
                                                        requiredLength -= current.getDuration().getTime();
 
754
                                                        removeBeat(current, false);
 
755
                                                }else if(requiredLength > 0){
 
756
                                                        moveBeat(current,requiredLength);
 
757
                                                }
 
758
                                                beats.remove(0);
 
759
                                        }
 
760
                                        return true;
 
761
                                }
 
762
                        }
 
763
                }
 
764
                
 
765
                // como ultimo intento, asigno la duracion de cualquier componente existente en el lugar.
 
766
                if(setCurrentDuration && currentBeat != null){
 
767
                        /*if(componentAtBeat instanceof TGSilence){
 
768
                                removeSilence((TGSilence)componentAtBeat, false);
 
769
                        }*/
 
770
                        currentBeat.getDuration().copy( duration );
 
771
                        return true;
 
772
                }
 
773
                return false;
 
774
        }
 
775
        
 
776
        /**
 
777
         * Cambia la Duracion del pulso.
 
778
         */
 
779
        public void changeDuration(TGMeasure measure,TGBeat beat,TGDuration duration,boolean tryMove){
 
780
                //obtengo la duracion vieja
 
781
                TGDuration oldDuration = beat.getDuration().clone(getSongManager().getFactory());
 
782
                
 
783
                //si no entra vuelvo a dejar la vieja
 
784
                if(validateDuration(measure,beat, duration,tryMove,false)){
 
785
                        //se lo agrego a todas las notas en la posicion
 
786
                        beat.setDuration(duration.clone(getSongManager().getFactory()));
 
787
                        
 
788
                        //trato de agregar un silencio similar al lado
 
789
                        tryChangeSilenceAfter(measure,beat);
 
790
                }else{
 
791
                        oldDuration.copy( beat.getDuration() );
 
792
                }
 
793
        }
 
794
        
 
795
        public void tryChangeSilenceAfter(TGMeasure measure,TGBeat beat){
 
796
                autoCompleteSilences(measure);
 
797
                TGBeat nextBeat = getNextBeat(measure.getBeats(),beat);
 
798
                
 
799
                long beatEnd = (beat.getStart() + beat.getDuration().getTime());
 
800
                long measureEnd = (measure.getStart() + measure.getLength());
 
801
                if(nextBeat != null && nextBeat.isRestBeat() && beatEnd <= measureEnd){
 
802
                        long theMove = (getRealStart(measure,beatEnd)) - getRealStart(measure,nextBeat.getStart());
 
803
                        if((nextBeat.getStart() + theMove) < measureEnd && (nextBeat.getStart() + nextBeat.getDuration().getTime() + theMove) <= measureEnd){
 
804
                                moveBeat(nextBeat,theMove);
 
805
                                changeDuration(measure,nextBeat,beat.getDuration().clone(getSongManager().getFactory()),false);
 
806
                        }
 
807
                }
 
808
        }
 
809
        
 
810
        /**
 
811
         * Calcula si hay espacios libres. y crea nuevos silencios
 
812
         */
 
813
        public void autoCompleteSilences(TGMeasure measure){
 
814
                long start = measure.getStart();
 
815
                long end = 0;
 
816
                long diff = 0;
 
817
                List components = measure.getBeats();
 
818
                TGBeat component = getFirstBeat(components);
 
819
                
 
820
                while (component != null) {
 
821
                        end = component.getStart() + component.getDuration().getTime();
 
822
                        if(component.getStart() > start){
 
823
                                diff = component.getStart() - start;
 
824
                                if(diff > 0){
 
825
                                        createSilences(measure,start,diff);
 
826
                                }
 
827
                        }
 
828
                        start = end;
 
829
                        component = getNextBeat(components,component);
 
830
                }
 
831
                end = measure.getStart() + measure.getLength();
 
832
                diff = end - start;
 
833
                if(diff > 0){
 
834
                        createSilences(measure,start,diff);
 
835
                }
 
836
        }
 
837
        
 
838
        /**
 
839
         * Crea Silencios temporarios en base a length
 
840
         */
 
841
        private void createSilences(TGMeasure measure,long start,long length){
 
842
                long nextStart = start;
 
843
                List durations = createDurations(getSongManager().getFactory(),length);
 
844
                Iterator it = durations.iterator();
 
845
                while(it.hasNext()){
 
846
                        TGDuration duration = (TGDuration)it.next();
 
847
                        TGBeat beat = getSongManager().getFactory().newBeat();
 
848
                        beat.setStart( getRealStart(measure, nextStart) );
 
849
                        duration.copy(beat.getDuration());
 
850
                        addBeat(measure,beat);
 
851
                        nextStart += duration.getTime();
 
852
                }
 
853
        }
 
854
        
 
855
        public long getRealStart(TGMeasure measure,long currStart){
 
856
                long beatLength = TGSongManager.getDivisionLength(measure.getHeader());
 
857
                long start = currStart;
 
858
                boolean startBeat = (start % beatLength == 0);
 
859
                if(!startBeat){
 
860
                        TGDuration minDuration = getSongManager().getFactory().newDuration();
 
861
                        minDuration.setValue(TGDuration.SIXTY_FOURTH);
 
862
                        minDuration.getTupleto().setEnters(3);
 
863
                        minDuration.getTupleto().setTimes(2);
 
864
                        for(int i = 0;i < minDuration.getTime();i++){
 
865
                                start ++;
 
866
                                startBeat = (start % beatLength == 0);
 
867
                                if(startBeat){
 
868
                                   break;
 
869
                                }
 
870
                        }
 
871
                        if(!startBeat){
 
872
                                start = currStart;
 
873
                        }
 
874
                }
 
875
                return start;
 
876
        }
 
877
        
 
878
        /** 
 
879
         * Liga la nota
 
880
         */
 
881
        public void changeTieNote(TGMeasure measure,long start,int string){
 
882
                TGNote note = getNote(measure,start,string);
 
883
                if(note != null){
 
884
                        changeTieNote(note);
 
885
                }
 
886
        }
 
887
        
 
888
        /** 
 
889
         * Liga la nota
 
890
         */
 
891
        public void changeTieNote(TGNote note){
 
892
                note.setTiedNote(!note.isTiedNote());
 
893
                note.getEffect().setDeadNote(false);
 
894
        }
 
895
        
 
896
        /** 
 
897
         * Agrega un vibrato
 
898
         */
 
899
        public void changeVibratoNote(TGMeasure measure,long start,int string){
 
900
                TGNote note = getNote(measure,start,string);
 
901
                if(note != null){
 
902
                        note.getEffect().setVibrato(!note.getEffect().isVibrato());
 
903
                }
 
904
        }
 
905
        
 
906
        /** 
 
907
         * Agrega una nota muerta
 
908
         */
 
909
        public void changeDeadNote(TGNote note){
 
910
                note.getEffect().setDeadNote(!note.getEffect().isDeadNote());
 
911
                note.setTiedNote(false);
 
912
        }
 
913
        
 
914
        /** 
 
915
         * Agrega un slide
 
916
         */
 
917
        public void changeSlideNote(TGMeasure measure,long start,int string){
 
918
                TGNote note = getNote(measure,start,string);
 
919
                if(note != null){
 
920
                        note.getEffect().setSlide(!note.getEffect().isSlide());
 
921
                }
 
922
        }
 
923
        
 
924
        /** 
 
925
         * Agrega un hammer
 
926
         */
 
927
        public void changeHammerNote(TGMeasure measure,long start,int string){
 
928
                TGNote note = getNote(measure,start,string);
 
929
                if(note != null){
 
930
                        note.getEffect().setHammer(!note.getEffect().isHammer());
 
931
                }
 
932
        }
 
933
        
 
934
        /** 
 
935
         * Agrega un palm-mute
 
936
         */
 
937
        public void changePalmMute(TGMeasure measure,long start,int string){
 
938
                TGNote note = getNote(measure,start,string);
 
939
                if(note != null){
 
940
                        note.getEffect().setPalmMute(!note.getEffect().isPalmMute());
 
941
                }
 
942
        }
 
943
        
 
944
        /** 
 
945
         * Agrega un staccato
 
946
         */
 
947
        public void changeStaccato(TGMeasure measure,long start,int string){
 
948
                TGNote note = getNote(measure,start,string);
 
949
                if(note != null){
 
950
                        note.getEffect().setStaccato(!note.getEffect().isStaccato());
 
951
                }
 
952
        }
 
953
        
 
954
        /** 
 
955
         * Agrega un tapping
 
956
         */
 
957
        public void changeTapping(TGMeasure measure,long start,int string){
 
958
                TGNote note = getNote(measure,start,string);
 
959
                if(note != null){
 
960
                        note.getEffect().setTapping(!note.getEffect().isTapping());
 
961
                }
 
962
        }
 
963
        
 
964
        /** 
 
965
         * Agrega un slapping
 
966
         */
 
967
        public void changeSlapping(TGMeasure measure,long start,int string){
 
968
                TGNote note = getNote(measure,start,string);
 
969
                if(note != null){
 
970
                        note.getEffect().setSlapping(!note.getEffect().isSlapping());
 
971
                }
 
972
        }
 
973
        
 
974
        /** 
 
975
         * Agrega un popping
 
976
         */
 
977
        public void changePopping(TGMeasure measure,long start,int string){
 
978
                TGNote note = getNote(measure,start,string);
 
979
                if(note != null){
 
980
                        note.getEffect().setPopping(!note.getEffect().isPopping());
 
981
                }
 
982
        }
 
983
        
 
984
        /** 
 
985
         * Agrega un bend
 
986
         */
 
987
        public void changeBendNote(TGMeasure measure,long start,int string,TGEffectBend bend){
 
988
                TGNote note = getNote(measure,start,string);
 
989
                if(note != null){
 
990
                        note.getEffect().setBend(bend);
 
991
                }
 
992
        }
 
993
        
 
994
        /** 
 
995
         * Agrega un tremoloBar
 
996
         */
 
997
        public void changeTremoloBar(TGMeasure measure,long start,int string,TGEffectTremoloBar tremoloBar){
 
998
                TGNote note = getNote(measure,start,string);
 
999
                if(note != null){
 
1000
                        note.getEffect().setTremoloBar(tremoloBar);
 
1001
                }
 
1002
        }
 
1003
        
 
1004
        /** 
 
1005
         * Agrega un GhostNote
 
1006
         */
 
1007
        public void changeGhostNote(TGMeasure measure,long start,int string){
 
1008
                TGNote note = getNote(measure,start,string);
 
1009
                if(note != null){ 
 
1010
                        note.getEffect().setGhostNote(!note.getEffect().isGhostNote());
 
1011
                }
 
1012
        }
 
1013
        
 
1014
        /** 
 
1015
         * Agrega un AccentuatedNote
 
1016
         */
 
1017
        public void changeAccentuatedNote(TGMeasure measure,long start,int string){
 
1018
                TGNote note = getNote(measure,start,string);
 
1019
                if(note != null){ 
 
1020
                        note.getEffect().setAccentuatedNote(!note.getEffect().isAccentuatedNote());
 
1021
                }
 
1022
        }
 
1023
        
 
1024
        /** 
 
1025
         * Agrega un GhostNote
 
1026
         */
 
1027
        public void changeHeavyAccentuatedNote(TGMeasure measure,long start,int string){
 
1028
                TGNote note = getNote(measure,start,string);
 
1029
                if(note != null){
 
1030
                        note.getEffect().setHeavyAccentuatedNote(!note.getEffect().isHeavyAccentuatedNote());
 
1031
                }
 
1032
        }
 
1033
        
 
1034
        /** 
 
1035
         * Agrega un harmonic
 
1036
         */
 
1037
        public void changeHarmonicNote(TGMeasure measure,long start,int string,TGEffectHarmonic harmonic){
 
1038
                TGNote note = getNote(measure,start,string);
 
1039
                if(note != null){
 
1040
                        note.getEffect().setHarmonic(harmonic);
 
1041
                }
 
1042
        }
 
1043
        
 
1044
        /** 
 
1045
         * Agrega un grace
 
1046
         */
 
1047
        public void changeGraceNote(TGMeasure measure,long start,int string,TGEffectGrace grace){
 
1048
                TGNote note = getNote(measure,start,string);
 
1049
                if(note != null){
 
1050
                        note.getEffect().setGrace(grace);
 
1051
                }
 
1052
        }
 
1053
        
 
1054
        /** 
 
1055
         * Agrega un trill
 
1056
         */
 
1057
        public void changeTrillNote(TGMeasure measure,long start,int string,TGEffectTrill trill){
 
1058
                TGNote note = getNote(measure,start,string);
 
1059
                if(note != null){
 
1060
                        note.getEffect().setTrill(trill);
 
1061
                }
 
1062
        }
 
1063
        
 
1064
        /** 
 
1065
         * Agrega un tremolo picking
 
1066
         */
 
1067
        public void changeTremoloPicking(TGMeasure measure,long start,int string,TGEffectTremoloPicking tremoloPicking){
 
1068
                TGNote note = getNote(measure,start,string);
 
1069
                if(note != null){
 
1070
                        note.getEffect().setTremoloPicking(tremoloPicking);
 
1071
                }
 
1072
        }
 
1073
        
 
1074
        /** 
 
1075
         * Agrega un fadeIn
 
1076
         */
 
1077
        public void changeFadeIn(TGMeasure measure,long start,int string){
 
1078
                TGNote note = getNote(measure,start,string);
 
1079
                if(note != null){
 
1080
                        note.getEffect().setFadeIn(!note.getEffect().isFadeIn());
 
1081
                }
 
1082
        }
 
1083
        
 
1084
        /** 
 
1085
         * Cambia el Velocity
 
1086
         */
 
1087
        public void changeVelocity(int velocity,TGMeasure measure,long start,int string){
 
1088
                TGNote note = getNote(measure,start,string);
 
1089
                if(note != null){
 
1090
                        note.setVelocity(velocity);
 
1091
                }
 
1092
        }
 
1093
        /*
 
1094
        public static List createDurations(TGFactory factory,long time){
 
1095
                List durations = new ArrayList();
 
1096
                TGDuration tempDuration = factory.newDuration();
 
1097
                tempDuration.setValue(TGDuration.WHOLE);
 
1098
                tempDuration.setDotted(true);
 
1099
                long tempTime = time;
 
1100
                boolean finish = false;
 
1101
                while(!finish){
 
1102
                        long currentDurationTime = tempDuration.getTime();
 
1103
                        if(currentDurationTime <= tempTime){
 
1104
                                durations.add(tempDuration.clone(factory));
 
1105
                                tempTime -= currentDurationTime;
 
1106
                        }else{
 
1107
                                if(tempDuration.isDotted()){
 
1108
                                        tempDuration.setDotted(false);
 
1109
                                }else{
 
1110
                                        tempDuration.setValue(tempDuration.getValue() * 2);
 
1111
                                        tempDuration.setDotted(true);
 
1112
                                }
 
1113
                        }
 
1114
                        if(tempDuration.getValue() > TGDuration.SIXTY_FOURTH){
 
1115
                                finish = true;
 
1116
                        }
 
1117
                }
 
1118
                return durations;
 
1119
        }
 
1120
        */
 
1121
        
 
1122
        public static List createDurations(TGFactory factory,long time){
 
1123
                List durations = new ArrayList();
 
1124
                TGDuration minimum = factory.newDuration();
 
1125
                minimum.setValue(TGDuration.SIXTY_FOURTH);
 
1126
                minimum.setDotted(false);
 
1127
                minimum.setDoubleDotted(false);
 
1128
                minimum.getTupleto().setEnters(3);
 
1129
                minimum.getTupleto().setTimes(2);
 
1130
                
 
1131
                long missingTime = time;
 
1132
                while( missingTime > minimum.getTime() ){
 
1133
                        TGDuration duration = TGDuration.fromTime(factory, missingTime, minimum ,  10);
 
1134
                        durations.add( duration.clone(factory) );
 
1135
                        missingTime -= duration.getTime();
 
1136
                }
 
1137
                return durations;
 
1138
        }
 
1139
        
 
1140
}