Skip to content

Commit 2a5eb1d

Browse files
committed
feat: add ClipView
1 parent 0fb845c commit 2a5eb1d

File tree

2 files changed

+132
-20
lines changed

2 files changed

+132
-20
lines changed

lib/Clip.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Properties } from './Properties';
22
import { AbletonLive } from '.';
33
import { Note, SerializedNote } from './Note';
4-
4+
import { ClipView } from './ClipView';
55

66
// TODO Missing properties
77
// > groove
@@ -11,7 +11,6 @@ import { Note, SerializedNote } from './Note';
1111
// > warp_markers (bang)
1212
// > playing_status (bang)
1313

14-
1514
export const enum WarpMode {
1615
Beats = 0,
1716
Tones = 1,
@@ -216,6 +215,26 @@ export interface ClipGetProperties {
216215
warping: boolean;
217216
}
218217

218+
/**
219+
* @interface ClipChildrenProperties
220+
*/
221+
export interface ClipChildrenProperties {
222+
/**
223+
* Includes mixer device.
224+
*/
225+
clipView: null;
226+
}
227+
228+
/**
229+
* @interface ClipTransformedProperties
230+
*/
231+
export interface ClipTransformedProperties {
232+
/**
233+
* Includes mixer device.
234+
*/
235+
clipView: ClipView;
236+
}
237+
219238
/**
220239
* @interface ClipSetProperties
221240
*/
@@ -454,7 +473,7 @@ export interface RawClip {
454473
/**
455474
* @private
456475
*/
457-
export const RawClipKeys = [ 'name', 'is_audio_clip', 'length' ];
476+
export const RawClipKeys = ['name', 'is_audio_clip', 'length'];
458477

459478
type NotesResponse = {
460479
notes: SerializedNote[];
@@ -464,17 +483,23 @@ type NotesResponse = {
464483
* This class represents a clip in Live. It can be either an audio clip or a MIDI clip in the Arrangement or Session View, depending on the track / slot it lives in.
465484
*
466485
* @class Clip
467-
* @extends {Properties<ClipGetProperties, unknown, unknown, ClipSetProperties, ClipObservableProperties>}
486+
* @extends {Properties<ClipGetProperties, ClipChildrenProperties, ClipTransformedProperties, ClipSetProperties, ClipObservableProperties>}
468487
*/
469-
export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSetProperties, ClipObservableProperties> {
488+
export class Clip extends Properties<
489+
ClipGetProperties,
490+
ClipChildrenProperties,
491+
ClipTransformedProperties,
492+
ClipSetProperties,
493+
ClipObservableProperties
494+
> {
470495
static sessionPath = 'live_set tracks $1 clip_slots $2 clip';
471496
static arrangementPath = 'live_set tracks $1 arrangement_clips $2 clip';
472497

473498
static getSessionPath(trackNumber: number, clipSlotNumber: number): string {
474499
return Clip.sessionPath.replace('$1', `${trackNumber}`).replace('$2', `${clipSlotNumber}`);
475500
}
476501

477-
static getArrangementPath(trackNumber: number, clipSlotNumber: number, ): string {
502+
static getArrangementPath(trackNumber: number, clipSlotNumber: number): string {
478503
return Clip.arrangementPath.replace('$1', `${trackNumber}`).replace('$2', `${clipSlotNumber}`);
479504
}
480505

@@ -498,7 +523,9 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
498523
this._type = raw.is_audio_clip ? ClipType.Midi : ClipType.Audio;
499524
this._length = raw.length;
500525

501-
this.childrenTransformers = {};
526+
this.childrenTransformers = {
527+
clipView: () => new ClipView(this.ableton),
528+
};
502529
}
503530

504531
// =========================================================================
@@ -566,7 +593,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
566593
* @return {void}
567594
*/
568595
public async addNewNotes(notes: Note[]): Promise<void> {
569-
return this.call('add_new_notes', [ this.prepareNotes(notes) ]);
596+
return this.call('add_new_notes', [this.prepareNotes(notes)]);
570597
}
571598

572599
/**
@@ -578,7 +605,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
578605
* @return {void}
579606
*/
580607
public async applyNoteModifications(notes: Note[]): Promise<void> {
581-
return this.call('apply_note_modifications', [ this.prepareNotes(notes) ]);
608+
return this.call('apply_note_modifications', [this.prepareNotes(notes)]);
582609
}
583610

584611
/**
@@ -599,7 +626,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
599626
* @return {void}
600627
*/
601628
public async clearEnvelope(deviceParameterId: number): Promise<void> {
602-
return this.call('clear_envelope', [ deviceParameterId ]);
629+
return this.call('clear_envelope', [deviceParameterId]);
603630
}
604631

605632
/**
@@ -660,7 +687,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
660687
pitch = -1,
661688
transpositionAmount = 0
662689
): Promise<void> {
663-
return this.call('duplicate_region', [ regionStart, regionLength, destinationTime, pitch, transpositionAmount ]);
690+
return this.call('duplicate_region', [regionStart, regionLength, destinationTime, pitch, transpositionAmount]);
664691
}
665692

666693
/**
@@ -685,7 +712,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
685712
* @return {void}
686713
*/
687714
public async getNotes(startTime = 0, timeRange = 256, startPitch = 0, pitchRange = 127): Promise<Note[]> {
688-
return this.call('get_notes_extended', [ startPitch, pitchRange, startTime.toFixed(3), timeRange.toFixed(3) ]).then(
715+
return this.call('get_notes_extended', [startPitch, pitchRange, startTime.toFixed(3), timeRange.toFixed(3)]).then(
689716
this.parseNotes.bind(this)
690717
);
691718
}
@@ -699,7 +726,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
699726
* @return {void}
700727
*/
701728
public async getNotesById(ids: number[]): Promise<Note[]> {
702-
return this.call('get_notes_by_id', [ ...ids ]).then(this.parseNotes.bind(this));
729+
return this.call('get_notes_by_id', [...ids]).then(this.parseNotes.bind(this));
703730
}
704731

705732
/**
@@ -723,7 +750,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
723750
* @return {void}
724751
*/
725752
public async movePlayingPos(beats: number): Promise<void> {
726-
return this.call('move_playing_pos', [ beats ]);
753+
return this.call('move_playing_pos', [beats]);
727754
}
728755

729756
/**
@@ -736,7 +763,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
736763
* @return {void}
737764
*/
738765
public async quantize(quantizationGrid: number, amount: number): Promise<void> {
739-
return this.call('quantize', [ quantizationGrid, amount ]);
766+
return this.call('quantize', [quantizationGrid, amount]);
740767
}
741768

742769
/**
@@ -750,7 +777,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
750777
* @return {void}
751778
*/
752779
public async quantizePitch(pitch: number, quantizationGrid: number, amount: number): Promise<void> {
753-
return this.call('quantize_pitch', [ pitch, quantizationGrid, amount ]);
780+
return this.call('quantize_pitch', [pitch, quantizationGrid, amount]);
754781
}
755782

756783
/**
@@ -765,7 +792,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
765792
* @return {void}
766793
*/
767794
public async removeNotes(startTime = 0, timeRange = 256, startPitch = 0, pitchRange = 127): Promise<void> {
768-
return this.call('remove_notes_extended', [ startPitch, pitchRange, startTime.toFixed(4), timeRange.toFixed(4) ]);
795+
return this.call('remove_notes_extended', [startPitch, pitchRange, startTime.toFixed(4), timeRange.toFixed(4)]);
769796
}
770797

771798
/**
@@ -777,7 +804,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
777804
* @return {void}
778805
*/
779806
public async removeNotesById(ids: number[]): Promise<void> {
780-
return this.call('remove_notes_by_id', [ ...ids ]);
807+
return this.call('remove_notes_by_id', [...ids]);
781808
}
782809

783810
/**
@@ -791,7 +818,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
791818
* @return {void}
792819
*/
793820
public async scrub(beatTime: number): Promise<void> {
794-
return this.call('scrub', [ beatTime ]);
821+
return this.call('scrub', [beatTime]);
795822
}
796823

797824
/**
@@ -814,7 +841,7 @@ export class Clip extends Properties<ClipGetProperties, unknown, unknown, ClipSe
814841
* @return {void}
815842
*/
816843
public async setFireButtonState(state: boolean): Promise<void> {
817-
return this.call('set_fire_button_state', [ state ]);
844+
return this.call('set_fire_button_state', [state]);
818845
}
819846

820847
/**

lib/ClipView.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { Properties } from './Properties';
2+
import { AbletonLive } from '.';
3+
4+
/**
5+
* @interface ClipViewGetProperties
6+
*/
7+
export interface ClipViewGetProperties {
8+
/**
9+
* Get whether the clip is displayed with a triplet grid.
10+
*/
11+
grid_is_triplet: boolean;
12+
}
13+
14+
/**
15+
* @interface ClipSetProperties
16+
*/
17+
export interface ClipViewSetProperties {
18+
/**
19+
* Set whether the clip is displayed with a triplet grid.
20+
*/
21+
grid_is_triplet: boolean;
22+
}
23+
24+
/**
25+
* Representing the view aspects of a Clip.
26+
*
27+
* @class ClipView
28+
* @extends {Properties<ClipViewGetProperties, unknown, unknown, ClipViewSetProperties, ClipViewObservableProperties>}
29+
*/
30+
export class ClipView extends Properties<ClipViewGetProperties, unknown, unknown, ClipViewSetProperties, unknown> {
31+
static path = 'live_set tracks $1 clip_slots $2 clip view';
32+
33+
static getPath(trackNumber: number, clipSlotNumber: number): string {
34+
return ClipView.path.replace('$1', `${trackNumber}`).replace('$2', `${clipSlotNumber}`);
35+
}
36+
37+
/**
38+
* Creates an instance of ClipView.
39+
* @private
40+
* @param {AbletonLive} ableton
41+
* @memberof Clip
42+
*/
43+
constructor(ableton: AbletonLive) {
44+
super(ableton, 'clip view', ClipView.path);
45+
}
46+
47+
// =========================================================================
48+
// * Custom API
49+
// =========================================================================
50+
51+
// =========================================================================
52+
// * Official API
53+
// =========================================================================
54+
55+
/**
56+
* Hide the Envelopes box
57+
*
58+
* @memberof ClipView
59+
* @return {void}
60+
*/
61+
public async hideEnvelope(): Promise<void> {
62+
return this.call('hide_envelope');
63+
}
64+
65+
/**
66+
* Show the Envelopes box
67+
*
68+
* @memberof ClipView
69+
* @param {number} deviceParam Select the specified device parameter in the Envelopes box.
70+
* @return {void}
71+
*/
72+
public async showEnvelope(): Promise<void> {
73+
return this.call('show_envelope');
74+
}
75+
76+
/**
77+
* If the clip is visible in Live's Detail View, this function will make the current loop visible there.
78+
*
79+
* @memberof ClipView
80+
* @return {void}
81+
*/
82+
public async showLoop(): Promise<void> {
83+
return this.call('show_loop');
84+
}
85+
}

0 commit comments

Comments
 (0)