@zync/zync-screnplay-player 0.1.251 → 0.1.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.js +1 -1
- package/dist/bundle.js.LICENSE.txt +24 -0
- package/dist/screenplay/RemotionRenderer/RemotionRenderer.js +51 -42
- package/dist/screenplay/RemotionRenderer/assets/wordObjects/LICENSE +21 -0
- package/dist/screenplay/RemotionRenderer/assets/wordObjects/emojiCatalog.json +1 -0
- package/dist/screenplay/RemotionRenderer/assets/wordObjects/images.js +24 -0
- package/dist/screenplay/RemotionRenderer/assets/wordObjects/manifest.json +67 -0
- package/dist/screenplay/RemotionRenderer/components/effects/CaptionWordObjectOverlay.js +275 -0
- package/dist/screenplay/RemotionRenderer/components/effects/Sentence.js +10 -3
- package/dist/screenplay/RemotionRenderer/components/layouts/Keyword.js +7 -9
- package/dist/screenplay/RemotionRenderer/components/layouts/KeywordStudioBackdrop.js +5 -7
- package/dist/screenplay/RemotionRenderer/components/layouts/SimpleFrameSentence.js +3 -1
- package/dist/screenplay/RemotionRenderer/components/utils/FaceCenteredVideo.js +9 -0
- package/dist/screenplay/RemotionRenderer/helpers/captionWordObjectGeometry.js +143 -0
- package/dist/screenplay/RemotionRenderer/helpers/captionWordObjects.js +143 -0
- package/dist/screenplay/RemotionRenderer/helpers/emojiCatalog.js +17 -0
- package/dist/screenplay/RemotionRenderer/helpers/headingColors.js +12 -0
- package/dist/screenplay/RemotionRenderer/helpers/loadWordObjectArtwork.js +56 -0
- package/dist/screenplay/RemotionRenderer/helpers/normalizeDisabledTranscripts.js +3 -629
- package/dist/screenplay/RemotionRenderer/main/lib/layouts/LayoutFactory.js +0 -15
- package/dist/screenplay/RemotionRenderer/main/lib/layouts/SimpleFrameLayout.js +8 -3
- package/dist/screenplay/RemotionRenderer/theme/themes/default/CaptionPunctuated.js +29 -6
- package/dist/screenplay/RemotionRenderer/theme/themes/default/CaptionWordBoom.js +42 -47
- package/dist/screenplay/RemotionRenderer/theme/themes/default/CaptionWordBubble.js +30 -7
- package/dist/screenplay/RemotionRenderer/theme/themes/default/Sentence/AnimatedSentence.js +1 -0
- package/dist/screenplay/RemotionRenderer/theme/themes/default/Sentence.js +8 -4
- package/dist/screenplay/RemotionRenderer/theme/themes/fullcover/TextFullCover.js +10 -5
- package/dist/screenplay/RemotionRenderer/theme/themes/glassmorphism/Sentence.js +14 -4
- package/dist/screenplay/RemotionRenderer/tracks/LayoutVideoTrack.js +1 -1
- package/dist/screenplay/RemotionRenderer/tracks/Soundtrack.js +20 -3
- package/dist/timing.cjs +1050 -0
- package/package.json +8 -4
|
@@ -1 +1,25 @@
|
|
|
1
|
+
/*! Fluent Emoji artwork
|
|
2
|
+
MIT License
|
|
3
|
+
|
|
4
|
+
Copyright (c) Microsoft Corporation.
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE
|
|
23
|
+
*/
|
|
24
|
+
|
|
1
25
|
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
|
@@ -8,13 +8,14 @@ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r),
|
|
|
8
8
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
9
9
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
10
10
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
11
|
+
import { prepareCaptionWordObjects } from "./helpers/captionWordObjects.js";
|
|
12
|
+
import { getWordObjectArtwork, isCatalogEmoji } from "./helpers/emojiCatalog.js";
|
|
11
13
|
import { applyLogoVisibility } from "./helpers/applyLogoVisibility.js";
|
|
12
14
|
import { screenplaySchema } from "./main/screenplaySchema.js";
|
|
13
15
|
import { LayoutFactory } from "./main/lib/layouts/LayoutFactory.js";
|
|
14
16
|
import { toFrames, toPascalCase } from "./main/lib/Sequence.js";
|
|
15
17
|
import { getCreatorCollabEffectProps } from "./main/lib/layouts/creatorCollabProps.js";
|
|
16
|
-
import
|
|
17
|
-
import { normalizeDisabledTranscripts } from "./helpers/normalizeDisabledTranscripts.js";
|
|
18
|
+
import timing from "../../timing.cjs";
|
|
18
19
|
import { coerceRenderableText, coerceRenderableTextProps, RENDERABLE_TEXT_PROP_KEYS } from "./helpers/coerceRenderableText.js";
|
|
19
20
|
export var RemotionRenderer = /*#__PURE__*/function () {
|
|
20
21
|
function RemotionRenderer(screenplay) {
|
|
@@ -27,7 +28,8 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
27
28
|
_defineProperty(this, "captionsVideoTrack", []);
|
|
28
29
|
_defineProperty(this, "audioTrack", []);
|
|
29
30
|
_defineProperty(this, "output", void 0);
|
|
30
|
-
this.screenplay =
|
|
31
|
+
this.screenplay = timing.prepareScreenplay(applyLogoVisibility(screenplay));
|
|
32
|
+
this.wordObjectStats = prepareCaptionWordObjects(this.screenplay, this.fps);
|
|
31
33
|
this.output = this.getRemotionOutputSettings();
|
|
32
34
|
}
|
|
33
35
|
return _createClass(RemotionRenderer, [{
|
|
@@ -44,10 +46,8 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
44
46
|
}, {
|
|
45
47
|
key: "getRemotionOutputSettings",
|
|
46
48
|
value: function getRemotionOutputSettings() {
|
|
47
|
-
var _this = this;
|
|
48
49
|
var compositionMetadata = {};
|
|
49
50
|
var orientation = this.screenplay.output.orientation;
|
|
50
|
-
var theme = this.screenplay.input.theme || "default";
|
|
51
51
|
switch (orientation) {
|
|
52
52
|
case "landscape":
|
|
53
53
|
{
|
|
@@ -68,24 +68,9 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
68
68
|
break;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
var _segment$layout, _segment$layout$data, _segment$layout2, _segment$layout2$data, _segment$layout3, _segment$layout3$data, _segment$transitionAf;
|
|
75
|
-
var segmentDuration = (segment === null || segment === void 0 ? void 0 : (_segment$layout = segment.layout) === null || _segment$layout === void 0 ? void 0 : (_segment$layout$data = _segment$layout.data) === null || _segment$layout$data === void 0 ? void 0 : _segment$layout$data.duration) || 0;
|
|
76
|
-
var trimLeft = (segment === null || segment === void 0 ? void 0 : (_segment$layout2 = segment.layout) === null || _segment$layout2 === void 0 ? void 0 : (_segment$layout2$data = _segment$layout2.data) === null || _segment$layout2$data === void 0 ? void 0 : _segment$layout2$data.trimLeft) || 0;
|
|
77
|
-
var trimRight = (segment === null || segment === void 0 ? void 0 : (_segment$layout3 = segment.layout) === null || _segment$layout3 === void 0 ? void 0 : (_segment$layout3$data = _segment$layout3.data) === null || _segment$layout3$data === void 0 ? void 0 : _segment$layout3$data.trimRight) || 0;
|
|
78
|
-
var netDuration = segmentDuration - trimLeft - trimRight;
|
|
79
|
-
var duration = durationInFrames + netDuration * _this.fps;
|
|
80
|
-
var transitionTheme = transitionThemes[theme];
|
|
81
|
-
var transitionAfter = (_segment$transitionAf = segment === null || segment === void 0 ? void 0 : segment.transitionAfter) !== null && _segment$transitionAf !== void 0 ? _segment$transitionAf : segment === null || segment === void 0 ? void 0 : segment.__transitionAfter;
|
|
82
|
-
if (transitionTheme) {
|
|
83
|
-
var isLast = index === array.length - 1;
|
|
84
|
-
var shouldApplyTransition = !isLast && transitionAfter !== false;
|
|
85
|
-
return toFrames(duration) - (shouldApplyTransition ? transitionTheme.durationInFrames : 0);
|
|
86
|
-
}
|
|
87
|
-
return toFrames(duration);
|
|
88
|
-
}, 0);
|
|
71
|
+
compositionMetadata.durationInFrames = timing.getScreenplayTiming(this.screenplay, {
|
|
72
|
+
prepared: true
|
|
73
|
+
}).durationInFrames;
|
|
89
74
|
compositionMetadata.theme = this.screenplay.input.theme || "default";
|
|
90
75
|
compositionMetadata.fps = this.fps;
|
|
91
76
|
return _objectSpread(_objectSpread({}, this.screenplay.output), compositionMetadata);
|
|
@@ -146,7 +131,7 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
146
131
|
}, {
|
|
147
132
|
key: "toRemotionSegment",
|
|
148
133
|
value: function toRemotionSegment(screenPlaySegment) {
|
|
149
|
-
var
|
|
134
|
+
var _this = this,
|
|
150
135
|
_ref2,
|
|
151
136
|
_screenPlaySegment$tr;
|
|
152
137
|
var layout = screenPlaySegment.layout,
|
|
@@ -156,9 +141,9 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
156
141
|
layout: LayoutFactory.createObject(layout),
|
|
157
142
|
effects: effects.map(function (effect) {
|
|
158
143
|
if (effect.type.includes("caption")) {
|
|
159
|
-
return
|
|
144
|
+
return _this.toRemotionCaptionSegment(effect, layout);
|
|
160
145
|
}
|
|
161
|
-
return
|
|
146
|
+
return _this.toRemotionFragment(effect, layout);
|
|
162
147
|
}),
|
|
163
148
|
transitionAfter: (_ref2 = (_screenPlaySegment$tr = screenPlaySegment === null || screenPlaySegment === void 0 ? void 0 : screenPlaySegment.transitionAfter) !== null && _screenPlaySegment$tr !== void 0 ? _screenPlaySegment$tr : screenPlaySegment === null || screenPlaySegment === void 0 ? void 0 : screenPlaySegment.__transitionAfter) !== null && _ref2 !== void 0 ? _ref2 : true
|
|
164
149
|
};
|
|
@@ -173,8 +158,16 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
173
158
|
value: function toRemotionCaptionSegment(screenPlaySegment, screenplayLayout) {
|
|
174
159
|
var _screenplayLayout$dat,
|
|
175
160
|
_screenPlaySegment$da23,
|
|
176
|
-
|
|
161
|
+
_this2 = this,
|
|
162
|
+
_screenplayLayout$dat2,
|
|
163
|
+
_screenplayLayout$dat3,
|
|
164
|
+
_screenplayLayout$dat4,
|
|
165
|
+
_screenplayLayout$dat5,
|
|
166
|
+
_screenplayLayout$dat6;
|
|
177
167
|
var trimLeft = (screenplayLayout === null || screenplayLayout === void 0 ? void 0 : (_screenplayLayout$dat = screenplayLayout.data) === null || _screenplayLayout$dat === void 0 ? void 0 : _screenplayLayout$dat.trimLeft) || 0;
|
|
168
|
+
// Only these layouts use the full-canvas face projection below. Other
|
|
169
|
+
// layouts still animate objects without assuming a full-canvas face crop.
|
|
170
|
+
var hasFullFrameVideo = ["simple_frame", "simple_frame_zoom_cut"].includes(screenplayLayout === null || screenplayLayout === void 0 ? void 0 : screenplayLayout.type);
|
|
178
171
|
var segmentOffset = Number(screenPlaySegment === null || screenPlaySegment === void 0 ? void 0 : (_screenPlaySegment$da23 = screenPlaySegment.data) === null || _screenPlaySegment$da23 === void 0 ? void 0 : _screenPlaySegment$da23.offset);
|
|
179
172
|
var from = Number.isFinite(segmentOffset) ? this.fps * (segmentOffset + trimLeft) : 0;
|
|
180
173
|
var transcripts = screenPlaySegment.data.transcript_text;
|
|
@@ -182,16 +175,20 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
182
175
|
throw new Error("No transcript_text provided in transcript segment");
|
|
183
176
|
}
|
|
184
177
|
transcripts = transcripts.map(function (transcript) {
|
|
185
|
-
var transcriptFrom =
|
|
186
|
-
var transcriptDurationInFrames = toFrames(
|
|
178
|
+
var transcriptFrom = _this2.fps * (transcript.offset - trimLeft) || 0;
|
|
179
|
+
var transcriptDurationInFrames = toFrames(_this2.fps * transcript.duration);
|
|
187
180
|
return {
|
|
188
181
|
text: coerceRenderableText(transcript.text),
|
|
189
182
|
from: transcriptFrom,
|
|
190
183
|
durationInFrames: transcriptDurationInFrames,
|
|
191
184
|
punctuations: transcript.punctuations ? transcript.punctuations.map(function (p) {
|
|
185
|
+
var _p$wordObject;
|
|
192
186
|
return _objectSpread(_objectSpread({}, p), {}, {
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
// Private URLs are always rebuilt from our catalog, never saved input.
|
|
188
|
+
__wordObjectImageUrl: p.__wordObjectDurationInFrames && isCatalogEmoji((_p$wordObject = p.wordObject) === null || _p$wordObject === void 0 ? void 0 : _p$wordObject.assetId) ? getWordObjectArtwork(p.wordObject.assetId) : undefined,
|
|
189
|
+
__wordObjectImageUnavailable: undefined,
|
|
190
|
+
start: toFrames(_this2.fps * (p.start - trimLeft)),
|
|
191
|
+
end: toFrames(_this2.fps * (p.end - trimLeft))
|
|
195
192
|
});
|
|
196
193
|
}) : []
|
|
197
194
|
};
|
|
@@ -202,7 +199,12 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
202
199
|
from: from,
|
|
203
200
|
transcripts: transcripts,
|
|
204
201
|
theme: screenPlaySegment.theme,
|
|
205
|
-
color: screenPlaySegment.data.color
|
|
202
|
+
color: screenPlaySegment.data.color,
|
|
203
|
+
wordObjectGeometry: screenplayLayout ? {
|
|
204
|
+
faceMetadata: hasFullFrameVideo ? (_screenplayLayout$dat2 = screenplayLayout.data) === null || _screenplayLayout$dat2 === void 0 ? void 0 : (_screenplayLayout$dat3 = _screenplayLayout$dat2.noBackgroundVideo) === null || _screenplayLayout$dat3 === void 0 ? void 0 : _screenplayLayout$dat3.faceMetadata : undefined,
|
|
205
|
+
videoZoom: screenplayLayout.type === "simple_frame_zoom_cut" ? 1.2 : ((_screenplayLayout$dat4 = screenplayLayout.data) === null || _screenplayLayout$dat4 === void 0 ? void 0 : (_screenplayLayout$dat5 = _screenplayLayout$dat4.sourceVideo) === null || _screenplayLayout$dat5 === void 0 ? void 0 : _screenplayLayout$dat5.zoom) || 1,
|
|
206
|
+
framePadding: (_screenplayLayout$dat6 = screenplayLayout.data) !== null && _screenplayLayout$dat6 !== void 0 && _screenplayLayout$dat6.frameColor ? 30 : 0
|
|
207
|
+
} : undefined
|
|
206
208
|
};
|
|
207
209
|
}
|
|
208
210
|
}, {
|
|
@@ -234,17 +236,23 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
234
236
|
}, {
|
|
235
237
|
key: "generateLayoutTrack",
|
|
236
238
|
value: function generateLayoutTrack() {
|
|
237
|
-
var
|
|
239
|
+
var _this3 = this;
|
|
238
240
|
var segmentTrack = this.getSegmentTrack();
|
|
239
241
|
var segments = segmentTrack.segments;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
var _timing$getScreenplay = timing.getScreenplayTiming(this.screenplay, {
|
|
243
|
+
prepared: true
|
|
244
|
+
}),
|
|
245
|
+
sequences = _timing$getScreenplay.sequences;
|
|
246
|
+
segments.forEach(function (segment, index) {
|
|
247
|
+
var rendered = _this3.toRemotionSegment(segment);
|
|
248
|
+
if (_this3.screenplay.input.theme === "none") rendered.transitionAfter = sequences[index].overlapFrames > 0;
|
|
249
|
+
_this3.layoutVideoTrack.push(rendered);
|
|
242
250
|
});
|
|
243
251
|
}
|
|
244
252
|
}, {
|
|
245
253
|
key: "generateEffectsTrack",
|
|
246
254
|
value: function generateEffectsTrack() {
|
|
247
|
-
var
|
|
255
|
+
var _this4 = this;
|
|
248
256
|
var screenPlayEffectTrack = this.screenplay.tracks.find(function (track) {
|
|
249
257
|
return track.type === "effect";
|
|
250
258
|
});
|
|
@@ -253,13 +261,13 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
253
261
|
}
|
|
254
262
|
var segments = screenPlayEffectTrack.segments;
|
|
255
263
|
segments.forEach(function (segment) {
|
|
256
|
-
|
|
264
|
+
_this4.effectsVideoTrack.push(_this4.toEffectSegment(segment));
|
|
257
265
|
});
|
|
258
266
|
}
|
|
259
267
|
}, {
|
|
260
268
|
key: "generateCaptionsTrack",
|
|
261
269
|
value: function generateCaptionsTrack() {
|
|
262
|
-
var
|
|
270
|
+
var _this5 = this;
|
|
263
271
|
var screenPlayCaptionTrack = this.screenplay.tracks.find(function (track) {
|
|
264
272
|
return track.type === "caption";
|
|
265
273
|
});
|
|
@@ -269,13 +277,13 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
269
277
|
var segments = screenPlayCaptionTrack.segments;
|
|
270
278
|
segments.forEach(function (segment, _ref3) {
|
|
271
279
|
_objectDestructuringEmpty(_ref3);
|
|
272
|
-
|
|
280
|
+
_this5.captionsVideoTrack.push(_this5.toRemotionCaptionSegment(segment));
|
|
273
281
|
});
|
|
274
282
|
}
|
|
275
283
|
}, {
|
|
276
284
|
key: "generateAudioTrack",
|
|
277
285
|
value: function generateAudioTrack() {
|
|
278
|
-
var
|
|
286
|
+
var _this6 = this;
|
|
279
287
|
var screenPlayAudioTrack = this.screenplay.tracks.find(function (track) {
|
|
280
288
|
return track.type === "audio";
|
|
281
289
|
});
|
|
@@ -285,7 +293,7 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
285
293
|
}
|
|
286
294
|
var segments = screenPlayAudioTrack.segments;
|
|
287
295
|
segments.forEach(function (segment) {
|
|
288
|
-
|
|
296
|
+
_this6.audioTrack.push(_this6.toRemotionAudioFragment(segment));
|
|
289
297
|
});
|
|
290
298
|
}
|
|
291
299
|
}, {
|
|
@@ -298,7 +306,8 @@ export var RemotionRenderer = /*#__PURE__*/function () {
|
|
|
298
306
|
effectsVideoTrack: this.effectsVideoTrack,
|
|
299
307
|
captionsVideoTrack: this.captionsVideoTrack,
|
|
300
308
|
audioTrack: this.audioTrack,
|
|
301
|
-
output: this.output
|
|
309
|
+
output: this.output,
|
|
310
|
+
captionWordObjectStats: this.wordObjectStats
|
|
302
311
|
};
|
|
303
312
|
}
|
|
304
313
|
}]);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|