serve-sim 0.1.46 → 0.1.47-beta.119.1
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.
|
@@ -70,6 +70,7 @@ void SimCamLogSwallowedRuntimeError(NSString *via, id object, NSDictionary *user
|
|
|
70
70
|
AVCaptureDeviceFormat *SimCamSharedFakeFormat(void);
|
|
71
71
|
AVCaptureDevice *SimCamFakeDeviceForPosition(AVCaptureDevicePosition p);
|
|
72
72
|
AVCaptureDeviceInput *SimCamFakeInputForPosition(AVCaptureDevicePosition p);
|
|
73
|
+
NSArray<AVCaptureInputPort *> *SimCamFakePortsForInput(AVCaptureInput *input);
|
|
73
74
|
|
|
74
75
|
AVCaptureConnection *SimCamFakeConnectionForOutput(AVCaptureOutput *out);
|
|
75
76
|
void SimCamSetOutputInput(AVCaptureOutput *out, AVCaptureInput *input);
|
|
@@ -317,8 +317,7 @@ static AVCaptureInputPort *SimCamFakeInputPortForInput(AVCaptureInput *input, AV
|
|
|
317
317
|
- (AVCaptureOutput *)output { return _outputRef; }
|
|
318
318
|
- (NSArray *)inputPorts {
|
|
319
319
|
AVCaptureInput *input = SimCamOutputInput(_outputRef) ?: SimCamFakeInputForPosition(_position);
|
|
320
|
-
|
|
321
|
-
return port ? @[port] : @[];
|
|
320
|
+
return SimCamFakePortsForInput(input);
|
|
322
321
|
}
|
|
323
322
|
- (AVCaptureInput *)input { return SimCamOutputInput(_outputRef) ?: SimCamFakeInputForPosition(_position); }
|
|
324
323
|
- (AVCaptureVideoPreviewLayer *)videoPreviewLayer { return nil; }
|
|
@@ -480,6 +479,12 @@ static AVCaptureInputPort *SimCamFakeInputPortForInput(AVCaptureInput *input, AV
|
|
|
480
479
|
return port;
|
|
481
480
|
}
|
|
482
481
|
|
|
482
|
+
NSArray<AVCaptureInputPort *> *SimCamFakePortsForInput(AVCaptureInput *input) {
|
|
483
|
+
if (!SimCamIsFakeInput(input)) return @[];
|
|
484
|
+
AVCaptureInputPort *port = SimCamFakeInputPortForInput(input, SimCamPositionOf(input));
|
|
485
|
+
return port ? @[port] : @[];
|
|
486
|
+
}
|
|
487
|
+
|
|
483
488
|
#pragma mark - SimCamFakeInput marking
|
|
484
489
|
|
|
485
490
|
static char kSimCamFakeInputKey;
|
|
@@ -190,7 +190,7 @@ static BOOL SwizzleInstanceMethod(Class cls, SEL orig, SEL swiz) {
|
|
|
190
190
|
return [self simcam_device];
|
|
191
191
|
}
|
|
192
192
|
- (NSArray *)simcam_ports {
|
|
193
|
-
if (SimCamIsFakeInput(self)) return
|
|
193
|
+
if (SimCamIsFakeInput(self)) return SimCamFakePortsForInput(self);
|
|
194
194
|
return [self simcam_ports];
|
|
195
195
|
}
|
|
196
196
|
@end
|
|
@@ -200,7 +200,10 @@ static BOOL SwizzleInstanceMethod(Class cls, SEL orig, SEL swiz) {
|
|
|
200
200
|
static char kSimCamSessionRunningKey;
|
|
201
201
|
static char kSimCamSessionInputsKey;
|
|
202
202
|
static char kSimCamSessionOutputsKey;
|
|
203
|
+
static char kSimCamSessionConnectionsKey;
|
|
203
204
|
static char kSimCamOutputAttachedToFakeSessionKey;
|
|
205
|
+
static char kSimCamOutputSessionKey;
|
|
206
|
+
static char kSimCamMaxPhotoDimensionsKey;
|
|
204
207
|
|
|
205
208
|
static NSMutableArray *SimCamSessionTrackedInputs(AVCaptureSession *s) {
|
|
206
209
|
NSMutableArray *arr = objc_getAssociatedObject(s, &kSimCamSessionInputsKey);
|
|
@@ -218,6 +221,14 @@ static NSMutableArray *SimCamSessionTrackedOutputs(AVCaptureSession *s) {
|
|
|
218
221
|
}
|
|
219
222
|
return arr;
|
|
220
223
|
}
|
|
224
|
+
static NSMutableArray *SimCamSessionTrackedConnections(AVCaptureSession *s) {
|
|
225
|
+
NSMutableArray *arr = objc_getAssociatedObject(s, &kSimCamSessionConnectionsKey);
|
|
226
|
+
if (!arr) {
|
|
227
|
+
arr = [NSMutableArray new];
|
|
228
|
+
objc_setAssociatedObject(s, &kSimCamSessionConnectionsKey, arr, OBJC_ASSOCIATION_RETAIN);
|
|
229
|
+
}
|
|
230
|
+
return arr;
|
|
231
|
+
}
|
|
221
232
|
|
|
222
233
|
static AVCaptureInput *SimCamFirstFakeInputForSession(AVCaptureSession *s) {
|
|
223
234
|
for (AVCaptureInput *candidate in SimCamSessionTrackedInputs(s)) {
|
|
@@ -229,26 +240,95 @@ static AVCaptureInput *SimCamFirstFakeInputForSession(AVCaptureSession *s) {
|
|
|
229
240
|
// Real AVFoundation only exposes output connections after an output has been
|
|
230
241
|
// attached to a session. Keep this per-output so newly created outputs still
|
|
231
242
|
// look disconnected during client-side session configuration checks.
|
|
232
|
-
static void SimCamMarkOutputAttachedToFakeSession(AVCaptureSession *s, AVCaptureOutput *output) {
|
|
233
|
-
if (!output) return;
|
|
234
|
-
objc_setAssociatedObject(output, &kSimCamOutputAttachedToFakeSessionKey, @YES, OBJC_ASSOCIATION_RETAIN);
|
|
235
|
-
SimCamSetOutputInput(output, SimCamFirstFakeInputForSession(s));
|
|
236
|
-
}
|
|
237
243
|
static void SimCamUnmarkOutputAttachedToFakeSession(AVCaptureOutput *output) {
|
|
238
244
|
if (!output) return;
|
|
239
245
|
objc_setAssociatedObject(output, &kSimCamOutputAttachedToFakeSessionKey, nil, OBJC_ASSOCIATION_RETAIN);
|
|
246
|
+
objc_setAssociatedObject(output, &kSimCamOutputSessionKey, nil, OBJC_ASSOCIATION_RETAIN);
|
|
247
|
+
objc_setAssociatedObject(output, &kSimCamMaxPhotoDimensionsKey, nil, OBJC_ASSOCIATION_RETAIN);
|
|
240
248
|
SimCamSetOutputInput(output, nil);
|
|
241
249
|
}
|
|
250
|
+
static void SimCamMarkOutputAttachedToFakeSession(AVCaptureSession *s, AVCaptureOutput *output) {
|
|
251
|
+
if (!output) return;
|
|
252
|
+
AVCaptureInput *input = SimCamFirstFakeInputForSession(s);
|
|
253
|
+
if (!input) {
|
|
254
|
+
SimCamUnmarkOutputAttachedToFakeSession(output);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
objc_setAssociatedObject(output, &kSimCamOutputAttachedToFakeSessionKey, @YES, OBJC_ASSOCIATION_RETAIN);
|
|
258
|
+
SimCamWeakRef *sessionRef = [SimCamWeakRef new];
|
|
259
|
+
sessionRef.target = s;
|
|
260
|
+
objc_setAssociatedObject(output, &kSimCamOutputSessionKey, sessionRef, OBJC_ASSOCIATION_RETAIN);
|
|
261
|
+
SimCamSetOutputInput(output, input);
|
|
262
|
+
}
|
|
242
263
|
static BOOL SimCamOutputAttachedToFakeSession(AVCaptureOutput *output) {
|
|
243
264
|
if (!output) return NO;
|
|
244
265
|
return [objc_getAssociatedObject(output, &kSimCamOutputAttachedToFakeSessionKey) boolValue];
|
|
245
266
|
}
|
|
246
267
|
static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
247
|
-
AVCaptureInput *input = SimCamFirstFakeInputForSession(s);
|
|
248
268
|
for (AVCaptureOutput *output in SimCamSessionTrackedOutputs(s)) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
269
|
+
SimCamMarkOutputAttachedToFakeSession(s, output);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
static AVCaptureSession *SimCamFakeSessionForOutput(AVCaptureOutput *output) {
|
|
273
|
+
SimCamWeakRef *ref = objc_getAssociatedObject(output, &kSimCamOutputSessionKey);
|
|
274
|
+
return ref.target;
|
|
275
|
+
}
|
|
276
|
+
static BOOL SimCamConnectionUsesInput(AVCaptureConnection *connection, AVCaptureInput *input) {
|
|
277
|
+
for (AVCaptureInputPort *port in connection.inputPorts) {
|
|
278
|
+
if (port.input == input) return YES;
|
|
279
|
+
}
|
|
280
|
+
return NO;
|
|
281
|
+
}
|
|
282
|
+
static BOOL SimCamConnectionUsesFakeInput(AVCaptureConnection *connection) {
|
|
283
|
+
for (AVCaptureInputPort *port in connection.inputPorts) {
|
|
284
|
+
if (SimCamIsFakeInput(port.input)) return YES;
|
|
285
|
+
}
|
|
286
|
+
return NO;
|
|
287
|
+
}
|
|
288
|
+
static BOOL SimCamConnectionBelongsToSession(
|
|
289
|
+
AVCaptureConnection *connection,
|
|
290
|
+
AVCaptureSession *session
|
|
291
|
+
) {
|
|
292
|
+
NSArray<AVCaptureInputPort *> *ports = connection.inputPorts;
|
|
293
|
+
if (ports.count == 0) return NO;
|
|
294
|
+
NSArray<AVCaptureInput *> *inputs = SimCamSessionTrackedInputs(session);
|
|
295
|
+
for (AVCaptureInputPort *port in ports) {
|
|
296
|
+
if (![inputs containsObject:port.input]) return NO;
|
|
297
|
+
}
|
|
298
|
+
AVCaptureOutput *output = connection.output;
|
|
299
|
+
return !output || [SimCamSessionTrackedOutputs(session) containsObject:output];
|
|
300
|
+
}
|
|
301
|
+
static NSArray<AVCaptureConnection *> *SimCamConnectionsForOutput(AVCaptureOutput *output) {
|
|
302
|
+
AVCaptureSession *session = SimCamFakeSessionForOutput(output);
|
|
303
|
+
if (!session) return @[];
|
|
304
|
+
NSMutableArray *result = [NSMutableArray new];
|
|
305
|
+
for (AVCaptureConnection *connection in SimCamSessionTrackedConnections(session)) {
|
|
306
|
+
if (connection.output == output) [result addObject:connection];
|
|
307
|
+
}
|
|
308
|
+
return [result copy];
|
|
309
|
+
}
|
|
310
|
+
static void SimCamRecordConnection(AVCaptureSession *session, AVCaptureConnection *connection) {
|
|
311
|
+
if (!connection) return;
|
|
312
|
+
NSMutableArray *connections = SimCamSessionTrackedConnections(session);
|
|
313
|
+
if (![connections containsObject:connection]) [connections addObject:connection];
|
|
314
|
+
}
|
|
315
|
+
static void SimCamRemoveConnectionsForOutput(AVCaptureSession *session, AVCaptureOutput *output) {
|
|
316
|
+
NSMutableArray *connections = SimCamSessionTrackedConnections(session);
|
|
317
|
+
for (AVCaptureConnection *connection in [connections copy]) {
|
|
318
|
+
if (connection.output == output) [connections removeObject:connection];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
static void SimCamRemoveConnectionsForInput(AVCaptureSession *session, AVCaptureInput *input) {
|
|
322
|
+
NSMutableArray *connections = SimCamSessionTrackedConnections(session);
|
|
323
|
+
for (AVCaptureConnection *connection in [connections copy]) {
|
|
324
|
+
if (SimCamConnectionUsesInput(connection, input)) [connections removeObject:connection];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
static void SimCamAddAutomaticConnections(AVCaptureSession *session) {
|
|
328
|
+
for (AVCaptureOutput *output in SimCamSessionTrackedOutputs(session)) {
|
|
329
|
+
if (!SimCamOutputAttachedToFakeSession(output)) continue;
|
|
330
|
+
if (SimCamConnectionsForOutput(output).count > 0) continue;
|
|
331
|
+
SimCamRecordConnection(session, SimCamFakeConnectionForOutput(output));
|
|
252
332
|
}
|
|
253
333
|
}
|
|
254
334
|
|
|
@@ -264,6 +344,7 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
264
344
|
NSMutableArray *tracked = SimCamSessionTrackedInputs(self);
|
|
265
345
|
if (![tracked containsObject:input]) [tracked addObject:input];
|
|
266
346
|
SimCamRefreshAttachedOutputInputsForSession(self);
|
|
347
|
+
SimCamAddAutomaticConnections(self);
|
|
267
348
|
simcam_log(@"addInput: fake input (%@) — tracked (count=%lu), skipping native add",
|
|
268
349
|
p == AVCaptureDevicePositionBack ? @"back" : @"front",
|
|
269
350
|
(unsigned long)tracked.count);
|
|
@@ -294,6 +375,7 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
294
375
|
- (void)simcam_removeInput:(AVCaptureInput *)input {
|
|
295
376
|
if (SimCamIsFakeInput(input)) {
|
|
296
377
|
NSMutableArray *tracked = SimCamSessionTrackedInputs(self);
|
|
378
|
+
SimCamRemoveConnectionsForInput(self, input);
|
|
297
379
|
[tracked removeObject:input];
|
|
298
380
|
SimCamRefreshAttachedOutputInputsForSession(self);
|
|
299
381
|
if (tracked.count == 0) SimCamMarkSessionUsingFakeCamera(self, NO);
|
|
@@ -305,10 +387,13 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
305
387
|
}
|
|
306
388
|
- (void)simcam_addOutput:(AVCaptureOutput *)output {
|
|
307
389
|
SimCamSetPosition(output, SimCamPositionOf(self));
|
|
308
|
-
SimCamMarkOutputAttachedToFakeSession(self, output);
|
|
309
390
|
SimCamMarkCameraInUse();
|
|
310
391
|
NSMutableArray *tracked = SimCamSessionTrackedOutputs(self);
|
|
311
392
|
if (![tracked containsObject:output]) [tracked addObject:output];
|
|
393
|
+
SimCamMarkOutputAttachedToFakeSession(self, output);
|
|
394
|
+
if (SimCamOutputAttachedToFakeSession(output)) {
|
|
395
|
+
SimCamRecordConnection(self, SimCamFakeConnectionForOutput(output));
|
|
396
|
+
}
|
|
312
397
|
simcam_log(@"addOutput: %@ (intercepted, tracked count=%lu, pos=%d)",
|
|
313
398
|
NSStringFromClass([output class]),
|
|
314
399
|
(unsigned long)tracked.count,
|
|
@@ -317,16 +402,17 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
317
402
|
- (BOOL)simcam_canAddOutput:(AVCaptureOutput *)output { return YES; }
|
|
318
403
|
- (void)simcam_addOutputWithNoConnections:(AVCaptureOutput *)output {
|
|
319
404
|
SimCamSetPosition(output, SimCamPositionOf(self));
|
|
320
|
-
SimCamMarkOutputAttachedToFakeSession(self, output);
|
|
321
405
|
SimCamMarkCameraInUse();
|
|
322
406
|
NSMutableArray *tracked = SimCamSessionTrackedOutputs(self);
|
|
323
407
|
if (![tracked containsObject:output]) [tracked addObject:output];
|
|
408
|
+
SimCamMarkOutputAttachedToFakeSession(self, output);
|
|
324
409
|
simcam_log(@"addOutputWithNoConnections: %@ (intercepted, tracked count=%lu, pos=%d)",
|
|
325
410
|
NSStringFromClass([output class]),
|
|
326
411
|
(unsigned long)tracked.count,
|
|
327
412
|
(int)SimCamPositionOf(self));
|
|
328
413
|
}
|
|
329
414
|
- (void)simcam_removeOutput:(AVCaptureOutput *)output {
|
|
415
|
+
SimCamRemoveConnectionsForOutput(self, output);
|
|
330
416
|
SimCamUnmarkOutputAttachedToFakeSession(output);
|
|
331
417
|
NSMutableArray *tracked = SimCamSessionTrackedOutputs(self);
|
|
332
418
|
[tracked removeObject:output];
|
|
@@ -344,9 +430,33 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
344
430
|
simcam_log(@"commitConfiguration intercepted (session=%p, fakeInputs=%lu, fakeOutputs=%lu)",
|
|
345
431
|
self, (unsigned long)inCount, (unsigned long)outCount);
|
|
346
432
|
}
|
|
347
|
-
- (BOOL)simcam_canAddConnection:(AVCaptureConnection *)
|
|
433
|
+
- (BOOL)simcam_canAddConnection:(AVCaptureConnection *)connection {
|
|
434
|
+
if (SimCamConnectionUsesFakeInput(connection)) {
|
|
435
|
+
return SimCamConnectionBelongsToSession(connection, self) &&
|
|
436
|
+
![SimCamSessionTrackedConnections(self) containsObject:connection];
|
|
437
|
+
}
|
|
438
|
+
return [self simcam_canAddConnection:connection];
|
|
439
|
+
}
|
|
348
440
|
- (void)simcam_addConnection:(AVCaptureConnection *)c {
|
|
349
|
-
|
|
441
|
+
if (!SimCamConnectionUsesFakeInput(c)) {
|
|
442
|
+
[self simcam_addConnection:c];
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (!SimCamConnectionBelongsToSession(c, self)) {
|
|
446
|
+
simcam_log(@"addConnection: rejected unowned fake connection (session=%p, conn=%p)", self, c);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
AVCaptureOutput *output = c.output;
|
|
450
|
+
SimCamRecordConnection(self, c);
|
|
451
|
+
simcam_log(@"addConnection: fake input (session=%p, conn=%p, output=%p)", self, c, output);
|
|
452
|
+
}
|
|
453
|
+
- (void)simcam_removeConnection:(AVCaptureConnection *)c {
|
|
454
|
+
if (!SimCamConnectionUsesFakeInput(c)) {
|
|
455
|
+
[self simcam_removeConnection:c];
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
[SimCamSessionTrackedConnections(self) removeObject:c];
|
|
459
|
+
simcam_log(@"removeConnection: fake input (session=%p, conn=%p, output=%p)", self, c, c.output);
|
|
350
460
|
}
|
|
351
461
|
- (NSArray<AVCaptureInput *> *)simcam_inputs {
|
|
352
462
|
NSMutableArray *tracked = objc_getAssociatedObject(self, &kSimCamSessionInputsKey);
|
|
@@ -371,14 +481,10 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
371
481
|
return [merged copy];
|
|
372
482
|
}
|
|
373
483
|
- (NSArray<AVCaptureConnection *> *)simcam_connections {
|
|
374
|
-
NSMutableArray *
|
|
484
|
+
NSMutableArray *tracked = objc_getAssociatedObject(self, &kSimCamSessionConnectionsKey);
|
|
375
485
|
NSArray *native = [self simcam_connections];
|
|
376
|
-
if (
|
|
377
|
-
NSMutableArray *merged = [
|
|
378
|
-
for (AVCaptureOutput *o in trackedOut) {
|
|
379
|
-
AVCaptureConnection *c = SimCamFakeConnectionForOutput(o);
|
|
380
|
-
if (c) [merged addObject:c];
|
|
381
|
-
}
|
|
486
|
+
if (tracked.count == 0) return native ?: @[];
|
|
487
|
+
NSMutableArray *merged = [tracked mutableCopy];
|
|
382
488
|
for (AVCaptureConnection *n in native) {
|
|
383
489
|
if (![merged containsObject:n]) [merged addObject:n];
|
|
384
490
|
}
|
|
@@ -478,17 +584,22 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
478
584
|
if (real) return real;
|
|
479
585
|
if (!SimCamOutputAttachedToFakeSession(self)) return nil;
|
|
480
586
|
if (![mediaType isEqualToString:AVMediaTypeVideo]) return nil;
|
|
481
|
-
AVCaptureConnection *
|
|
482
|
-
simcam_log(@"connectionWithMediaType:%@ →
|
|
483
|
-
mediaType,
|
|
484
|
-
return
|
|
587
|
+
AVCaptureConnection *connection = SimCamConnectionsForOutput(self).firstObject;
|
|
588
|
+
simcam_log(@"connectionWithMediaType:%@ → tracked %p for %@ %p",
|
|
589
|
+
mediaType, connection, NSStringFromClass([self class]), self);
|
|
590
|
+
return connection;
|
|
485
591
|
}
|
|
486
592
|
- (NSArray<AVCaptureConnection *> *)simcam_connections {
|
|
487
593
|
NSArray *real = [self simcam_connections];
|
|
488
|
-
if (real.count > 0) return real;
|
|
489
594
|
if (!SimCamOutputAttachedToFakeSession(self)) return real ?: @[];
|
|
490
|
-
|
|
491
|
-
|
|
595
|
+
NSArray *tracked = SimCamConnectionsForOutput(self);
|
|
596
|
+
if (tracked.count == 0) return real ?: @[];
|
|
597
|
+
if (real.count == 0) return tracked;
|
|
598
|
+
NSMutableArray *merged = [tracked mutableCopy];
|
|
599
|
+
for (AVCaptureConnection *connection in real) {
|
|
600
|
+
if (![merged containsObject:connection]) [merged addObject:connection];
|
|
601
|
+
}
|
|
602
|
+
return [merged copy];
|
|
492
603
|
}
|
|
493
604
|
@end
|
|
494
605
|
|
|
@@ -537,8 +648,33 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
537
648
|
@interface AVCapturePhotoOutput (SimCam)
|
|
538
649
|
@end
|
|
539
650
|
@implementation AVCapturePhotoOutput (SimCam)
|
|
651
|
+
- (CMVideoDimensions)simcam_maxPhotoDimensions {
|
|
652
|
+
if (SimCamOutputAttachedToFakeSession(self)) {
|
|
653
|
+
NSValue *value = objc_getAssociatedObject(self, &kSimCamMaxPhotoDimensionsKey);
|
|
654
|
+
if (value) {
|
|
655
|
+
CMVideoDimensions dimensions = { 0, 0 };
|
|
656
|
+
[value getValue:&dimensions size:sizeof(dimensions)];
|
|
657
|
+
return dimensions;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return [self simcam_maxPhotoDimensions];
|
|
661
|
+
}
|
|
662
|
+
- (void)simcam_setMaxPhotoDimensions:(CMVideoDimensions)dimensions {
|
|
663
|
+
if (!SimCamOutputAttachedToFakeSession(self)) {
|
|
664
|
+
[self simcam_setMaxPhotoDimensions:dimensions];
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
// AVFoundation validates this against private AVCaptureDeviceFormat state.
|
|
668
|
+
// Synthetic formats only have public state, so retain the value per output.
|
|
669
|
+
NSValue *value = [NSValue valueWithBytes:&dimensions objCType:@encode(CMVideoDimensions)];
|
|
670
|
+
objc_setAssociatedObject(self, &kSimCamMaxPhotoDimensionsKey, value, OBJC_ASSOCIATION_RETAIN);
|
|
671
|
+
}
|
|
540
672
|
- (void)simcam_capturePhotoWithSettings:(AVCapturePhotoSettings *)settings
|
|
541
673
|
delegate:(id<AVCapturePhotoCaptureDelegate>)delegate {
|
|
674
|
+
if (!SimCamOutputAttachedToFakeSession(self)) {
|
|
675
|
+
[self simcam_capturePhotoWithSettings:settings delegate:delegate];
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
542
678
|
if (!delegate) return;
|
|
543
679
|
SimCamRegistry *reg = [SimCamRegistry shared];
|
|
544
680
|
CVPixelBufferRef pb = [reg currentPixelBuffer];
|
|
@@ -581,11 +717,11 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
581
717
|
(int)p, (int)mirror, (unsigned long)photo.fileDataRepresentation.length,
|
|
582
718
|
resolved.photoDimensions.width, resolved.photoDimensions.height);
|
|
583
719
|
AVCapturePhotoOutput *output = self;
|
|
584
|
-
SEL selWillBegin = @selector(
|
|
585
|
-
SEL selWillCapture = @selector(
|
|
586
|
-
SEL selDidProcess = @selector(
|
|
587
|
-
SEL selDidCapture = @selector(
|
|
588
|
-
SEL selDidFinish = @selector(
|
|
720
|
+
SEL selWillBegin = @selector(captureOutput:willBeginCaptureForResolvedSettings:);
|
|
721
|
+
SEL selWillCapture = @selector(captureOutput:willCapturePhotoForResolvedSettings:);
|
|
722
|
+
SEL selDidProcess = @selector(captureOutput:didFinishProcessingPhoto:error:);
|
|
723
|
+
SEL selDidCapture = @selector(captureOutput:didCapturePhotoForResolvedSettings:);
|
|
724
|
+
SEL selDidFinish = @selector(captureOutput:didFinishCaptureForResolvedSettings:error:);
|
|
589
725
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
590
726
|
if ([delegate respondsToSelector:selWillBegin]) {
|
|
591
727
|
((void (*)(id, SEL, AVCapturePhotoOutput *, AVCaptureResolvedPhotoSettings *))
|
|
@@ -595,16 +731,16 @@ static void SimCamRefreshAttachedOutputInputsForSession(AVCaptureSession *s) {
|
|
|
595
731
|
((void (*)(id, SEL, AVCapturePhotoOutput *, AVCaptureResolvedPhotoSettings *))
|
|
596
732
|
objc_msgSend)(delegate, selWillCapture, output, resolved);
|
|
597
733
|
}
|
|
734
|
+
if ([delegate respondsToSelector:selDidCapture]) {
|
|
735
|
+
((void (*)(id, SEL, AVCapturePhotoOutput *, AVCaptureResolvedPhotoSettings *))
|
|
736
|
+
objc_msgSend)(delegate, selDidCapture, output, resolved);
|
|
737
|
+
}
|
|
598
738
|
BOOL delivered = NO;
|
|
599
739
|
if ([delegate respondsToSelector:selDidProcess]) {
|
|
600
740
|
((void (*)(id, SEL, AVCapturePhotoOutput *, AVCapturePhoto *, NSError *))
|
|
601
741
|
objc_msgSend)(delegate, selDidProcess, output, photo, (NSError *)nil);
|
|
602
742
|
delivered = YES;
|
|
603
743
|
}
|
|
604
|
-
if ([delegate respondsToSelector:selDidCapture]) {
|
|
605
|
-
((void (*)(id, SEL, AVCapturePhotoOutput *, AVCaptureResolvedPhotoSettings *))
|
|
606
|
-
objc_msgSend)(delegate, selDidCapture, output, resolved);
|
|
607
|
-
}
|
|
608
744
|
if ([delegate respondsToSelector:selDidFinish]) {
|
|
609
745
|
((void (*)(id, SEL, AVCapturePhotoOutput *, AVCaptureResolvedPhotoSettings *, NSError *))
|
|
610
746
|
objc_msgSend)(delegate, selDidFinish, output, resolved, (NSError *)nil);
|
|
@@ -984,6 +1120,9 @@ void SimCamInstallSwizzles(void) {
|
|
|
984
1120
|
SwizzleInstanceMethod(sess,
|
|
985
1121
|
@selector(addConnection:),
|
|
986
1122
|
@selector(simcam_addConnection:));
|
|
1123
|
+
SwizzleInstanceMethod(sess,
|
|
1124
|
+
@selector(removeConnection:),
|
|
1125
|
+
@selector(simcam_removeConnection:));
|
|
987
1126
|
SwizzleInstanceMethod(sess,
|
|
988
1127
|
@selector(canAddConnection:),
|
|
989
1128
|
@selector(simcam_canAddConnection:));
|
|
@@ -1050,6 +1189,14 @@ void SimCamInstallSwizzles(void) {
|
|
|
1050
1189
|
}
|
|
1051
1190
|
|
|
1052
1191
|
Class photoOut = [AVCapturePhotoOutput class];
|
|
1192
|
+
if (@available(iOS 16.0, *)) {
|
|
1193
|
+
SwizzleInstanceMethod(photoOut,
|
|
1194
|
+
@selector(maxPhotoDimensions),
|
|
1195
|
+
@selector(simcam_maxPhotoDimensions));
|
|
1196
|
+
SwizzleInstanceMethod(photoOut,
|
|
1197
|
+
@selector(setMaxPhotoDimensions:),
|
|
1198
|
+
@selector(simcam_setMaxPhotoDimensions:));
|
|
1199
|
+
}
|
|
1053
1200
|
SwizzleInstanceMethod(photoOut,
|
|
1054
1201
|
@selector(capturePhotoWithSettings:delegate:),
|
|
1055
1202
|
@selector(simcam_capturePhotoWithSettings:delegate:));
|
package/dist/serve-sim.js
CHANGED
|
@@ -146,7 +146,7 @@ Usage:
|
|
|
146
146
|
serve-sim permissions reset <permission|all> <bundle-id> [-d <udid|name>]
|
|
147
147
|
serve-sim permissions list [bundle-id] [-d <udid|name>]
|
|
148
148
|
|
|
149
|
-
Permissions: ${k8().join(", ")}`),process.exit(1);let Y=J.device?o(J.device):Q$();if(!Y)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(J.verb==="list"){let G={udid:Y,bundleId:J.bundleId??null,tcc:RZ(Y,J.bundleId),location:UZ(Y,J.bundleId),notifications:FZ(Y,J.bundleId)};console.log(JSON.stringify(G,null,Q?0:2)),process.exit(0)}let X=J.bundleId;try{if(J.permission==="all")for(let G of k8())n6(Y,"reset",G,void 0,X);else n6(Y,J.verb,J.permission,J.value,X)}catch(G){console.error(G?.message??String(G)),process.exit(1)}if(Q)console.log(JSON.stringify({udid:Y,verb:J.verb,permission:J.permission,value:J.value??null,bundleId:X}));else{let G=J.value?` (${J.value})`:"";console.log(`\uD83D\uDD10 ${J.verb} ${J.permission}${G} for ${X} on ${Y}`)}process.exit(0)}l8();o8();function F7($,Q={}){let Z=new Date($.timestamp),J=Number.isNaN(Z.getTime())?$.timestamp:Z.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),Y=Q.deviceLabel??($.device?$.device.slice(0,8):null),X=$.status==="error"?" failed":"";return[J,Y,`${V1($)}${X?` (${X.trim()})`:""}`].filter(Boolean).join(" ")}function V1($){if($.kind==="tap"){let Q=i0($.details,"current")??i0($.details,"start");return Q?`Tap at ${a8(Q)}`:"Tap"}if($.kind==="drag"){let Q=i0($.details,"start"),Z=i0($.details,"current");if(Q&&Z)return`Drag from ${a8(Q)} to ${a8(Z)}`;return"Drag"}if($.kind==="key"){let Q=M1($.details,"key")??$.action??"key",Z=$.action==="down"?"down":$.action==="up"?"up":$.action;return Z?`Key ${Z} ${B7(Q)}`:`Key ${B7(Q)}`}if($.kind==="rotate"){let Q=$.action?T7($.action):"";return Q?`Rotate ${Q}`:"Rotate"}return R1($.msg??$.summary)}function i0($,Q){let Z=$?.[Q];if(!Z||typeof Z!=="object"||Array.isArray(Z))return null;let J=Z;return typeof J.x==="number"&&typeof J.y==="number"?{x:J.x,y:J.y}:null}function M1($,Q){let Z=$?.[Q];return typeof Z==="string"&&Z.length>0?Z:null}function a8($){return`${N7($.x)}, ${N7($.y)}`}function N7($){if(!Number.isFinite($))return"?";return(Math.round((H1($,0,1)+Number.EPSILON)*100)/100).toFixed(2)}function H1($,Q,Z){return Math.min(Z,Math.max(Q,$))}function R1($){return $.replace(/\b[a-z]+(?:_[a-z]+)+\b/g,T7)}function T7($){return $.replace(/[-_]+/g," ")}function B7($){return{MetaLeft:"Left Command",MetaRight:"Right Command",AltLeft:"Left Option",AltRight:"Right Option",ControlLeft:"Left Control",ControlRight:"Right Control",ShiftLeft:"Left Shift",ShiftRight:"Right Shift",ArrowLeft:"Left Arrow",ArrowRight:"Right Arrow",ArrowUp:"Up Arrow",ArrowDown:"Down Arrow"}[$]??$}var j7=["devices","tools","devtools"];function O7($){let Q=$.split(",").map((J)=>J.trim().toLowerCase()).filter(Boolean);if(Q.length===1&&Q[0]==="none")return[];if(Q.length===0||Q.includes("none"))throw Error("Expected 'none' or a comma-separated list of: devices, tools, devtools.");let Z=Q.filter((J)=>!j7.includes(J));if(Z.length>0)throw Error(`Unknown pane${Z.length===1?"":"s"}: ${Z.join(", ")}. Expected: ${j7.join(", ")}.`);return[...new Set(Q)]}function E7($){let Q=$.trim().toLowerCase();if(Q==="light"||Q==="dark")return Q;throw Error("Expected simulator theme: light or dark.")}s8();var C$=u0(import.meta.url);function LY(){return"0.1.
|
|
149
|
+
Permissions: ${k8().join(", ")}`),process.exit(1);let Y=J.device?o(J.device):Q$();if(!Y)console.error("No booted simulator. Boot one or pass -d <udid|name>."),process.exit(1);if(J.verb==="list"){let G={udid:Y,bundleId:J.bundleId??null,tcc:RZ(Y,J.bundleId),location:UZ(Y,J.bundleId),notifications:FZ(Y,J.bundleId)};console.log(JSON.stringify(G,null,Q?0:2)),process.exit(0)}let X=J.bundleId;try{if(J.permission==="all")for(let G of k8())n6(Y,"reset",G,void 0,X);else n6(Y,J.verb,J.permission,J.value,X)}catch(G){console.error(G?.message??String(G)),process.exit(1)}if(Q)console.log(JSON.stringify({udid:Y,verb:J.verb,permission:J.permission,value:J.value??null,bundleId:X}));else{let G=J.value?` (${J.value})`:"";console.log(`\uD83D\uDD10 ${J.verb} ${J.permission}${G} for ${X} on ${Y}`)}process.exit(0)}l8();o8();function F7($,Q={}){let Z=new Date($.timestamp),J=Number.isNaN(Z.getTime())?$.timestamp:Z.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"}),Y=Q.deviceLabel??($.device?$.device.slice(0,8):null),X=$.status==="error"?" failed":"";return[J,Y,`${V1($)}${X?` (${X.trim()})`:""}`].filter(Boolean).join(" ")}function V1($){if($.kind==="tap"){let Q=i0($.details,"current")??i0($.details,"start");return Q?`Tap at ${a8(Q)}`:"Tap"}if($.kind==="drag"){let Q=i0($.details,"start"),Z=i0($.details,"current");if(Q&&Z)return`Drag from ${a8(Q)} to ${a8(Z)}`;return"Drag"}if($.kind==="key"){let Q=M1($.details,"key")??$.action??"key",Z=$.action==="down"?"down":$.action==="up"?"up":$.action;return Z?`Key ${Z} ${B7(Q)}`:`Key ${B7(Q)}`}if($.kind==="rotate"){let Q=$.action?T7($.action):"";return Q?`Rotate ${Q}`:"Rotate"}return R1($.msg??$.summary)}function i0($,Q){let Z=$?.[Q];if(!Z||typeof Z!=="object"||Array.isArray(Z))return null;let J=Z;return typeof J.x==="number"&&typeof J.y==="number"?{x:J.x,y:J.y}:null}function M1($,Q){let Z=$?.[Q];return typeof Z==="string"&&Z.length>0?Z:null}function a8($){return`${N7($.x)}, ${N7($.y)}`}function N7($){if(!Number.isFinite($))return"?";return(Math.round((H1($,0,1)+Number.EPSILON)*100)/100).toFixed(2)}function H1($,Q,Z){return Math.min(Z,Math.max(Q,$))}function R1($){return $.replace(/\b[a-z]+(?:_[a-z]+)+\b/g,T7)}function T7($){return $.replace(/[-_]+/g," ")}function B7($){return{MetaLeft:"Left Command",MetaRight:"Right Command",AltLeft:"Left Option",AltRight:"Right Option",ControlLeft:"Left Control",ControlRight:"Right Control",ShiftLeft:"Left Shift",ShiftRight:"Right Shift",ArrowLeft:"Left Arrow",ArrowRight:"Right Arrow",ArrowUp:"Up Arrow",ArrowDown:"Down Arrow"}[$]??$}var j7=["devices","tools","devtools"];function O7($){let Q=$.split(",").map((J)=>J.trim().toLowerCase()).filter(Boolean);if(Q.length===1&&Q[0]==="none")return[];if(Q.length===0||Q.includes("none"))throw Error("Expected 'none' or a comma-separated list of: devices, tools, devtools.");let Z=Q.filter((J)=>!j7.includes(J));if(Z.length>0)throw Error(`Unknown pane${Z.length===1?"":"s"}: ${Z.join(", ")}. Expected: ${j7.join(", ")}.`);return[...new Set(Q)]}function E7($){let Q=$.trim().toLowerCase();if(Q==="light"||Q==="dark")return Q;throw Error("Expected simulator theme: light or dark.")}s8();var C$=u0(import.meta.url);function LY(){return"0.1.47-beta.119.1"}function T4(){if(!K$(W$))$6(W$,{recursive:!0})}function r($){if($)return sQ(V0($));for(let Q of b0()){let Z=sQ(Q);if(Z)return Z}return null}var _8={at:0,booted:null};function UY(){let $=Date.now();if(_8.booted&&$-_8.at<1000)return _8.booted;try{let Q=J$("xcrun simctl list devices booted -j",{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3000}),Z=JSON.parse(Q),J=new Set;for(let Y of Object.values(Z.devices))for(let X of Y)if(X.state==="Booted")J.add(X.udid);return _8={at:$,booted:J},J}catch{return null}}function sQ($){try{if(!K$($))return V$("state file missing %s",$),null;let Q=JSON.parse(m$($,"utf-8"));try{process.kill(Q.pid,0)}catch{return V$("helper pid %d dead, removing stale state %s",Q.pid,$),g$($),null}let Z=UY();if(Z&&!Z.has(Q.device)){if(Q.pid===process.pid){V$("dropping own stale state for non-booted device %s",Q.device);try{g$($)}catch{}return null}V$("helper pid %d bound to non-booted device %s — killing stale helper",Q.pid,Q.device),console.error(`[serve-sim] Helper pid ${Q.pid} is bound to device ${Q.device} which is no longer booted — killing stale helper.`);try{process.kill(Q.pid,"SIGTERM")}catch{}try{g$($)}catch{}return null}return V$("state ok pid=%d device=%s port=%d",Q.pid,Q.device,Q.port),Q}catch(Q){return V$("readStateFile threw for %s: %o",$,Q),null}}function x0(){let $=[];for(let Q of b0()){let Z=sQ(Q);if(Z)$.push(Z)}return $}function _Y($){T4(),J6(V0($.device),JSON.stringify($,null,2)),V$("wrote state pid=%d device=%s port=%d",$.pid,$.device,$.port)}function c$($){if($){V$("clearState device=%s",$);try{g$(V0($))}catch{}}else{V$("clearState (all)");for(let Q of b0())try{g$(Q)}catch{}}}function Y6(){try{let $=J$("xcrun simctl list devices -j",{encoding:"utf-8"}),Q=JSON.parse($),Z=Object.keys(Q.devices).filter((J)=>/SimRuntime\.iOS-/i.test(J)).sort((J,Y)=>{let X=(J.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number),G=(Y.match(/iOS-(\d+)-(\d+)/)??[]).slice(1).map(Number);return(G[0]??0)-(X[0]??0)||(G[1]??0)-(X[1]??0)});for(let J of Z){let X=(Q.devices[J]??[]).find((G)=>G.isAvailable!==!1&&/^iPhone\b/i.test(G.name));if(X)return{udid:X.udid,name:X.name}}}catch{}return null}function B4($){return j4().get($)??null}function j4(){let $=new Map;try{let Q=J$("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse(Q);for(let J of Object.values(Z.devices))for(let Y of J)$.set(Y.udid,Y.name)}catch{}return $}function O4($){try{let Q=J$("xcrun simctl list devices -j",{encoding:"utf-8"}),Z=JSON.parse(Q);for(let J of Object.values(Z.devices))for(let Y of J)if(Y.udid===$)return Y.state==="Booted"}catch{}return!1}function eQ($){try{return process.kill($,0),!0}catch{return!1}}function E4($){try{process.kill($,"SIGTERM")}catch{return}let Q=Date.now()+500;while(Date.now()<Q)try{process.kill($,0),I$(25)}catch{return}try{process.kill($,"SIGKILL")}catch{}let Z=Date.now()+500;while(Date.now()<Z)try{process.kill($,0),I$(25)}catch{return}}function NY($){if(!O4($))try{J$(`xcrun simctl boot ${$}`,{encoding:"utf-8",stdio:"pipe"})}catch(Q){let Z=(Q.stderr??Q.message??"").toLowerCase();if(!Z.includes("booted")&&!Z.includes("current state"))throw Error(`Failed to boot device ${$}: ${Q.stderr||Q.message}`)}try{J$("open -ga Simulator",{encoding:"utf-8",stdio:"pipe",timeout:3000})}catch{}}function BY(){let $=RY();for(let Q of Object.values($))for(let Z of Q??[])if(Z.family==="IPv4"&&!Z.internal)return Z.address;return null}async function q4($){let Q=new Set(x0().map((Z)=>Z.port));for(let Z=$;Z<$+100;Z++){if(Q.has(Z))continue;if(await m6(Z))return Z}throw Error(`No available port found in range ${$}-${$+99}`)}async function FY($){NY($);try{VY("xcrun",s0($),{encoding:"utf-8",stdio:"pipe",timeout:60000})}catch(Q){if(!O4($))console.error(`Device ${$} failed to reach booted state: ${Q.stderr||Q.message}`),process.exit(1)}}function TY($){if(process.argv[0]&&/(^|\/)serve-sim$/.test(process.argv[0]))return{command:process.argv[0],args:$};return{command:process.argv[0],args:[process.argv[1],...$]}}async function jY($,Q=150000){let Z=Date.now();while(Date.now()-Z<Q){let J=r($);if(J)return J;await new Promise((Y)=>setTimeout(Y,200))}return null}async function A4($,Q,Z){i8("startHelper udid=%s port=%d detach=%s",$,Q,Z.detach);let J="127.0.0.1";T4(),c$($),p6(Q);let Y=M$(W$,`server-${$}.log`),X=Q6(Y,"w"),{command:G,args:V}=TY([$,"--port",String(Q),"--host",J]),W=F4(G,V,{detached:Z.detach,stdio:["ignore",X,X]});if(Z6(X),Z.detach)W.unref();let z=await jY($);if(!z){if(W.pid)E4(W.pid);let K="";try{K=m$(Y,"utf-8").trim()}catch{}console.error(K?`Preview server failed:
|
|
150
150
|
${K}`:"Preview server failed to start"),process.exit(1)}return Z.detach?{pid:z.pid}:{pid:z.pid,child:W}}async function OY($,Q,Z){n8("follow devices=%o startPort=%d",$,Q);let J=$.length>0?$.map(o):(()=>{let z=Q$();if(z)return[z];let K=Y6();if(!K)console.error("No device specified and no available iOS simulator found."),process.exit(1);if(!Z)console.log(`No booted simulator — booting ${K.name}...`);return[K.udid]})(),Y=new Map,X=[],G=Q;for(let z of J){let K=r(z);if(K){if(!Z){let T=B4(z)??z;if(J.length>1)console.log(`
|
|
151
151
|
==> ${T} (${z}) <==`);console.log(` Already running on port ${K.port}`),console.log(` Stream: ${K.streamUrl}`),console.log(` WebSocket: ${K.wsUrl}`)}X.push(K);continue}G=await q4(G);let{child:R}=await A4(z,G,{detach:!1});if(R)Y.set(z,R);let H=r(z)??i$(z,G,"/","127.0.0.1");if(X.push(H),!Z){let T=B4(z)??z;if(J.length>1)console.log(`
|
|
152
152
|
==> ${T} (${z}) <==`);console.log(` Stream: ${H.streamUrl}`),console.log(` WebSocket: ${H.wsUrl}`),console.log(` Port: ${G}`)}G++}if(X.length===1){let z=X[0];console.log(JSON.stringify({url:z.url,streamUrl:z.streamUrl,wsUrl:z.wsUrl,port:z.port,device:z.device}))}else console.log(JSON.stringify({devices:X.map((z)=>({url:z.url,streamUrl:z.streamUrl,wsUrl:z.wsUrl,port:z.port,device:z.device}))}));if(Y.size===0)return;let V=!1,W=(z)=>{if(V)return;if(V=!0,!Z)console.log(`
|
|
@@ -202,5 +202,5 @@ Examples:
|
|
|
202
202
|
serve-sim --list Show all running streams
|
|
203
203
|
serve-sim --kill Stop all streams`).action(async($,Q)=>{if(Q.list!==void 0){AY(typeof Q.list==="string"?Q.list:void 0);return}if(Q.kill!==void 0){DY(typeof Q.kill==="string"?Q.kill:void 0);return}let Z=Q.port;if(Q.detach){let J=await EY($,Z??3100);qY(J)}else if(Q.preview===!1)await OY($,Z??3100,!!Q.quiet);else{let J=Q.panes!==void 0||Q.fit?{...Q.panes!==void 0?{panes:Q.panes}:{},...Q.fit?{fit:!0}:{}}:void 0;await oY(Z??3200,$,Z!==void 0,Q.host,Q.codec,J,Q.theme)}});var P$=["-d, --device <udid>","Target a specific simulator (udid or name)"];Y$.command("gesture").description("Send a touch gesture").argument("<json>",`Gesture JSON, e.g. '{"type":"begin","x":0.5,"y":0.5}'`).option(...P$).action(($,Q)=>xY($,Q.device));Y$.command("tap").description("Tap at normalized 0..1 coords").argument("<x>","X coord, normalized 0..1").argument("<y>","Y coord, normalized 0..1").option(...P$).action(($,Q,Z)=>wY($,Q,Z.device));Y$.command("button").description("Send a hardware button press").argument("[name]","Button name","home").option(...P$).action(($,Q)=>fY($,Q.device));Y$.command("type").description("Type text (US keyboard only)").argument("[text...]","Text to type").option(...P$).option("--stdin","Read text from stdin").option("--file <path>","Read text from a file").action(($,Q)=>kY($,{device:Q.device,stdin:Q.stdin,file:Q.file}));Y$.command("rotate").description("Set device orientation (portrait|portrait_upside_down|landscape_left|landscape_right)").argument("<orientation>").option(...P$).action(($,Q)=>SY($,Q.device));Y$.command("ca-debug").description("Toggle a CoreAnimation debug render flag (blended|copies|misaligned|offscreen|slow-animations)").argument("<option>").argument("<state>","on|off").option(...P$).action(($,Q,Z)=>bY($,Q,Z.device));Y$.command("memory-warning").description("Simulate a memory warning on the device").option(...P$).action(($)=>vY($.device));Y$.command("event-log").description("Show recent simulator events").option(...P$).option("-j, --json","Print JSON").option("-n, --limit <count>","Maximum number of events").action(($)=>CY($.device,{json:$.json,limit:$.limit}));Y$.command("camera").description("Inject a synthetic camera feed and launch an app (see `camera --help`)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>nY($));Y$.command("permissions").description("Manage app permissions (see `permissions` with no args for usage)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>e6($));Y$.command("ui").description("Get or set simulator-wide UI options (see `ui --help`)").allowUnknownOption(!0).helpOption(!1).argument("[args...]").action(($)=>G7($));await Y$.parseAsync(process.argv);
|
|
204
204
|
|
|
205
|
-
//# debugId=
|
|
205
|
+
//# debugId=4B851EADC630E3CD64756E2164756E21
|
|
206
206
|
//# sourceMappingURL=serve-sim.js.map
|
|
Binary file
|