{"id":44254063,"url":"https://github.com/cascable/cascablecore-simulated-camera","last_synced_at":"2026-02-10T16:01:52.193Z","repository":{"id":211125905,"uuid":"728201449","full_name":"Cascable/cascablecore-simulated-camera","owner":"Cascable","description":"A plugin for CascableCore to aid development without having a real camera to hand.","archived":false,"fork":false,"pushed_at":"2025-12-15T15:00:54.000Z","size":20777,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-18T19:42:35.775Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cascable.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-12-06T12:52:43.000Z","updated_at":"2025-12-15T14:59:45.000Z","dependencies_parsed_at":"2025-12-15T21:19:03.212Z","dependency_job_id":null,"html_url":"https://github.com/Cascable/cascablecore-simulated-camera","commit_stats":null,"previous_names":["cascable/cascablecore-simulated-camera"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/Cascable/cascablecore-simulated-camera","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Fcascablecore-simulated-camera","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Fcascablecore-simulated-camera/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Fcascablecore-simulated-camera/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Fcascablecore-simulated-camera/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cascable","download_url":"https://codeload.github.com/Cascable/cascablecore-simulated-camera/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cascable%2Fcascablecore-simulated-camera/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29306433,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T15:37:45.286Z","status":"ssl_error","status_checked_at":"2026-02-10T15:37:41.567Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-10T16:01:51.382Z","updated_at":"2026-02-10T16:01:52.187Z","avatar_url":"https://github.com/Cascable.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"#  CascableCore Simulated Camera\n\nThis Swift Package Manager/SPM package contains a plugin for [CascableCore](https://github.com/cascable/cascablecore-distribution/) that provides a \"simulated\" camera through the regular CascableCore APIs. By including this package in your CascableCore-using product, you can work with the simulated camera with just a few lines of code.\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg width=\"800\" src=\"https://github.com/Cascable/cascablecore-simulated-camera/assets/514900/344d1024-0238-4328-8bcc-70bcbdd68f47\"\u003e\u003cbr\u003e\n\t\u003cem\u003eThe simulated camera in use in some of Cascable's apps.\u003c/em\u003e\n\u003c/p\u003e\n\n### Contents\n\n- [What It's Bad For](#what-its-bad-for)\n- [What It's Good For](#what-its-good-for)\n- [Adding the Simulated Camera to Your Project](#adding-the-simulated-camera-to-your-project)\n- [Configuring the Simulated Camera](#configuring-the-simulated-camera)\n- [Limitations](#limitations)\n\n### What It's Bad For\n\n🚨 **Important:** 🚨 The simulated camera is **not** a replacement for testing your app with real cameras. Real cameras are complicated, subject to the user providing input via them, and have whims and lifecycles of their own. The simulated camera plugin makes no attempt to replicate these details.\n\n### What It's Good For\n\nWhat the simulated camera *is* good for, however, is drastically simplifying day-to-day development, testing camera UI flows you may not have access to, implementing UI tests, and even producing marketing materials.\n\nSome example use cases include:\n\n- Having a simulated camera allows access to portions of your app that require a connected camera, allowing development of these portions without needing a real camera constantly around.\n\n- The simulated camera can be configured with different authentication types and property types, allowing the testing of the various UI pieces needed for these different variations without having to have many different cameras always at hand.\n\n- The simulated camera is available in the simulator and without any network access, meaning it can be used by automated UI tests (tip: set the simulated camera's `connectionSpeed` to `.instant` for snappy and repeatable tests).\n\n- The simulated camera can be configured with a custom model name and live view images, making it great for producing marketing images. Many of the marketing screenshots used on [our own website](https://cascable.se/ios/) and App Store pages were produced automatically using UI automation and the simulated camera plugin.\n\n### Adding the Simulated Camera to Your Project\n\nAdding the simulated camera to your project is easy - simply add this package to your project as you would any other Swift Package Manager package, then `import CascableCoreSimulatedCamera` near your camera connection code. The CascableCore plugin system will pick up and load the plugin when your application runs.\n\n**Note:** Since the simulated camera plugin is built alongside CascableCore, it has fairly tight version requirements to the CascableCore distribution package.\n\nPlugin loading is done via the CascableCore `CameraDiscovery` class. You can check that the plugin is loaded by checking the `loadedPluginIdentifiers` property:\n\n```swift\nimport CascableCore\nimport CascableCoreSimulatedCamera\n\nlet cameraDiscovery = CameraDiscovery.shared\n\nif cameraDiscovery.loadedPluginIdentifiers.contains(SimulatedCameraEntryPoint.pluginIdentifier) {\n    print(\"Simulated camera is loaded!\")\n}\n```\n\nCascableCore enables all plugins by default. It's probably not a good idea to have the simulated camera enabled in builds distributed to your customers (at least not by default), so it's important to disable it if it's not wanted. For example, maybe you only want it enabled for debug builds:\n\n```swift \n#if DEBUG\ncameraDiscovery.setEnabled(true, forPluginWithIdentifier: SimulatedCameraEntryPoint.pluginIdentifier)\n#else\ncameraDiscovery.setEnabled(false, forPluginWithIdentifier: SimulatedCameraEntryPoint.pluginIdentifier)\n#endif\n\nif cameraDiscovery.enabledPluginIdentifiers.contains(SimulatedCameraEntryPoint.pluginIdentifier) {\n    print(\"Simulated camera is enabled!\")\n}\n```\n\nOnce added and enabled (or, rather, not disabled), the simulated camera will be delivered through the same camera discovery process you'd use for any other camera.\n\n### Configuring the Simulated Camera\n\nThe simulated camera is set up with some sensible defaults by default, but you can configure various aspects of it to suit your needs via the `SimulatedCameraConfiguration` struct.\n\n**Important:** You must apply configuration changes before the simulated camera is discovered by CascableCore. The best way to ensure this is to apply your changes before calling `beginSearching()` on the `CameraDiscovery` object:\n\n```swift  \nimport CascableCore\nimport CascableCoreSimulatedCamera\n\nvar config: SimulatedCameraConfiguration = .default\nconfig.connectionAuthentication = .fourDigitCode(\"1234\")\nconfig.connectionSpeed = .fast\nconfig.apply() // You *must* call this method for changes to take effect.\n\nlet cameraDiscovery = CameraDiscovery.shared\ncameraDiscovery.delegate = self\ncameraDiscovery.beginSearching()\n```\n\nThe `SimulatedCameraConfiguration` struct has the following properties:\n\n- **manufacturer**: The simulated camera's manufacturer name. The default value is `Cascable`.\n\n- **model**: The simulated camera's model name. The default value is `Simulated Camera`.\n\n- **identifier**: The simulated camera's identifier, which will be used for serial numbers, authentication identifiers, etc. The default value is the plugin's identifier (`se.cascable.CascableCore.plugin.simulated-camera`).\n\n- **connectionAuthentication**: Which authentication type to perform when connecting to the simulated camera. The default value is `.pairOnCamera`.\n\n- **connectionSpeed**: The simulated connection speed. The default value is `.fast`.\n\n- **connectionTransports**: Which transport(s) the simulated camera will be discovered on. The default value is `[.network, .USB]`.\n\n- **exposurePropertyType**: How simulated exposure properties (aperture, shutter speed, ISO, etc) are set. Defaults to `.enumerated`.\n\n- **liveViewImageFrames**: An array of local file URLs to JPEG images to be used as the live view stream. These images will be loaded upon live view start and delivered in a loop at approximately 30fps. The images must all be the same size and around 720p (or the 3:2 or 4:3 equivalent) or so to be accurate. Setting an array of one item is valid for a static image. Setting an empty array or including non-JPEG images will cause the simulated live view stream to fail.\n\n- **storageFileSystemRoot**: The local filesystem URL to expose as a storage device on the simulated camera. When set to an accessible directory, the simulated camera will use that directory's contents to populate the camera's storage device. For best results, it should simulate a real layout (`/DCIM/100CAMERA/etc`). The default value is `nil`.\n\n- **fileSystemAccess**: How the simulated camera grants filesystem access. Defaults to `.alongsideRemoteShooting`.\n\n### Limitations\n\nThe simulated camera has been an internal Cascable tool for a few years, and these initial versions are largely a tidyup and documentation effort of that internal plugin. As such, a decent amount of more advanced functionality has yet to be implemented. We'll be improving the plugin over time — if any missing features are particularly important to you, please let us know.\n\n#### Camera Discovery \u0026 Connection  \n\n- ✅ Customisation of camera manufacturer, name, identifier, etc\n- ✅ Customisation of simulated connection speed\n- ✅ Simulation of all connection authentication types\n\n#### Properties\n\n- ✅ Exposure settings based on autoexposure mode \n- ✅ Enumerated property setting\n- ✅ Stepped property setting\n- ✅ Basic properties\n- ❌ Full range of properties\n\n#### Photo \u0026 Video Shooting\n\n- ✅ Basic shooting\n- ❌ Autoexposure results\n- ❌ Direct focus manipulation\n- ✅ Camera-initiated transfers for previews\n- ❌ Camera-initiated transfers for original images (\"tethering\")\n- ✅ Video recording\n- ✅ Switching the simulated camera between stills shooting, video recording, and filesystem modes \n\n#### Live View\n\n- ✅ Live view streaming with customisable image feed\n- ✅ Application of the `CBLLiveViewOptionSkipImageDecoding` setting\n- ❌ Application of the `CBLLiveViewOptionFavorHighFrameRate` setting\n- ❌ Live view rotation\n- ❌ Tap-to-focus, focus point geometry\n- ❌ Live view zoom\n\n#### Filesystem Access\n\n- ✅ Read-only access to the file system\n- ❌ Filesystem event observation\n- ❌ Read-write access to the file system (file deletion, etc)\n\n#### Misc. Features\n\n- ❌ Clock updating\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcascable%2Fcascablecore-simulated-camera","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcascable%2Fcascablecore-simulated-camera","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcascable%2Fcascablecore-simulated-camera/lists"}