├── .gitignore ├── LICENSE.md ├── README.md ├── dependencies ├── .gitkeep ├── EDSDK │ ├── .gitkeep │ └── Header │ │ └── .gitkeep └── EDSDK_64 │ ├── Dll │ └── .gitkeep │ └── Library │ └── .gitkeep ├── edsdk ├── __init__.py ├── api.pyi ├── constants │ ├── __init__.py │ ├── commands.py │ ├── generic.py │ └── properties.py ├── edsdk_python.cpp ├── edsdk_python.h ├── edsdk_utils.cpp ├── edsdk_utils.h └── py.typed ├── examples └── save_image.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # PyCharm project folders 107 | .idea 108 | 109 | # SciKit-Build files 110 | _skbuild/ 111 | 112 | .DS_Store 113 | tags 114 | 115 | dependencies/* 116 | !**.gitkeep 117 | 118 | .vscode 119 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Francesco Leacche 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # edsdk-python 2 | 3 | Python wrapper for Canon EOS Digital Software Development Kit, aka EDSDK. 4 | 5 | Currently, it supports Windows only. But it shouldn't be difficult to adapt it for macOS. 6 | 7 | # How to build 8 | 9 | ## Obtain the EDSDK from Canon 10 | 11 | Before you can use this library you need to obtain the EDSDK library from Canon. You can do so via their developers program: 12 | 13 | - [Canon Europe](https://www.canon-europe.com/business/imaging-solutions/sdk/) 14 | - [Canon Americas](https://developercommunity.usa.canon.com) 15 | - [Canon Asia](https://asia.canon/en/campaign/developerresources) 16 | - [Canon Oceania](https://www.canon.com.au/support/support-news/support-news/digital-slr-camera-software-developers-kit) 17 | - [Canon China](https://www.canon.com.cn/supports/sdk/index.html) 18 | - [Canon Korea](https://www.canon-ci.co.kr/support/sdk/sdkMain) 19 | - [Canon Japan](https://cweb.canon.jp/eos/info/api-package/) 20 | 21 | Once you were granted access - this may take a few days - download the latest version of their library. 22 | 23 | ## Copy the EDSDK Headers and Libraries 24 | 25 | You should now have access to a zip file containing the file you need to build this library. 26 | 27 | Unzip the file and copy the following folders inside the `dependencies` folder of this project: 28 | 1. `EDSDK` - Containing headers and 32-bit libraries (we only use the headers!) 29 | 2. `EDSDK_64` - Containing 64-bit version of the .lib and .dlls (which we do use!) 30 | 31 | Your dependencies folder structure should now look like this: 32 | 33 | ``` 34 | dependencies/EDSDK/Header/EDSDK.h 35 | dependencies/EDSDK/Header/EDSDKErrors.h 36 | dependencies/EDSDK/Header/EDSDKTypes.h 37 | 38 | dependencies/EDSDK_64/Dll/EDSDK.dll 39 | dependencies/EDSDK_64/Dll/EdsImage.dll 40 | 41 | dependencies/EDSDK_64/Library/EDSDK.lib 42 | ``` 43 | 44 | Any additional files aren't needed, but won't hurt either in case you copied the entire folders. 45 | 46 | 47 | ## Modify EDSDKTypes.h 48 | 49 | This file contains an enum definition, called `Unknown`, which collides with a DEFINE in the `Windows.h` header. 50 | 51 | Therefore needs to be renamed. 52 | 53 | ```c 54 | typedef enum 55 | { 56 | Unknown = 0x00000000, 57 | Jpeg = 0x3801, 58 | CR2 = 0xB103, 59 | MP4 = 0xB982, 60 | CR3 = 0xB108, 61 | HEIF_CODE = 0xB10B, 62 | } EdsObjectFormat; 63 | ``` 64 | 65 | You can comment out `Unknown` or rename it to `UNKNOWN` (or whatever you want) or it won't compile on Windows. 66 | 67 | 68 | ## Build the library 69 | 70 | Run: 71 | 72 | ```bash 73 | pip install . 74 | ``` 75 | 76 | ## Throubleshooting 77 | 78 | C2365: 'Unknown': redefinition; previous definition was 'enumerator' : go to the section [Modify EDSDKTypes.h](#modify-edsdktypesh) and follow the instructions. 79 | -------------------------------------------------------------------------------- /dependencies/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiloc/edsdk-python/129cadba64efe92776ce53a79127aa8dcf64b373/dependencies/.gitkeep -------------------------------------------------------------------------------- /dependencies/EDSDK/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiloc/edsdk-python/129cadba64efe92776ce53a79127aa8dcf64b373/dependencies/EDSDK/.gitkeep -------------------------------------------------------------------------------- /dependencies/EDSDK/Header/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiloc/edsdk-python/129cadba64efe92776ce53a79127aa8dcf64b373/dependencies/EDSDK/Header/.gitkeep -------------------------------------------------------------------------------- /dependencies/EDSDK_64/Dll/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiloc/edsdk-python/129cadba64efe92776ce53a79127aa8dcf64b373/dependencies/EDSDK_64/Dll/.gitkeep -------------------------------------------------------------------------------- /dependencies/EDSDK_64/Library/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiloc/edsdk-python/129cadba64efe92776ce53a79127aa8dcf64b373/dependencies/EDSDK_64/Library/.gitkeep -------------------------------------------------------------------------------- /edsdk/__init__.py: -------------------------------------------------------------------------------- 1 | from edsdk.api import * 2 | from edsdk.constants import * 3 | -------------------------------------------------------------------------------- /edsdk/api.pyi: -------------------------------------------------------------------------------- 1 | from typing import Tuple, Dict, Callable, Any, Union 2 | from edsdk.constants import ( 3 | CameraStatusCommand, 4 | ProgressOption, 5 | StateEvent, 6 | ObjectEvent, 7 | PropertyEvent, 8 | PropID, 9 | CameraCommand, 10 | Access, 11 | FileCreateDisposition, 12 | DataType, 13 | ImageSource, 14 | TargetImageType, 15 | ) 16 | 17 | 18 | class EdsObject: ... 19 | 20 | 21 | def InitializeSDK() -> None: 22 | """Initializes the libraries 23 | When using the EDSDK libraries, you must call this API once 24 | before using EDSDK APIs 25 | 26 | :raises EdsError: Any of the sdk errors. 27 | """ 28 | ... 29 | 30 | 31 | def TerminateSDK() -> None: 32 | """Terminates use of the libraries 33 | This function muse be called when ending the SDK. 34 | Calling this function releases all resources allocated by the libraries. 35 | 36 | :raises EdsError: Any of the sdk errors. 37 | """ 38 | ... 39 | 40 | 41 | def GetChildCount(parent: EdsObject) -> int: 42 | """Gets the number of child objects of the designated object. 43 | Example: Number of files in a directory 44 | 45 | :param EdsObject parent: the list object. 46 | :raises EdsError: Any of the sdk errors. 47 | :return int: Number of elements in this list. 48 | """ 49 | ... 50 | 51 | 52 | def GetChildAtIndex(parent: EdsObject, index: int) -> EdsObject: 53 | """Gets an indexed child object of the designated object 54 | 55 | :param EdsObject parent: the list object. 56 | :param int index: The index that is passed in, is zero based. 57 | :raises EdsError: Any of the sdk errors. 58 | :return EdsObject: the child object. 59 | """ 60 | ... 61 | 62 | 63 | def GetParent(item: EdsObject) -> EdsObject: 64 | """Gets the parent object of the designated object. 65 | 66 | :param EdsObject item: the item object. 67 | :raises EdsError: Any of the sdk errors. 68 | :return EdsObject: the parent object. 69 | """ 70 | ... 71 | 72 | 73 | def GetPropertySize( 74 | camera_or_image: EdsObject, property_id: PropID, param: int = 0 75 | ) -> Tuple[DataType, int]: 76 | """Gets the byte size and data type of a designated property 77 | from a camera object or image object. 78 | 79 | :param EdsObject camera_or_image: the item object. 80 | :param PropID property_id: The property ID. 81 | :param int param: Specify an index in case there are two or 82 | more values over the same ID, defaults to 0. 83 | :raises EdsError: Any of the sdk errors. 84 | :return Tuple[DataType, int]: the property DataType and size in bytes. 85 | """ 86 | ... 87 | 88 | 89 | def GetPropertyData( 90 | camera_or_image: EdsObject, property_id: PropID, param: int = 0 91 | ) -> Any: 92 | """Gets property information from the designated object. 93 | 94 | :param EdsObject camera_or_image: The reference of the item. 95 | :param PropID property_id: The PropertyID. 96 | :param int param: Specify an index in case there are two or 97 | more values over the same ID, defaults to 0. 98 | :raises EdsError: Any of the sdk errors. 99 | :return Any: The property value. 100 | """ 101 | ... 102 | 103 | 104 | def SetPropertyData( 105 | camera_or_image: EdsObject, property_id: PropID, param: int, data: Any 106 | ) -> None: 107 | """Sets property data for the designated object. 108 | 109 | :param EdsObject camera_or_image: The item object. 110 | :param PropID property_id: The PropertyID. 111 | :param int param: Specify an index in case there are two or 112 | more values over the same ID. 113 | :param Any data: The data to set. 114 | :raises EdsError: Any of the sdk errors. 115 | """ 116 | ... 117 | 118 | 119 | def GetPropertyDesc(camera: EdsObject, property_id: PropID) -> Dict[str, Any]: 120 | """Gets a list of property data that can be set for the object 121 | designated in inRef, as well as maximum and minimum values. 122 | This API is intended for only some shooting-related properties. 123 | 124 | 125 | :param EdsObject camera: The camera item. 126 | :param PropID property_id: The Property ID. 127 | :raises EdsError: Any of the sdk errors. 128 | :return Dict[str, Any]: The values which can be set up. 129 | """ 130 | ... 131 | 132 | 133 | def GetCameraList() -> EdsObject: 134 | """Gets camera list objects. 135 | 136 | :raises EdsError: Any of the sdk errors. 137 | :return EdsObject: the camera-list. 138 | """ 139 | ... 140 | 141 | 142 | def GetDeviceInfo(camera: EdsObject) -> Dict[str, Any]: 143 | """Gets device information, such as the device name. 144 | Because device information of remote cameras is stored 145 | on the host computer, you can use this API 146 | before the camera object initiates communication 147 | (that is, before a session is opened). 148 | 149 | :param EdsObject camera: The camera object. 150 | :raises EdsError: Any of the sdk errors. 151 | :return Dict[str, Any]: The device information. 152 | """ 153 | ... 154 | 155 | 156 | def OpenSession(camera: EdsObject) -> None: 157 | """Establishes a logical connection with a remote camera. 158 | Use this API after getting the camera's EdsCamera object. 159 | 160 | :param EdsObject camera: the camera. 161 | :raises EdsError: Any of the sdk errors. 162 | """ 163 | ... 164 | 165 | 166 | def CloseSession(camera: EdsObject) -> None: 167 | """Closes a logical connection with a remote camera 168 | 169 | :param EdsObject camera: the camera. 170 | :raises EdsError: Any of the sdk errors. 171 | """ 172 | ... 173 | 174 | 175 | def SendCommand(camera: EdsObject, command: CameraCommand, param: int = 0) -> None: 176 | """Sends a command such as "Shoot" to a remote camera. 177 | 178 | :param EdsObject camera: The camera object. 179 | :param CameraCommand command: Specifies the command to be sent. 180 | :param int param: Specifies additional command-specific information, 181 | defaults to 0. 182 | :raises EdsError: Any of the sdk errors. 183 | """ 184 | ... 185 | 186 | def SendStatusCommand( 187 | camera: EdsObject, command: CameraStatusCommand, param: int = 0 188 | ) -> None: 189 | """Sends a command such as "Shoot" to a remote camera. 190 | 191 | :param EdsObject camera: The camera object. 192 | :param CameraStatusCommand command: Specifies the command to be sent. 193 | :param int param: Specifies additional command-specific information, 194 | defaults to 0. 195 | :raises EdsError: Any of the sdk errors. 196 | """ 197 | ... 198 | 199 | 200 | def SetCapacity(camera: EdsObject, capacity: Dict[str, Any]) -> None: 201 | """Sets the remaining HDD capacity on the host computer 202 | (excluding the portion from image transfer), 203 | as calculated by subtracting the portion from the previous time. 204 | Set a reset flag initially and designate the cluster length 205 | and number of free clusters. 206 | Some type 2 protocol standard cameras can display the number of shots 207 | left on the camera based on the available disk capacity 208 | of the host computer 209 | For these cameras, after the storage destination is set to the computer, 210 | use this API to notify the camera of the available disk capacity 211 | of the host computer. 212 | 213 | :param EdsObject camera: The camera object. 214 | :param Dict[str, Any] capacity: The remaining capacity of a transmission place. 215 | :raises EdsError: Any of the sdk errors. 216 | """ 217 | ... 218 | 219 | 220 | def GetVolumeInfo(volume: EdsObject) -> Dict[str, Any]: 221 | """Gets volume information for a memory card in the camera. 222 | 223 | :param EdsObject volume: The volume item. 224 | :raises EdsError: Any of the sdk errors. 225 | :return Dict[str, Any]: Information of the volume 226 | """ 227 | ... 228 | 229 | 230 | def FormatVolume(volume: EdsObject) -> None: 231 | """Formats volumes of memory cards in a camera. 232 | 233 | :param EdsObject volume: The volume item. 234 | :raises EdsError: Any of the sdk errors. 235 | """ 236 | ... 237 | 238 | 239 | def GetDirectoryItemInfo(dir_item: EdsObject) -> Dict[str, Any]: 240 | """Gets information about the directory or file objects 241 | on the memory card (volume) in a remote camera. 242 | 243 | :param EdsObject dir_item: The reference of the directory item. 244 | :raises EdsError: Any of the sdk errors. 245 | :return Dict[str, Any]: Information of the directory item. 246 | """ 247 | ... 248 | 249 | 250 | def DeleteDirectoryItem(dir_item: EdsObject) -> None: 251 | """Deletes a camera folder or file. 252 | If folders with subdirectories are designated, all files are deleted 253 | except protected files. 254 | EdsDirectoryItem objects deleted by means of this API are implicitly 255 | released by the EDSDK. 256 | 257 | :param EdsObject dir_item: The item to be deleted. 258 | :raises EdsError: Any of the sdk errors. 259 | """ 260 | ... 261 | 262 | 263 | def Download(dir_item: EdsObject, size: int, stream: EdsObject) -> None: 264 | """Downloads a file on a remote camera 265 | (in the camera memory or on a memory card) to the host computer. 266 | The downloaded file is sent directly to a file stream created in advance. 267 | When dividing the file being retrieved, call this API repeatedly. 268 | Also in this case, make the data block size a multiple of 512 (bytes), 269 | excluding the final block. 270 | :param EdsObject dir_item: The directory item. 271 | :param int size: The number of bytes to be retrieved. 272 | :param EdsObject stream: The stream. 273 | :raises EdsError: Any of the sdk errors. 274 | """ 275 | ... 276 | 277 | 278 | def DownloadCancel(dir_item: EdsObject) -> None: 279 | """Must be executed when downloading of a directory item is canceled. 280 | Calling this API makes the camera cancel file transmission. 281 | It also releases resources. 282 | This operation need not be executed when using EdsDownloadThumbnail. 283 | 284 | :param EdsObject dir_item: The directory item. 285 | :raises EdsError: Any of the sdk errors. 286 | """ 287 | ... 288 | 289 | 290 | def DownloadComplete(dir_item: EdsObject) -> None: 291 | """Must be called when downloading of directory items is complete. 292 | Executing this API makes the camera 293 | recognize that file transmission is complete. 294 | This operation need not be executed when using EdsDownloadThumbnail. 295 | 296 | :param EdsObject dir_item: The directory item. 297 | :raises EdsError: Any of the sdk errors. 298 | """ 299 | ... 300 | 301 | 302 | def DownloadThumbnail(dir_item: EdsObject) -> EdsObject: 303 | """Extracts and downloads thumbnail information from image files in a camera. 304 | Thumbnail information in the camera's image files is downloaded 305 | to the host computer. 306 | Downloaded thumbnails are sent directly to a file stream created in advance. 307 | 308 | :param EdsObject dir_item: The directory item. 309 | :raises EdsError: Any of the sdk errors. 310 | :return EdsObject: The stream. 311 | """ 312 | ... 313 | 314 | 315 | def GetAttribute(dir_item: EdsObject) -> int: 316 | """Gets attributes of files on a camera. 317 | 318 | :param EdsObject dir_item: The directory item. 319 | :raises EdsError: Any of the sdk errors. 320 | :return int: Indicates the file attributes. 321 | As for the file attributes, OR values of the value defined 322 | by enum FileAttributes can be retrieved. Thus, when 323 | determining the file attributes, you must check 324 | if an attribute flag is set for target attributes. 325 | """ 326 | ... 327 | 328 | 329 | def SetAttribute(dir_item: EdsObject, file_attributes: int) -> int: 330 | """Changes attributes of files on a camera. 331 | 332 | :param EdsObject dir_item: The directory item. 333 | :param int file_attributes: Indicates the file attributes. 334 | As for the file attributes, OR values of the value 335 | defined by enum FileAttributes can be retrieved. 336 | :raises EdsError: Any of the sdk errors. 337 | """ 338 | ... 339 | 340 | 341 | def CreateFileStream( 342 | filename: str, disposition: FileCreateDisposition, access: Access 343 | ) -> EdsObject: 344 | """Creates a new file on a host computer (or opens an existing file) 345 | and creates a file stream for access to the file. 346 | If a new file is designated before executing this API, 347 | the file is actually created following the timing of writing 348 | by means of EdsWrite or the like with respect to an open stream. 349 | 350 | :param str filename: the file name. 351 | :param FileCreateDisposition disposition: Action to take on files that exist or not. 352 | :param Access access: Access to the stream (reading, writing, or both). 353 | :raises EdsError: Any of the sdk errors. 354 | :return EdsObject: The reference of the stream. 355 | """ 356 | ... 357 | 358 | 359 | def CreateMemoryStream(buffer_size: int) -> EdsObject: 360 | """Creates a stream in the memory of a host computer. 361 | In the case of writing in excess of the allocated buffer size, 362 | the memory is automatically extended. 363 | 364 | :param int buffer_size: The number of bytes of the memory to allocate. 365 | :raises EdsError: Any of the sdk errors. 366 | :return EdsObject: The stream. 367 | """ 368 | ... 369 | 370 | 371 | def CreateMemoryStreamFromPointer( 372 | buffer: Union[bytes, bytearray, memoryview] 373 | ) -> EdsObject: 374 | """Creates a stream from the memory buffer you prepare. 375 | Unlike the buffer size of streams created by means of EdsCreateMemoryStream, 376 | the buffer size you prepare for streams created this way does not expand. 377 | 378 | :param Union[bytes, bytearray, memoryview] buffer: The buffer. 379 | :raises EdsError: Any of the sdk errors. 380 | :return EdsObject: The stream. 381 | """ 382 | ... 383 | 384 | 385 | def GetPosition(stream_or_image: EdsObject) -> int: 386 | """Gets the current read or write position of the stream 387 | (that is, the file position indicator). 388 | 389 | :param EdsObject stream_or_image: The stream or image. 390 | :raises EdsError: Any of the sdk errors. 391 | :return int: The current stream pointer. 392 | """ 393 | ... 394 | 395 | 396 | def GetLength(stream_or_image: EdsObject) -> int: 397 | """Gets the stream size. 398 | 399 | :param EdsObject stream_or_image: The stream or image. 400 | :raises EdsError: Any of the sdk errors. 401 | :return int: The length of the stream. 402 | """ 403 | ... 404 | 405 | 406 | def CopyData( 407 | in_stream_or_image: EdsObject, write_size: int, out_stream_or_image: EdsObject 408 | ) -> None: 409 | """Copies data from the copy source stream to the copy destination stream. 410 | The read or write position of the data to copy is determined from 411 | the current file read or write position of the respective stream. 412 | After this API is executed, the read or write positions of the copy source 413 | and copy destination streams are moved an amount corresponding to 414 | inWriteSize in the positive direction. 415 | 416 | :param EdsObject in_stream_or_image: The input stream or image. 417 | :param int write_size: The number of bytes to copy. 418 | :param EdsObject out_stream_or_image: The output stream or image. 419 | """ 420 | ... 421 | 422 | 423 | def SetProgressCallback( 424 | camera: EdsObject, callback: Callable, option: ProgressOption 425 | ) -> None: 426 | """Register a progress callback function. 427 | An event is received as notification of progress during processing that 428 | takes a relatively long time, such as downloading files from a 429 | remote camera. 430 | If you register the callback function, the EDSDK calls the callback 431 | function during execution or on completion of the following APIs. 432 | This timing can be used in updating on-screen progress bars, for example. 433 | 434 | :param EdsObject stream_or_image: the stream or image object. 435 | :param Callable callback: The callback function. 436 | Expected signature (percent: int, cancel: bool) -> int. 437 | :param ProgressOption option: The option about progress is specified. 438 | Must be one of the following values. 439 | ProgressOption.Done 440 | When processing is completed,a callback function 441 | is called only once. 442 | ProgressOption.Periodically 443 | A callback function is performed periodically. 444 | :raises EdsError: Any of the sdk errors. 445 | """ 446 | ... 447 | 448 | 449 | def CreateImageRef(stream: EdsObject) -> EdsObject: 450 | """Creates an image object from an image file. 451 | Without modification, stream objects cannot be worked with as images. 452 | Thus, when extracting images from image files, 453 | you must use this API to create image objects. 454 | The image object created this way can be used to get image information 455 | (such as the height and width, number of color components, and 456 | resolution), thumbnail image data, and the image data itself. 457 | 458 | :param EdsObject stream: The stream. 459 | :raises EdsError: Any of the sdk errors. 460 | :return EdsObject: The image. 461 | """ 462 | ... 463 | 464 | 465 | def GetImageInfo(image: EdsObject, image_source: ImageSource) -> Dict[str, Any]: 466 | """Gets image information from a designated image object. 467 | Here, image information means the image width and height, 468 | number of color components, resolution, and effective image area. 469 | 470 | :param EdsObject image: The image. 471 | :param ImageSource image_source: Of the various image data items in the image file, 472 | designate the type of image data representing the 473 | information you want to get. Designate the image as 474 | defined in Enum ImageSource. 475 | ImageSource.FullView 476 | The image itself (a full-sized image) 477 | ImageSource.Thumbnail 478 | A thumbnail image 479 | ImageSource.Preview 480 | A preview image 481 | :raises EdsError: Any of the sdk errors. 482 | :return Dict[str, Any]: Stores the image data information designated 483 | in inImageSource. 484 | """ 485 | ... 486 | 487 | 488 | def GetImage( 489 | image: EdsObject, image_source: ImageSource, image_type: TargetImageType, 490 | source_rect: Dict[str, Dict[str, int]], dest_size: Dict[str, int] 491 | ) -> EdsObject: 492 | """Gets designated image data from an image file, in the form of a 493 | designated rectangle. 494 | Returns uncompressed results for JPEGs and processed results 495 | in the designated pixel order (RGB, Top-down BGR, and so on) for 496 | RAW images. 497 | Additionally, by designating the input/output rectangle, 498 | it is possible to get reduced, enlarged, or partial images. 499 | However, because images corresponding to the designated output rectangle 500 | are always returned by the SDK, the SDK does not take the aspect 501 | ratio into account. 502 | To maintain the aspect ratio, you must keep the aspect ratio in mind 503 | when designating the rectangle. 504 | 505 | :param EdsObject image: The image for which to get the image data. 506 | :param ImageSource image_source: Designate the type of image data to get 507 | from the image file (thumbnail, preview, and so on). 508 | :param TargetImageType image_type: Designate the output image type. Because 509 | the output format of GetImage may only be RGB, only 510 | TargetImageType.RGB or TargetImageType.RGB16 can be designed. 511 | However, image types exceeding the resolution of 512 | image_source cannot be designated. 513 | :param Dict[str, Dict[str, int]] source_rect: Designate the coordinates 514 | and size of the rectangle to be retrieved from the source image. 515 | :param Dict[str, int] dest_size: Designate the rectangle size for output. 516 | :raises EdsError: Any of the sdk errors. 517 | :return EdsObject: the memory or file stream for output of the image. 518 | """ 519 | ... 520 | 521 | 522 | def CreateEvfImageRef(stream: EdsObject) -> EdsObject: 523 | """Creates an object used to get the live view image data set. 524 | 525 | :param EdsObject stream: The stream which opened to get EVF JPEG image. 526 | :raises EdsError: Any of the sdk errors. 527 | :return EdsObject: The EVFData. 528 | """ 529 | ... 530 | 531 | 532 | def DownloadEvfImage(camera: EdsObject, evf_image: EdsObject) -> None: 533 | """"Downloads the live view image data set for a camera currently in live view mode. 534 | Live view can be started by using the property ID:PropID.Evf_OutputDevice and 535 | data:OutputDevice.PC to call SetPropertyData. 536 | In addition to image data, information such as zoom, focus position, and histogram data 537 | is included in the image data set. Image data is saved in a stream maintained by EdsEvfImageRef. 538 | GetPropertyData can be used to get information such as the zoom, focus position, etc. 539 | Although the information of the zoom and focus position can be obtained from EvfImageRef, 540 | settings are applied to EdsCameraRef. 541 | 542 | :param EdsObject camera: The camera. 543 | :param EdsObject evf_image: The EVFData. 544 | :raises EdsError: Any of the sdk errors. 545 | """ 546 | ... 547 | 548 | 549 | def SetCameraAddedHandler(callback: Callable) -> None: 550 | """Registers a callback function for when a camera is detected. 551 | 552 | :param Callable callback: the callback called when a camera is connected. 553 | Expected signature () -> int. 554 | :raises EdsError: Any of the sdk errors. 555 | """ 556 | ... 557 | 558 | 559 | def SetPropertyEventHandler( 560 | camera: EdsObject, event: PropertyEvent, callback: Callable 561 | ) -> None: 562 | """Registers a callback function for receiving status 563 | change notification events for property states on a camera. 564 | 565 | :param EdsObject camera: the camera object. 566 | :param PropertyEvent event: the event to be supplemented. 567 | To designate all events, use PropertyEvent.All. 568 | :param Callable callback: the callback for receiving events. 569 | Expected signature (event: StateEvent, prop_id: PropID, param: int) -> int. 570 | :raises EdsError: Any of the sdk errors. 571 | """ 572 | ... 573 | 574 | 575 | def SetObjectEventHandler( 576 | camera: EdsObject, event: ObjectEvent, callback: Callable 577 | ) -> None: 578 | """Registers a callback function for receiving status 579 | change notification events for objects on a remote camera. 580 | Here, object means volumes representing memory cards, files and directories, 581 | tand shot images stored in memory, in particular. 582 | 583 | :param EdsObject camera: the camera object. 584 | :param ObjectEvent event: the event to be supplemented. 585 | To designate all events, use ObjectEvent.All. 586 | :param Callable callback: the callback for receiving events. 587 | Expected signature (event: ObjectEvent, obj_ref: EdsObject) -> int. 588 | :raises EdsError: Any of the sdk errors. 589 | """ 590 | ... 591 | 592 | 593 | def SetCameraStateEventHandler( 594 | camera: EdsObject, event: StateEvent, callback: Callable 595 | ) -> None: 596 | """Registers a callback function for receiving status 597 | change notification events for property states on a camera 598 | 599 | :param EdsObject camera: the camera object. 600 | :param StateEvent event: the event to be supplemented. 601 | To designate all events, use StateEvent.All. 602 | :param Callable callback: the callback for receiving the events. 603 | Expected signature (event: StateEvent, event_data: int) -> int. 604 | :raises EdsError: Any of the sdk errors. 605 | """ 606 | ... 607 | 608 | 609 | def GetEvent() -> None: 610 | """This function acquires an event. 611 | In console application, please call this function regularly to acquire 612 | the event from a camera. 613 | :raises EdsError: Any of the sdk errors. 614 | """ 615 | ... 616 | -------------------------------------------------------------------------------- /edsdk/constants/__init__.py: -------------------------------------------------------------------------------- 1 | from .generic import * 2 | from .commands import * 3 | from .properties import * 4 | -------------------------------------------------------------------------------- /edsdk/constants/commands.py: -------------------------------------------------------------------------------- 1 | from enum import IntEnum 2 | 3 | 4 | class CameraCommand(IntEnum): 5 | TakePicture = 0x00000000 6 | ExtendShutDownTimer = 0x00000001 7 | BulbStart = 0x00000002 8 | BulbEnd = 0x00000003 9 | DoEvfAf = 0x00000102 10 | DriveLensEvf = 0x00000103 11 | DoClickWBEvf = 0x00000104 12 | MovieSelectSwON = 0x00000107 # Change to Movie Mode 13 | MovieSelectSwOFF = 0x00000108 # Change to Still Image Mode 14 | 15 | PressShutterButton = 0x00000004 16 | RequestRollPitchLevel = 0x00000109 17 | DrivePowerZoom = 0x0000010d 18 | SetRemoteShootingMode = 0x0000010f 19 | RequestSensorCleaning = 0x00000112 20 | 21 | 22 | # CameraCommand.DoEvfAf 23 | class EvFAf(IntEnum): 24 | Off = 0 25 | On = 1 26 | 27 | 28 | # CameraCommand.DriveLensEvf 29 | class DriveLens(IntEnum): 30 | Near1 = 0x00000001 31 | Near2 = 0x00000002 32 | Near3 = 0x00000003 33 | Far1 = 0x00008001 34 | Far2 = 0x00008002 35 | Far3 = 0x00008003 36 | 37 | 38 | # CameraCommand.PressShutterButton 39 | class ShutterButton(IntEnum): 40 | OFF = 0x00000000 41 | Halfway = 0x00000001 42 | Completely = 0x00000003 43 | Halfway_NonAF = 0x00010001 44 | Completely_NonAF = 0x00010003 45 | 46 | 47 | # CameraCommand.SetRemoteShootingMode 48 | class DcRemoteShootingMode(IntEnum): 49 | Stop = 0 50 | Start = 1 51 | 52 | 53 | # CameraCommand.DrivePowerZoom 54 | class DrivePowerZoom(IntEnum): 55 | Stop = 0x00000000 56 | LimitOff_Wide = 0x00000001 57 | LimitOff_Tele = 0x00000002 58 | LimitOn_Wide = 0x00000011 59 | LimitOn_Tele = 0x00000012 60 | 61 | 62 | # CameraCommand.RequestSensorCleaning 63 | class RequestSensorCleaning(IntEnum): 64 | CleanNextTurnOn_Off = 0x00 65 | CleanNow = 0x01 # Note:Camera will shut down after execution. 66 | 67 | 68 | # CameraCommand.SetModeDialDisable 69 | class SetModeDialDisable(IntEnum): 70 | Cancel = 0x00 71 | ModeDialDisable = 0x01 72 | 73 | 74 | # CameraCommand.RequestRollPitchLevel 75 | class RequestRollPitchLevel(IntEnum): 76 | Start = 0 77 | Stop = 1 78 | -------------------------------------------------------------------------------- /edsdk/constants/generic.py: -------------------------------------------------------------------------------- 1 | from enum import IntEnum 2 | 3 | 4 | class DataType(IntEnum): 5 | Unknown = 0 6 | Bool = 1 7 | String = 2 8 | Int8 = 3 9 | UInt8 = 6 10 | Int16 = 4 11 | UInt16 = 7 12 | Int32 = 8 13 | UInt32 = 9 14 | Int64 = 10 15 | UInt64 = 11 16 | Float = 12 17 | Double = 13 18 | ByteBlock = 14 19 | Rational = 20 20 | Point = 21 21 | Rect = 22 22 | Time = 23 23 | 24 | Bool_Array = 30 25 | Int8_Array = 31 26 | Int16_Array = 32 27 | Int32_Array = 33 28 | UInt8_Array = 34 29 | UInt16_Array = 35 30 | UInt32_Array = 36 31 | Rational_Array = 37 32 | 33 | FocusInfo = 101 34 | PictureStyleDesc = 102 35 | 36 | 37 | class CameraStatusCommand(IntEnum): 38 | UILock = 0x00000000 39 | UIUnLock = 0x00000001 40 | EnterDirectTransfer = 0x00000002 41 | ExitDirectTransfer = 0x00000003 42 | 43 | 44 | class PropertyEvent(IntEnum): 45 | All = 0x00000100 46 | PropertyChanged = 0x00000101 47 | PropertyDescChanged = 0x00000102 48 | 49 | 50 | class ObjectEvent(IntEnum): 51 | All = 0x00000200 52 | VolumeInfoChanged = 0x00000201 53 | VolumeUpdateItems = 0x00000202 54 | FolderUpdateItems = 0x00000203 55 | DirItemCreated = 0x00000204 56 | DirItemRemoved = 0x00000205 57 | DirItemInfoChanged = 0x00000206 58 | DirItemContentChanged = 0x00000207 59 | DirItemRequestTransfer = 0x00000208 60 | DirItemRequestTransferDT = 0x00000209 61 | DirItemCancelTransferDT = 0x0000020a 62 | VolumeAdded = 0x0000020c 63 | VolumeRemoved = 0x0000020d 64 | 65 | 66 | class StateEvent(IntEnum): 67 | All = 0x00000300 68 | Shutdown = 0x00000301 69 | JobStatusChanged = 0x00000302 70 | WillSoonShutDown = 0x00000303 71 | ShutDownTimerUpdate = 0x00000304 72 | CaptureError = 0x00000305 73 | InternalError = 0x00000306 74 | AfResult = 0x00000309 75 | BulbExposureTime = 0x00000310 76 | PowerZoomInfoChanged = 0x00000311 77 | 78 | 79 | class Access(IntEnum): 80 | Read = 0 81 | Write = 1 82 | ReadWrite = 2 83 | Error = 0xFFFFFFFF 84 | 85 | 86 | class FileCreateDisposition(IntEnum): 87 | CreateNew = 0 88 | CreateAlways = 1 89 | OpenExisting = 2 90 | OpenAlways = 3 91 | TruncateExisting = 4 92 | 93 | 94 | class ImageSource(IntEnum): 95 | FullView = 0 96 | Thumbnail = 1 97 | Preview = 2 98 | RAWThumbnail = 3 99 | RAWFullView = 4 100 | 101 | 102 | class TargetImageType(IntEnum): 103 | Unknown = 0x00000000 104 | Jpeg = 0x00000001 105 | TIFF = 0x00000007 106 | TIFF16 = 0x00000008 107 | RGB = 0x00000009 108 | RGB16 = 0x0000000A 109 | DIB = 0x0000000B 110 | 111 | 112 | class ProgressOption(IntEnum): 113 | NoReport = 0 114 | Done = 1 115 | Periodically = 2 116 | 117 | 118 | class FileAttributes(IntEnum): 119 | Normal = 0x00000000 120 | ReadOnly = 0x00000001 121 | Hidden = 0x00000002 122 | System = 0x00000004 123 | Archive = 0x00000020 124 | 125 | 126 | class ObjectFormat(IntEnum): 127 | Jpeg = 0x3801 128 | CR2 = 0xB103 129 | MP4 = 0xB982 130 | CR3 = 0xB108 131 | HEIF_CODE = 0xB10B 132 | 133 | 134 | class StorageType(IntEnum): 135 | Non = 0 136 | CF = 1 137 | SD = 2 138 | HD = 4 139 | CFast = 5 140 | CFe = 7 141 | 142 | 143 | class DeviceSubType(IntEnum): 144 | CanonPTPCamera = 1 145 | CanonPTP_IPCamera = 2 146 | 147 | 148 | # What is this used for? 149 | class BatteryLevel2(IntEnum): 150 | Empty = 0 151 | Low = 9 152 | Half = 49 153 | Normal = 80 154 | Hi = 69 155 | Quarter = 19 156 | Error = 0 157 | BCLevel = 0 158 | AC = 0xFFFFFFFF 159 | Unknown = 0xFFFFFFFE 160 | 161 | 162 | # What is this used for? 163 | class TransferOption(IntEnum): 164 | ByDirectTransfer = 1 165 | ByRelease = 2 166 | ToDesktop = 0x00000100 167 | 168 | 169 | # What is this used for? 170 | class StroboMode(IntEnum): 171 | Internal = 0 172 | ExternalETTL = 1 173 | ExternalATTL = 2 174 | ExternalTTL = 3 175 | ExternalAuto = 4 176 | ExternalManual = 5 177 | Manual = 6 178 | 179 | 180 | # What is this used for? 181 | class ETTL2Mode(IntEnum): 182 | Evaluative = 0 183 | Average = 1 184 | -------------------------------------------------------------------------------- /edsdk/constants/properties.py: -------------------------------------------------------------------------------- 1 | from enum import IntEnum 2 | 3 | 4 | class PropID(IntEnum): 5 | # Camera Properties 6 | Unknown = 0x0000ffff 7 | 8 | ProductName = 0x00000002 9 | OwnerName = 0x00000004 10 | MakerName = 0x00000005 11 | DateTime = 0x00000006 12 | FirmwareVersion = 0x00000007 13 | BatteryLevel = 0x00000008 14 | SaveTo = 0x0000000b 15 | CurrentStorage = 0x0000000c 16 | CurrentFolder = 0x0000000d 17 | 18 | BatteryQuality = 0x00000010 19 | 20 | BodyIDEx = 0x00000015 21 | HDDirectoryStructure = 0x00000020 22 | 23 | TempStatus = 0x01000415 24 | 25 | # Image Properties 26 | ImageQuality = 0x00000100 27 | Orientation = 0x00000102 28 | ICCProfile = 0x00000103 29 | FocusInfo = 0x00000104 30 | WhiteBalance = 0x00000106 31 | ColorTemperature = 0x00000107 32 | WhiteBalanceShift = 0x00000108 33 | ColorSpace = 0x0000010d 34 | PictureStyle = 0x00000114 35 | PictureStyleDesc = 0x00000115 36 | PictureStyleCaption = 0x00000200 37 | 38 | # GPS Properties 39 | GPSVersionID = 0x00000800 40 | GPSLatitudeRef = 0x00000801 41 | GPSLatitude = 0x00000802 42 | GPSLongitudeRef = 0x00000803 43 | GPSLongitude = 0x00000804 44 | GPSAltitudeRef = 0x00000805 45 | GPSAltitude = 0x00000806 46 | GPSTimeStamp = 0x00000807 47 | GPSSatellites = 0x00000808 48 | GPSStatus = 0x00000809 49 | GPSMapDatum = 0x00000812 50 | GPSDateStamp = 0x0000081D 51 | 52 | # Capture Properties 53 | AEMode = 0x00000400 54 | DriveMode = 0x00000401 55 | ISOSpeed = 0x00000402 56 | MeteringMode = 0x00000403 57 | AFMode = 0x00000404 58 | Av = 0x00000405 59 | Tv = 0x00000406 60 | ExposureCompensation = 0x00000407 61 | FocalLength = 0x00000409 62 | AvailableShots = 0x0000040a 63 | Bracket = 0x0000040b 64 | WhiteBalanceBracket = 0x0000040c 65 | LensName = 0x0000040d 66 | AEBracket = 0x0000040e 67 | FEBracket = 0x0000040f 68 | ISOBracket = 0x00000410 69 | NoiseReduction = 0x00000411 70 | FlashOn = 0x00000412 71 | RedEye = 0x00000413 72 | FlashMode = 0x00000414 73 | LensStatus = 0x00000416 74 | Artist = 0x00000418 75 | Copyright = 0x00000419 76 | AEModeSelect = 0x00000436 77 | PowerZoom_Speed = 0x00000444 78 | 79 | # EVF Properties 80 | Evf_OutputDevice = 0x00000500 81 | Evf_Mode = 0x00000501 82 | Evf_WhiteBalance = 0x00000502 83 | Evf_ColorTemperature = 0x00000503 84 | Evf_DepthOfFieldPreview = 0x00000504 85 | 86 | # EVF Image Data Properties 87 | Evf_Zoom = 0x00000507 88 | Evf_ZoomPosition = 0x00000508 89 | Evf_Histogram = 0x0000050A 90 | Evf_ImagePosition = 0x0000050B 91 | Evf_HistogramStatus = 0x0000050C 92 | Evf_AFMode = 0x0000050E 93 | 94 | Record = 0x00000510 95 | 96 | Evf_HistogramY = 0x00000515 97 | Evf_HistogramR = 0x00000516 98 | Evf_HistogramG = 0x00000517 99 | Evf_HistogramB = 0x00000518 100 | 101 | Evf_CoordinateSystem = 0x00000540 102 | Evf_ZoomRect = 0x00000541 103 | Evf_ImageClipRect = 0x00000545 104 | 105 | Evf_PowerZoom_CurPosition = 0x00000550 106 | Evf_PowerZoom_MaxPosition = 0x00000551 107 | Evf_PowerZoom_MinPosition = 0x00000552 108 | 109 | # Limited Properties 110 | UTCTime = 0x01000016 111 | TimeZone = 0x01000017 112 | SummerTimeSetting = 0x01000018 113 | ManualWhiteBalanceData = 0x01000204 114 | MirrorLockUpState = 0x01000421 115 | FixedMovie = 0x01000422 116 | MovieParam = 0x01000423 117 | Aspect = 0x01000431 118 | MirrorUpSetting = 0x01000438 119 | AutoPowerOffSetting = 0x0100045e 120 | Evf_ClickWBCoeffs = 0x01000506 121 | EVF_RollingPitching = 0x01000544 122 | Evf_VisibleRect = 0x01000546 123 | StillMovieDivideSetting = 0x01000470 124 | CardExtension = 0x01000471 125 | MovieCardExtension = 0x01000472 126 | StillCurrentMedia = 0x01000473 127 | MovieCurrentMedia = 0x01000474 128 | FocusShiftSetting = 0x01000457 129 | MovieHFRSetting = 0x0100045d 130 | 131 | # DC Properties 132 | DC_Zoom = 0x00000600 133 | DC_Strobe = 0x00000601 134 | LensBarrelStatus = 0x00000605 135 | 136 | 137 | # PropID.TimeZone 138 | class TimeZone(IntEnum): 139 | None_ = 0x0000 140 | ChathamIslands = 0x0001 141 | Wellington = 0x0002 142 | SolomonIsland = 0x0003 143 | Syndney = 0x0004 144 | Adeladie = 0x0005 145 | Tokyo = 0x0006 146 | HongKong = 0x0007 147 | Bangkok = 0x0008 148 | Yangon = 0x0009 149 | Dacca = 0x000A 150 | Kathmandu = 0x000B 151 | Delhi = 0x000C 152 | Karachi = 0x000D 153 | Kabul = 0x000E 154 | Dubai = 0x000F 155 | Tehran = 0x0010 156 | Moscow = 0x0011 157 | Cairo = 0x0012 158 | Paris = 0x0013 159 | London = 0x0014 160 | Azores = 0x0015 161 | FernandoDeNoronha = 0x0016 162 | SaoPaulo = 0x0017 163 | Newfoundland = 0x0018 164 | Santiago = 0x0019 165 | Caracas = 0x001A 166 | NewYork = 0x001B 167 | Chicago = 0x001C 168 | Denver = 0x001D 169 | LosAngeles = 0x001E 170 | Anchorage = 0x001F 171 | Honolulu = 0x0020 172 | Samoa = 0x0021 173 | Riyadh = 0x0022 174 | Manaus = 0x0023 175 | UTC = 0x0100 176 | 177 | 178 | # PropID.SummerTimeSetting 179 | class SummerTimeSetting(IntEnum): 180 | Off = 0 181 | On = 1 182 | 183 | 184 | # PropID.BatteryQuality 185 | class BatteryQuality(IntEnum): 186 | Low = 0 187 | Half = 1 188 | HI = 2 189 | Full = 3 190 | 191 | 192 | # PropID.SaveTo 193 | class SaveTo(IntEnum): 194 | Camera = 1 195 | Host = 2 196 | Both = Camera | Host 197 | 198 | 199 | # PropID.FocusInfo 200 | class AFFrameValid(IntEnum): 201 | Invalid = 0 202 | Valid = 1 203 | 204 | 205 | class AFFrameSelected(IntEnum): 206 | Unselected = 0 207 | Selected = 1 208 | 209 | 210 | class AFFrameJustFocus(IntEnum): 211 | Standby = 0 212 | FocusingSuccess = 1 213 | FocusingFailure = 2 214 | ServoAFStopping = 3 215 | ServoAFRunning = 4 216 | 217 | 218 | # PropID.ImageQuality 219 | class ImageType(IntEnum): 220 | Unknown = 0x00000000 221 | Jpeg = 0x00000001 222 | CRW = 0x00000002 223 | RAW = 0x00000004 224 | CR2 = 0x00000006 225 | HEIF = 0x00000008 226 | 227 | 228 | class ImageSize(IntEnum): 229 | Large = 0 230 | Middle = 1 231 | Small = 2 232 | Middle1 = 5 233 | Middle2 = 6 234 | Small1 = 14 235 | Small2 = 15 236 | Small3 = 16 237 | Unknown = 0xffffffff 238 | 239 | 240 | class CompressQuality(IntEnum): 241 | Normal = 2 242 | Fine = 3 243 | Lossless = 4 244 | SuperFine = 5 245 | Unknown = 0xffffffff 246 | 247 | 248 | class ImageQuality(IntEnum): 249 | # Jpeg Only 250 | LJ = 0x0010ff0f # Jpeg Large 251 | MJ = 0x0110ff0f # Jpeg Middle 252 | M1J = 0x0510ff0f # Jpeg Middle1 253 | M2J = 0x0610ff0f # Jpeg Middle2 254 | SJ = 0x0210ff0f # Jpeg Small 255 | S1J = 0x0e10ff0f # Jpeg Small1 256 | S2J = 0x0f10ff0f # Jpeg Small2 257 | LJF = 0x0013ff0f # Jpeg Large Fine 258 | LJN = 0x0012ff0f # Jpeg Large Normal 259 | MJF = 0x0113ff0f # Jpeg Middle Fine 260 | MJN = 0x0112ff0f # Jpeg Middle Normal 261 | SJF = 0x0213ff0f # Jpeg Small Fine 262 | SJN = 0x0212ff0f # Jpeg Small Normal 263 | S1JF = 0x0E13ff0f # Jpeg Small1 Fine 264 | S1JN = 0x0E12ff0f # Jpeg Small1 Normal 265 | S2JF = 0x0F13ff0f # Jpeg Small2 266 | S3JF = 0x1013ff0f # Jpeg Small3 267 | 268 | # RAW + Jpeg 269 | LR = 0x0064ff0f # RAW 270 | LRLJF = 0x00640013 # RAW + Jpeg Large Fine 271 | LRLJN = 0x00640012 # RAW + Jpeg Large Normal 272 | LRMJF = 0x00640113 # RAW + Jpeg Middle Fine 273 | LRMJN = 0x00640112 # RAW + Jpeg Middle Normal 274 | LRSJF = 0x00640213 # RAW + Jpeg Small Fine 275 | LRSJN = 0x00640212 # RAW + Jpeg Small Normal 276 | LRS1JF = 0x00640E13 # RAW + Jpeg Small1 Fine 277 | LRS1JN = 0x00640E12 # RAW + Jpeg Small1 Normal 278 | LRS2JF = 0x00640F13 # RAW + Jpeg Small2 279 | LRS3JF = 0x00641013 # RAW + Jpeg Small3 280 | 281 | LRLJ = 0x00640010 # RAW + Jpeg Large 282 | LRMJ = 0x00640110 # RAW + Jpeg Middle 283 | LRM1J = 0x00640510 # RAW + Jpeg Middle1 284 | LRM2J = 0x00640610 # RAW + Jpeg Middle2 285 | LRSJ = 0x00640210 # RAW + Jpeg Small 286 | LRS1J = 0x00640e10 # RAW + Jpeg Small1 287 | LRS2J = 0x00640f10 # RAW + Jpeg Small2 288 | 289 | # MRAW(SRAW1) + Jpeg 290 | MR = 0x0164ff0f # MRAW(SRAW1) 291 | MRLJF = 0x01640013 # MRAW(SRAW1) + Jpeg Large Fine 292 | MRLJN = 0x01640012 # MRAW(SRAW1) + Jpeg Large Normal 293 | MRMJF = 0x01640113 # MRAW(SRAW1) + Jpeg Middle Fine 294 | MRMJN = 0x01640112 # MRAW(SRAW1) + Jpeg Middle Normal 295 | MRSJF = 0x01640213 # MRAW(SRAW1) + Jpeg Small Fine 296 | MRSJN = 0x01640212 # MRAW(SRAW1) + Jpeg Small Normal 297 | MRS1JF = 0x01640E13 # MRAW(SRAW1) + Jpeg Small1 Fine 298 | MRS1JN = 0x01640E12 # MRAW(SRAW1) + Jpeg Small1 Normal 299 | MRS2JF = 0x01640F13 # MRAW(SRAW1) + Jpeg Small2 300 | MRS3JF = 0x01641013 # MRAW(SRAW1) + Jpeg Small3 301 | 302 | MRLJ = 0x01640010 # MRAW(SRAW1) + Jpeg Large 303 | MRM1J = 0x01640510 # MRAW(SRAW1) + Jpeg Middle1 304 | MRM2J = 0x01640610 # MRAW(SRAW1) + Jpeg Middle2 305 | MRSJ = 0x01640210 # MRAW(SRAW1) + Jpeg Small 306 | 307 | # SRAW(SRAW2) + Jpeg 308 | SR = 0x0264ff0f # SRAW(SRAW2) 309 | SRLJF = 0x02640013 # SRAW(SRAW2) + Jpeg Large Fine 310 | SRLJN = 0x02640012 # SRAW(SRAW2) + Jpeg Large Normal 311 | SRMJF = 0x02640113 # SRAW(SRAW2) + Jpeg Middle Fine 312 | SRMJN = 0x02640112 # SRAW(SRAW2) + Jpeg Middle Normal 313 | SRSJF = 0x02640213 # SRAW(SRAW2) + Jpeg Small Fine 314 | SRSJN = 0x02640212 # SRAW(SRAW2) + Jpeg Small Normal 315 | SRS1JF = 0x02640E13 # SRAW(SRAW2) + Jpeg Small1 Fine 316 | SRS1JN = 0x02640E12 # SRAW(SRAW2) + Jpeg Small1 Normal 317 | SRS2JF = 0x02640F13 # SRAW(SRAW2) + Jpeg Small2 318 | SRS3JF = 0x02641013 # SRAW(SRAW2) + Jpeg Small3 319 | 320 | SRLJ = 0x02640010 # SRAW(SRAW2) + Jpeg Large 321 | SRM1J = 0x02640510 # SRAW(SRAW2) + Jpeg Middle1 322 | SRM2J = 0x02640610 # SRAW(SRAW2) + Jpeg Middle2 323 | SRSJ = 0x02640210 # SRAW(SRAW2) + Jpeg Small 324 | 325 | # CRAW + Jpeg 326 | CR = 0x0063ff0f # CRAW 327 | CRLJF = 0x00630013 # CRAW + Jpeg Large Fine 328 | CRMJF = 0x00630113 # CRAW + Jpeg Middle Fine 329 | CRM1JF = 0x00630513 # CRAW + Jpeg Middle1 Fine 330 | CRM2JF = 0x00630613 # CRAW + Jpeg Middle2 Fine 331 | CRSJF = 0x00630213 # CRAW + Jpeg Small Fine 332 | CRS1JF = 0x00630E13 # CRAW + Jpeg Small1 Fine 333 | CRS2JF = 0x00630F13 # CRAW + Jpeg Small2 Fine 334 | CRS3JF = 0x00631013 # CRAW + Jpeg Small3 Fine 335 | CRLJN = 0x00630012 # CRAW + Jpeg Large Normal 336 | CRMJN = 0x00630112 # CRAW + Jpeg Middle Normal 337 | CRM1JN = 0x00630512 # CRAW + Jpeg Middle1 Normal 338 | CRM2JN = 0x00630612 # CRAW + Jpeg Middle2 Normal 339 | CRSJN = 0x00630212 # CRAW + Jpeg Small Normal 340 | CRS1JN = 0x00630E12 # CRAW + Jpeg Small1 Normal 341 | 342 | CRLJ = 0x00630010 # CRAW + Jpeg Large 343 | CRMJ = 0x00630110 # CRAW + Jpeg Middle 344 | CRM1J = 0x00630510 # CRAW + Jpeg Middle1 345 | CRM2J = 0x00630610 # CRAW + Jpeg Middle2 346 | CRSJ = 0x00630210 # CRAW + Jpeg Small 347 | CRS1J = 0x00630e10 # CRAW + Jpeg Small1 348 | CRS2J = 0x00630f10 # CRAW + Jpeg Small2 349 | 350 | # HEIF 351 | HEIFL = 0x0080ff0f # HEIF Large 352 | RHEIFL = 0x00640080 # RAW + HEIF Large 353 | CRHEIFL = 0x00630080 # CRAW + HEIF Large 354 | 355 | HEIFLF = 0x0083ff0f # HEIF Large Fine 356 | HEIFLN = 0x0082ff0f # HEIF Large Normal 357 | HEIFMF = 0x0183ff0f # HEIF Middle Fine 358 | HEIFMN = 0x0182ff0f # HEIF Middle Normal 359 | HEIFS1F = 0x0e83ff0f # HEIF Small1 Fine 360 | HEIFS1N = 0x0e82ff0f # HEIF Small1 Normal 361 | HEIFS2F = 0x0f83ff0f # HEIF Small2 Fine 362 | RHEIFLF = 0x00640083 # RAW + HEIF Large Fine 363 | RHEIFLN = 0x00640082 # RAW + HEIF Large Normal 364 | RHEIFMF = 0x00640183 # RAW + HEIF Middle Fine 365 | RHEIFMN = 0x00640182 # RAW + HEIF Middle Normal 366 | RHEIFS1F = 0x00640e83 # RAW + HEIF Small1 Fine 367 | RHEIFS1N = 0x00640e82 # RAW + HEIF Small1 Normal 368 | RHEIFS2F = 0x00640f83 # RAW + HEIF Small2 Fine 369 | CRHEIFLF = 0x00630083 # CRAW + HEIF Large Fine 370 | CRHEIFLN = 0x00630082 # CRAW + HEIF Large Normal 371 | CRHEIFMF = 0x00630183 # CRAW + HEIF Middle Fine 372 | CRHEIFMN = 0x00630182 # CRAW + HEIF Middle Normal 373 | CRHEIFS1F = 0x00630e83 # CRAW + HEIF Small1 Fine 374 | CRHEIFS1N = 0x00630e82 # CRAW + HEIF Small1 Normal 375 | CRHEIFS2F = 0x00630f83 # CRAW + HEIF Small2 Fine 376 | 377 | Unknown = 0xffffffff 378 | 379 | 380 | # PropID.AEMode 381 | class AEMode(IntEnum): 382 | Program = 0x00, 383 | Tv = 0x01 384 | Av = 0x02 385 | Manual = 0x03 386 | Bulb = 0x04 387 | A_DEP = 0x05 388 | DEP = 0x06 389 | Custom = 0x07 390 | Lock = 0x08 391 | Green = 0x09 392 | NightPortrait = 0x0A 393 | Sports = 0x0B 394 | Portrait = 0x0C 395 | Landscape = 0x0D 396 | Closeup = 0x0E 397 | FlashOff = 0x0F 398 | CreativeAuto = 0x13 399 | Movie = 0x14 400 | PhotoInMovie = 0x15 401 | SceneIntelligentAuto = 0x16 402 | SCN = 0x19 403 | NightScenes = 0x17 404 | BacklitScenes = 0x18 405 | Children = 0x1A 406 | Food = 0x1B 407 | CandlelightPortraits = 0x1C 408 | CreativeFilter = 0x1D 409 | RoughMonoChrome = 0x1E 410 | SoftFocus = 0x1F 411 | ToyCamera = 0x20 412 | Fisheye = 0x21 413 | WaterColor = 0x22 414 | Miniature = 0x23 415 | Hdr_Standard = 0x24 416 | Hdr_Vivid = 0x25 417 | Hdr_Bold = 0x26 418 | Hdr_Embossed = 0x27 419 | Movie_Fantasy = 0x28 420 | Movie_Old = 0x29 421 | Movie_Memory = 0x2A 422 | DirectMono= 0x2B 423 | Movie_Mini = 0x2C 424 | PanningAssist = 0x2D 425 | GroupPhoto = 0x2E 426 | Myself = 0x32 427 | PlusMovieAuto = 0x33 428 | SmoothSkin = 0x34 429 | Panorama = 0x35 430 | Silent = 0x36 431 | Flexible = 0x37 432 | OilPainting = 0x38 433 | Fireworks = 0x39 434 | StarPortrait = 0x3A 435 | StarNightscape = 0x3B 436 | StarTrails = 0x3C 437 | StarTimelapseMovie = 0x3D 438 | BackgroundBlur = 0x3E 439 | VideoBlog = 0x3F 440 | Unknown = 0xffffffff 441 | 442 | 443 | # PropID.AEModeSelect 444 | class AEModeSelect(IntEnum): 445 | Custom1 = 0x07 446 | Custom2 = 0x10 447 | Custom3 = 0x11 448 | SCNSpecialScene = 0x19 449 | 450 | 451 | # PropID.DriveMode 452 | class DriveMode(IntEnum): 453 | SingleShooting = 0x00000000 454 | ContinuousShooting = 0x00000001 455 | Video = 0x00000002 456 | HighSpeedContinuous = 0x00000004 457 | LowSpeedContinuous = 0x00000005 458 | SingleSilentShooting = 0x00000006 459 | SelfTimerContinuous = 0x00000007 460 | SelfTimer10Sec = 0x00000010 461 | SelfTimer2Sec = 0x00000011 462 | SuperHighSpeed14Fps = 0x00000012 463 | SilentSingleShooting = 0x00000013 464 | SilentContinuousShooting = 0x00000014 465 | SilentHighSpeedContinuous = 0x00000015 466 | SilentLowSpeedContinuous = 0x00000016 467 | 468 | 469 | # PropID.ISOSpeed 470 | class ISOSpeedCamera(IntEnum): 471 | ISOAuto = 0x00000000 472 | ISO6 = 0x00000028 473 | ISO12 = 0x00000030 474 | ISO25 = 0x00000038 475 | ISO50 = 0x00000040 476 | ISO100 = 0x00000048 477 | ISO125 = 0x0000004b 478 | ISO160 = 0x0000004d 479 | ISO200 = 0x00000050 480 | ISO250 = 0x00000053 481 | ISO320 = 0x00000055 482 | ISO400 = 0x00000058 483 | ISO500 = 0x0000005b 484 | ISO640 = 0x0000005d 485 | ISO800 = 0x00000060 486 | ISO1000 = 0x00000063 487 | ISO1250 = 0x00000065 488 | ISO1600 = 0x00000068 489 | ISO2000 = 0x0000006b 490 | ISO2500 = 0x0000006d 491 | ISO3200 = 0x00000070 492 | ISO4000 = 0x00000073 493 | ISO5000 = 0x00000075 494 | ISO6400 = 0x00000078 495 | ISO8000 = 0x0000007b 496 | ISO10000 = 0x0000007d 497 | ISO12800 = 0x00000080 498 | ISO16000 = 0x00000083 499 | ISO20000 = 0x00000085 500 | ISO25600 = 0x00000088 501 | ISO32000 = 0x0000008b 502 | ISO40000 = 0x0000008d 503 | ISO51200 = 0x00000090 504 | ISO64000 = 0x00000093 505 | ISO80000 = 0x00000095 506 | ISO102400 = 0x00000098 507 | ISO204800 = 0x000000a0 508 | ISO409600 = 0x000000a8 509 | ISO819200 = 0x000000b0 510 | NotValid_NoSettingsChanges = 0xffffffff 511 | 512 | 513 | class ISOSpeedImage(IntEnum): 514 | ISO50 = 50 515 | ISO100 = 100 516 | ISO200 = 200 517 | ISO400 = 400 518 | ISO800 = 800 519 | ISO1600 = 1600 520 | ISO3200 = 3200 521 | ISO6400 = 6400 522 | ISO12800 = 12800 523 | ISO25600 = 25600 524 | ISO51200 = 51200 525 | ISO102400 = 102400 526 | 527 | 528 | # PropID.MeteringMode 529 | class MeteringMode(IntEnum): 530 | StopMetering = 1 531 | EvaluativeMetering = 3 532 | PartialMetering = 4 533 | CenterWeightedAveragingMetering = 5 534 | NotValid_NoSettingsChanges = 0xFFFFFFFF 535 | 536 | 537 | # PropID.AFMode 538 | class AFMode(IntEnum): 539 | OneShotAF = 0 540 | AIServoAF_ServoAF = 1 541 | AIFocusAF = 2 542 | ManualFocus = 3 # ReadOnly 543 | NotValid_NoSettingsChanges = 0xffffffff 544 | 545 | 546 | # PropID.Av 547 | Av = { 548 | 0x08: "1", 0x0B: "1.1", 0x0C: "1.2", 0x0D: "1.2 (1/3)", 0x10: "1.4", 549 | 0x13: "1.6", 0x14: "1.8", 0x15: "1.8 (1/3)", 0x18: "2", 0x1B: "2.2", 550 | 0x1C: "2.5", 0x1D: "2.5 (1/3)", 0x20: "2.8", 0x23: "3.2", 0x85: "3.4", 551 | 0x24: "3.5", 0x25: "3.5 (1/3)", 0x28: "4", 0x2B: "4.5", 0x2C: "4.5", 552 | 0x2D: "5.0", 0x30: "5.6", 0x33: "6.3", 0x34: "6.7", 0x35: "7.1", 0x38: "8", 553 | 0x3B: "9", 0x3C: "9.5", 0x3D: "10", 0x40: "11", 0x43: "13 (1/3)", 554 | 0x44: "13", 0x45: "14", 0x48: "16", 0x4B: "18", 0x4C: "19", 0x4D: "20", 555 | 0x50: "22", 0x53: "25", 0x54: "27", 0x55: "29", 0x58: "32", 0x5B: "36", 556 | 0x5C: "38", 0x5D: "40", 0x60: "45", 0x63: "51", 0x64: "54", 0x65: "57", 557 | 0x68: "64", 0x6B: "72", 0x6C: "76", 0x6D: "80", 0x70: "91", 558 | 0xffffffff: "Not valid/no settings changes", 559 | } 560 | 561 | 562 | # PropID.Tv 563 | Tv = { 564 | 0x0C: "Bulb", 565 | 0x10: "30\"", 0x13: "25\"", 0x14: "20\"", 0x15: "20\" (1/3)", 566 | 0x18: "15\"", 0x1B: "13\"", 0x1C: "10\"", 0x1D: "10\" (1/3)", 567 | 0x20: "8\"", 0x23: "6\" (1/3)", 0x24: "6\"", 0x25: "5\"", 0x28: "4\"", 568 | 0x2B: "3\"2", 0x2C: "3", 0x2D: "2\"5", 0x30: "2", 0x33: "1\"6", 569 | 0x34: "1\"5", 0x35: "1\"3", 0x38: "1", 0x3B: "0\"8", 0x3C: "0\"7", 570 | 0x3D: "0\"6", 0x40: "0\"5", 0x43: "0\"4", 0x44: "0\"3", 0x45: "0\"3 (1/3)", 571 | 0x48: "1/4", 0x4B: "1/5", 0x4C: "1/6", 0x4D: "1/6 (1/3)", 0x50: "1/8", 572 | 0x53: "1/10 (1/3)", 0x54: "1/10", 0x55: "1/13", 0x58: "1/15", 573 | 0x5B: "1/20 (1/3)", 0x5C: "1/20", 0x5D: "1/25", 0x60: "1/30", 574 | 0x63: "1/40", 0x64: "1/45", 0x65: "1/50", 0x68: "1/60", 0x6B: "1/80", 575 | 0x6C: "1/90", 0x6D: "1/100", 0x70: "1/125", 0x73: "1/160", 0x74: "1/180", 576 | 0x75: "1/200", 0x78: "1/250", 0x7B: "1/320", 0x7C: "1/350", 0x7D: "1/400", 577 | 0x80: "1/500", 0x83: "1/640", 0x84: "1/750", 0x85: "1/800", 0x88: "1/1000", 578 | 0x8B: "1/1250", 0x8C: "1/1500", 0x8D: "1/1600", 0x90: "1/2000", 579 | 0x93: "1/2500", 0x94: "1/3000", 0x95: "1/3200", 0x98: "1/4000", 580 | 0x9B: "1/5000", 0x9C: "1/6000", 0x9D: "1/6400", 0xA0: "1/8000", 581 | 0xA3: "1/10000", 0xA5: "1/12800", 0xA8: "1/16000", 582 | 0xffffffff: "Not valid/no settings changes" 583 | } 584 | 585 | 586 | # PropID.ExposureCompensation 587 | ExposureComponensation = { 588 | 0x28: "+5", 589 | 0x25: "+4 2/3", 590 | 0x24: "+4 1/2", 591 | 0x23: "+4 1/3", 592 | 0x20: "+4", 593 | 0x1D: "+3 2/3", 594 | 0x1C: "+3 1/2", 595 | 0x1B: "+3 1/3", 596 | 0x18: "+3", 597 | 0x15: "+2 2/3", 598 | 0x14: "+2 1/2", 599 | 0x13: "+2 1/3", 600 | 0x10: "+2", 601 | 0x0D: "+1 2/3", 602 | 0x0C: "+1 1/2", 603 | 0x0B: "+1 1/3", 604 | 0x08: "+1", 605 | 0x05: "+2/3", 606 | 0x04: "+1/2", 607 | 0x03: "+1/3", 608 | 0x00: "0", 609 | 0xFD: "-1/3", 610 | 0xFC: "-1/2", 611 | 0xFB: "-2/3", 612 | 0xF8: "-1", 613 | 0xF5: "-1 1/3", 614 | 0xF4: "-1 1/2", 615 | 0xF3: "-1 2/3", 616 | 0xF0: "-2", 617 | 0xED: "-2 1/3", 618 | 0xEC: "-2 1/2", 619 | 0xEB: "-2 2/3", 620 | 0xE8: "-3", 621 | 0xE5: "-3 1/3", 622 | 0xE4: "-3 1/2", 623 | 0xE3: "-3 2/3", 624 | 0xE0: "-4", 625 | 0xDD: "-4 1/3", 626 | 0xDC: "-4 1/2", 627 | 0xDB: "-4 2/3", 628 | 0xD8: "-5", 629 | 0xffffffff: "Not valid/no settings changes" 630 | } 631 | 632 | 633 | # PropID.Bracket 634 | class Bracket(IntEnum): 635 | AEB = 0x01 636 | ISOB = 0x02 637 | WBB = 0x04 638 | FEB = 0x08 639 | Unknown = 0xffffffff 640 | 641 | 642 | # PropID.WhiteBalanceBracket 643 | class WhiteBalanceBracketMode(IntEnum): 644 | Off = 0 645 | ModeAB = 1 646 | ModeGM = 2 647 | NotSupported = 0xFFFFFFFF 648 | 649 | 650 | # PropID.WhiteBalance 651 | class WhiteBalance(IntEnum): 652 | Auto = 0 653 | Daylight = 1 654 | Cloudy = 2 655 | Tungsten = 3 656 | Fluorescent = 4 657 | Strobe = 5 658 | WhitePaper = 6 659 | Shade = 8 660 | ColorTemp = 9 661 | PCSet1 = 10 662 | PCSet2 = 11 663 | PCSet3 = 12 664 | WhitePaper2 = 15 665 | WhitePaper3 = 16 666 | WhitePaper4 = 18 667 | WhitePaper5 = 19 668 | PCSet4 = 20 669 | PCSet5 = 21 670 | AwbWhite = 23 671 | Click = -1 672 | Pasted = -2 673 | 674 | 675 | # PropID.ColorSpace 676 | class ColorSpace(IntEnum): 677 | sRGB = 1 678 | AdobeRGB = 2 679 | Unknown = 0xffffffff 680 | 681 | 682 | # PropID.PictureStyle 683 | class PictureStyle(IntEnum): 684 | Standard = 0x0081 685 | Portrait = 0x0082 686 | Landscape = 0x0083 687 | Neutral = 0x0084 688 | Faithful = 0x0085 689 | Monochrome = 0x0086 690 | Auto = 0x0087 691 | FineDetail = 0x0088 692 | User1 = 0x0021 693 | User2 = 0x0022 694 | User3 = 0x0023 695 | PC1 = 0x0041 696 | PC2 = 0x0042 697 | PC3 = 0x0043 698 | 699 | 700 | # PropID.FlashOn 701 | class FlashOn(IntEnum): 702 | NoFlash = 0 703 | Flash = 1 704 | 705 | 706 | # PropID.FlashMode 707 | class FlashModeType(IntEnum): 708 | None_ = 0 709 | Internal = 1 710 | ExternalETTL = 2 711 | ExternalATTL = 3 712 | InvalidValue = 0xFFFFFFFF 713 | 714 | 715 | class FlashModeSynchroTiming(IntEnum): 716 | FirstCurtain = 0 717 | SecondCurtain = 1 718 | InvalidValue = 0xFFFFFFFF 719 | 720 | 721 | # PropID.RedEye 722 | class RedEye(IntEnum): 723 | Off = 0 724 | On = 1 725 | InvalidValue = 0xFFFFFFFF 726 | 727 | 728 | # PropID.NoiseReduction 729 | class NoiseReduction(IntEnum): 730 | Off = 0 731 | On1 = 1 732 | On2 = 2 733 | On = 3 734 | Auto = 4 735 | 736 | 737 | # PropID.LensStatus 738 | class LensStatus(IntEnum): 739 | NotAttached = 0 740 | Attached = 1 741 | 742 | 743 | # PropID.DC_Strobe 744 | class DcStrobe(IntEnum): 745 | Auto = 0 746 | On = 1 747 | Slowsynchro = 2 748 | Off = 3 749 | 750 | 751 | # PropID.LensBarrelStatus 752 | class DcLensBarrelState(IntEnum): 753 | Inner = 0 754 | Outer = 1 755 | 756 | 757 | # PropID.Evf_OutputDevice 758 | class EvfOutputDevice(IntEnum): 759 | TFT = 1 760 | PC = 2 761 | PC_Small = 8 762 | 763 | 764 | # PropID.Evf_Mode 765 | class EvfMode(IntEnum): 766 | Disable = 0 767 | Enable = 1 768 | 769 | 770 | # PropID.Evf_DepthOfFieldPreview 771 | class EvfDepthOfFieldPreview(IntEnum): 772 | OFF = 0x00000000 773 | ON = 0x00000001 774 | 775 | 776 | # PropID.Evf_Zoom 777 | class EvfZoom(IntEnum): 778 | Fit = 1 779 | x5 = 5 780 | x10 = 10 781 | 782 | 783 | # PropID.Evf_HistogramStatus 784 | class EvfHistogramStatus(IntEnum): 785 | Hide = 0 786 | Normal = 1 787 | Grayout = 2 788 | 789 | 790 | # PropID.Evf_AFMode 791 | class EvfAFMode(IntEnum): 792 | Quick = 0x00 793 | Live = 0x01 794 | LiveFace = 0x02 795 | LiveMulti = 0x03 796 | LiveZone = 0x04 797 | LiveSingleExpandCross = 0x05 798 | LiveSingleExpandSurround = 0x06 799 | LiveZoneLargeH = 0x07 800 | LiveZoneLargeV = 0x08 801 | LiveCatchAF = 0x09 802 | LiveSpotAF = 0x0a 803 | FlexibleZone1 = 0x0b 804 | FlexibleZone2 = 0x0c 805 | FlexibleZone3 = 0x0d 806 | WholeArea = 0x0e 807 | 808 | 809 | # PropID.Record 810 | class Record(IntEnum): 811 | EndMovieShooting = 0 812 | BeginMovieShooting = 4 813 | 814 | 815 | # PropID.MirrorUpSetting 816 | class MirrorUpSetting(IntEnum): 817 | Off = 0 818 | On = 1 819 | 820 | 821 | # PropID.MirrorLockUpState 822 | class MirrorLockUpState(IntEnum): 823 | Disable = 0 824 | Enable = 1 825 | DuringShooting = 2 826 | 827 | 828 | # PropID.FixedMovie 829 | class FixedMovie(IntEnum): 830 | MovideModeDisabled = 0x00 831 | MovieModeEnabled = 0x01 832 | 833 | 834 | # PropID.MovieParam 835 | MovieParam = { 836 | 0x00000200: "1920x1080 23.98fps", 837 | 0x00000210: "1920x1080 23.98fps For editing(ALL-I)", 838 | 0x00000230: "1920x1080 23.98fps Standard(IPB)", 839 | 0x00000300: "1920x1080 24.00fps", 840 | 0x00000310: "1920x1080 24.00fps For editing(ALL-I)", 841 | 0x00000330: "1920x1080 24.00fps Standard(IPB)", 842 | 0x00000400: "1920x1080 25.00fps", 843 | 0x00000410: "1920x1080 25.00fps For editing(ALL-I)", 844 | 0x00000430: "1920x1080 25.00fps Standard(IPB)", 845 | 0x00000500: "1920x1080 29.97fps", 846 | 0x00000510: "1920x1080 29.97fps For editing(ALL-I)", 847 | 0x00000530: "1920x1080 29.97fps Standard(IPB)", 848 | 0x00000610: "1920x1080 50.00fps For editing(ALL-I)", 849 | 0x00000630: "1920x1080 50.00fps Standard(IPB)", 850 | 0x00000710: "1920x1080 59.94fps For editing(ALL-I)", 851 | 0x00000730: "1920x1080 59.94fps Standard(IPB)", 852 | 0x00001210: "1920x1080 23.98fps For editing(ALL-I)", 853 | 0x00001230: "1920x1080 23.98fps Standard(IPB)", 854 | 0x00001231: "1920x1080 23.98fps Light(IPB)", 855 | 0x00001310: "1920x1080 24.00fps For editing(ALL-I)", 856 | 0x00001330: "1920x1080 24.00fps Standard(IPB)", 857 | 0x00001331: "1920x1080 24.00fps Light(IPB)", 858 | 0x00001410: "1920x1080 25.00fps For editing(ALL-I)", 859 | 0x00001430: "1920x1080 25.00fps Standard(IPB)", 860 | 0x00001431: "1920x1080 25.00fps Light(IPB)", 861 | 0x00001510: "1920x1080 29.97fps For editing(ALL-I)", 862 | 0x00001530: "1920x1080 29.97fps Standard(IPB)", 863 | 0x00001531: "1920x1080 29.97fps Light(IPB)", 864 | 0x00001610: "1920x1080 50.00fps For editing(ALL-I)", 865 | 0x00001630: "1920x1080 50.00fps Standard(IPB)", 866 | 0x00001631: "1920x1080 50.00fps Light(IPB)", 867 | 0x00001710: "1920x1080 59.94fps For editing(ALL-I)", 868 | 0x00001730: "1920x1080 59.94fps Standard(IPB)", 869 | 0x00001810: "1920x1080 100.0fps For editing(ALL-I)", 870 | 0x00001731: "1920x1080 59.94fps Light(IPB)", 871 | 0x00001910: "1920x1080 119.9fps For editing(ALL-I)", 872 | 0x00010600: "1280x720 50.00fps", 873 | 0x00010700: "1280x720 59.94fps", 874 | 0x00010810: "1280x720 100.0fps For editing(ALL-I)", 875 | 0x00010910: "1280x720 119.9fps For editing(ALL-I)", 876 | 0x00011430: "1280x720 25.00fps Standard(IPB)", 877 | 0x00011431: "1280x720 50.00fps Standard(IPB)", 878 | 0x00011530: "1280x720 29.97fps Standard(IPB)", 879 | 0x00011531: "1280x720 29.97fps Light(IPB)", 880 | 0x00011610: "1280x720 50.00fps For editing(ALL-I)", 881 | 0x00011630: "1280x720 50.00fps Standard(IPB)", 882 | 0x00011710: "1280x720 59.94fps For editing(ALL-I)", 883 | 0x00011730: "1280x720 59.94fps Standard(IPB)", 884 | 0x00011810: "1280x720 100.0fps For editing(ALL-I)", 885 | 0x00011830: "1280x720 100.0fps Standard(IPB)", 886 | 0x00011910: "1280x720 119.9fps For editing(ALL-I)", 887 | 0x00011930: "1280x720 119.9fps Standard(IPB)", 888 | 0x00020400: "640x480 25.00fps", 889 | 0x00020500: "640x480 29.97fps", 890 | 0x00030240: "4096x2160 23.98fps Motion JPEG", 891 | 0x00030340: "4096x2160 24.00fps Motion JPEG", 892 | 0x00030440: "4096x2160 25.00fps Motion JPEG", 893 | 0x00030540: "4096x2160 29.97fps Motion JPEG", 894 | 0x00031210: "4096x2160 23.98fps For editing(ALL-I)", 895 | 0x00031230: "4096x2160 23.98fps Standard(IPB)", 896 | 0x00031231: "4096x2160 23.98fps Light(IPB)", 897 | 0x00031310: "4096x2160 24.00fps For editing(ALL-I)", 898 | 0x00031330: "4096x2160 24.00fps Standard(IPB)", 899 | 0x00031331: "4096x2160 24.00fps Light(IPB)", 900 | 0x00031410: "4096x2160 25.00fps For editing(ALL-I)", 901 | 0x00031430: "4096x2160 25.00fps Standard(IPB)", 902 | 0x00031431: "4096x2160 25.00fps Light(IPB)", 903 | 0x00031510: "4096x2160 29.97fps For editing(ALL-I)", 904 | 0x00031530: "4096x2160 29.97fps Standard(IPB)", 905 | 0x00031531: "4096x2160 29.97fps Light(IPB)", 906 | 0x00031610: "4096x2160 50.00fps For editing(ALL-I)", 907 | 0x00031630: "4096x2160 50.00fps Standard(IPB)", 908 | 0x00031631: "4096x2160 50.00fps Light(IPB)", 909 | 0x00031710: "4096x2160 59.94fps For editing(ALL-I)", 910 | 0x00031730: "4096x2160 59.94fps Standard(IPB)", 911 | 0x00031731: "4096x2160 59.94fps Light(IPB)", 912 | 0x00031810: "4096x2160 100.0fps For editing(ALL-I)", 913 | 0x00031910: "4096x2160 119.9fps For editing(ALL-I)", 914 | 0x00051210: "3840x2160 23.98fps For editing(ALL-I)", 915 | 0x00051230: "3840x2160 23.98fps Standard(IPB)", 916 | 0x00051231: "3840x2160 23.98fps Light(IPB)", 917 | 0x00051310: "3840x2160 24.00fps For editing(ALL-I)", 918 | 0x00051330: "3840x2160 24.00fps Standard(IPB)", 919 | 0x00051331: "3840x2160 24.00fps Light (IPB)", 920 | 0x00051410: "3840x2160 25.00fps For editing(ALL-I)", 921 | 0x00051430: "3840x2160 25.00fps Standard(IPB)", 922 | 0x00051431: "3840x2160 25.00fps Light(IPB)", 923 | 0x00051510: "3840x2160 29.97fps For editing(ALL-I)", 924 | 0x00051530: "3840x2160 29.97fps Standard(IPB)", 925 | 0x00051531: "3840x2160 29.97fps Light(IPB)", 926 | 0x00051610: "3840x2160 50.00fps For editing(ALL-I)", 927 | 0x00051630: "3840x2160 50.00fps Standard(IPB)", 928 | 0x00051631: "3840x2160 50.00fps Light(IPB)", 929 | 0x00051710: "3840x2160 59.94fps For editing(ALL-I)", 930 | 0x00051730: "3840x2160 59.94fps Standard(IPB)", 931 | 0x00051731: "3840x2160 59.94fps Light(IPB)", 932 | 0x00051810: "3840x2160 100.0fps For editing(ALL-I)", 933 | 0x00051910: "3840x2160 119.9fps For editing(ALL-I)", 934 | 0x00081210: "8192x4320 23.98fps For editing(ALL-I)", 935 | 0x00081230: "8192x4320 23.98fps Standard(IPB)", 936 | 0x00081231: "8192x4320 23.98fps Light(IPB)", 937 | 0x00081310: "8192x4320 24.00fps For editing(ALL-I)", 938 | 0x00081330: "8192x4320 24.00fps Standard(IPB)", 939 | 0x00081331: "8192x4320 24.00fps Light(IPB)", 940 | 0x00081410: "8192x4320 25.00fps For editing(ALL-I)", 941 | 0x00081430: "8192x4320 25.00fps Standard(IPB)", 942 | 0x00081431: "8192x4320 25.00fps Light(IPB)", 943 | 0x00081510: "8192x4320 29.97fps For editing(ALL-I)", 944 | 0x00081530: "8192x4320 29.97fps Standard(IPB)", 945 | 0x00081531: "8192x4320 29.97fps Light(IPB)", 946 | 0x00091210: "7680x4320 23.98fps For editing(ALL-I)", 947 | 0x00091230: "7680x4320 23.98fps Standard(IPB)", 948 | 0x00091231: "7680x4320 23.98fps Light(IPB)", 949 | 0x00091330: "7680x4320 24.00fps Standard(IPB)", 950 | 0x00091331: "7680x4320 24.00fps Light(IPB)", 951 | 0x00091410: "7680x4320 25.00fps For editing(ALL-I)", 952 | 0x00091430: "7680x4320 25.00fps Standard(IPB)", 953 | 0x00091431: "7680x4320 25.00fps Light(IPB)", 954 | 0x00091510: "7680x4320 29.97fps For editing(ALL-I)", 955 | 0x00091530: "7680x4320 29.97fps Standard(IPB)", 956 | 0x00091531: "7680x4320 29.97fps Light(IPB)", 957 | 0x000a3270: "23.98fps (RAW)", 958 | 0x000a3271: "23.98fps Light(RAW)", 959 | 0x000a3370: "24.00fps (RAW)", 960 | 0x000a3371: "24.00fps Light(RAW)", 961 | 0x000a3470: "25.00fps (RAW)", 962 | 0x000a3471: "25.00fps Light(RAW)", 963 | 0x000a3570: "29.97fps (RAW)", 964 | 0x000a3571: "29.97fps Light(RAW)", 965 | 0x000a3670: "50.00fps (RAW)", 966 | 0x000a3770: "59.94fps (RAW)", 967 | 0x08001210: "1920x1080 23.98fps For editing(ALL-I)Crop", 968 | 0x08001230: "1920x1080 23.98fps Standard(IPB)Crop", 969 | 0x08001231: "1920x1080 23.98fps Light(IPB)Crop", 970 | 0x08001410: "1920x1080 24.00fps For editing(ALL-I)Crop", 971 | 0x08001430: "1920x1080 24.00fps Standard(IPB)Crop", 972 | 0x08001431: "1920x1080 25.00fps For editing(ALL-I)Crop", 973 | 0x08001510: "1920x1080 25.00fps Standard(IPB)Crop", 974 | 0x08001530: "1920x1080 29.97fps For editing(ALL-I)Crop", 975 | 0x08001531: "1920x1080 29.94fps Standard(IPB)Crop", 976 | 0x08001610: "1920x1080 50.00fps For editing(ALL-I)Crop", 977 | 0x08001630: "1920x1080 50.00fps Standard(IPB)Crop", 978 | 0x08001631: "1920x1080 50.00fps Light(IPB)Crop", 979 | 0x08001710: "1920x1080 59.94fps For editing(ALL-I)Crop", 980 | 0x08001730: "1920x1080 59.94fps Standard(IPB)Crop", 981 | 0x08001731: "1920x1080 59.94fps Light(IPB)Crop", 982 | 0x08001810: "1920x1080 100.0fps For editing(ALL-I)Crop", 983 | 0x08001910: "1920x1080 119.9fps For editing(ALL-I)Crop", 984 | 0x08031210: "4096x2160 23.98fps For editing(ALL-I) Crop", 985 | 0x08031230: "4096x2160 23.98fps Standard(IPB)Crop", 986 | 0x08031231: "4096x2160 23.98fps Light(IPB)Crop", 987 | 0x08031310: "4096x2160 24.00fps For editing(ALL-I)Crop", 988 | 0x08031330: "4096x2160 24.00fps Standard(IPB)Crop", 989 | 0x08031331: "4096x2160 24.00fps Light(IPB)Crop", 990 | 0x08031410: "4096x2160 25.00fps For editing(ALL-I)Crop", 991 | 0x08031430: "4096x2160 25.00fps Standard(IPB)Crop", 992 | 0x08031431: "4096x2160 25.00fps Light(IPB)Crop", 993 | 0x08031510: "4096x2160 29.97fps For editing(ALL-I)Crop", 994 | 0x08031530: "4096x2160 29.94fps Standard(IPB)Crop", 995 | 0x08031531: "4096x2160 29.94fps Light(IPB)Crop", 996 | 0x08031610: "4096x2160 50.00fps For editing(ALL-I)Crop", 997 | 0x08031630: "4096x2160 50.00fps Standard(IPB)Crop", 998 | 0x08031631: "4096x2160 50.00fps Light(IPB)Crop", 999 | 0x08031710: "4096x2160 59.94fps For editing(ALL-I)Crop", 1000 | 0x08031730: "4096x2160 59.94fps Standard(IPB)Crop", 1001 | 0x08031731: "4096x2160 59.94fps Light(IPB)Crop", 1002 | 0x08051210: "3840x2160 23.98fps For editing(ALL-I)", 1003 | 0x08051230: "3840x2160 23.98fps Standard(IPB)", 1004 | 0x08051231: "3840x2160 23.98fps Light(IPB)", 1005 | 0x08051410: "3840x2160 25.00fps For editing(ALL-I)", 1006 | 0x08051430: "3840x2160 25.00fps Standard(IPB)", 1007 | 0x08051431: "3840x2160 25.00fps Light (IPB)", 1008 | 0x08051510: "3840x2160 29.97fps For editing(ALL-I)", 1009 | 0x08051530: "3840x2160 29.97fps Standard(IPB)", 1010 | 0x08051531: "3840x2160 29.97fps Light(IPB)", 1011 | 0x08051610: "3840x2160 50.00fps For editing(ALL-I)", 1012 | 0x08051630: "3840x2160 50.00fps Standard(IPB)", 1013 | 0x08051631: "3840x2160 50.00fps Light (IPB)", 1014 | 0x08051710: "3840x2160 59.94fps For editing(ALL-I)", 1015 | 0x08051730: "3840x2160 59.94fps Standard(IPB)", 1016 | 0x08051731: "3840x2160 59.94fps Light (IPB)" 1017 | } 1018 | 1019 | 1020 | # PropID.TempStatus 1021 | class TempStatus1(IntEnum): 1022 | Normal = 0x0000 1023 | RestrictionMovieRecording = 0x0002 1024 | 1025 | 1026 | class TempStatus2(IntEnum): 1027 | Normal = 0x0000 1028 | WarningIndication = 0x0001 1029 | ReduceFrameRate = 0x0002 1030 | LiveViewProhibited = 0x0003 1031 | ShootingProhibited = 0x0004 1032 | DegratedStillImageQualityWarning = 0x0005 1033 | 1034 | 1035 | # PropID.Evf_RollingPitching 1036 | class EvfRollingPitchingStatus(IntEnum): 1037 | StartingAngleInformationDisplay = 0x00 1038 | StoppingAngleInformationDisplay = 0x01 1039 | AngleInformationDetection = 0x02 1040 | 1041 | 1042 | class EvfRollingPitchingPosition(IntEnum): 1043 | Horizontal = 0x00 1044 | GripOnBottom = 0x01 1045 | GripOnTop = 0x02 1046 | UnableToDetect = 0x03 1047 | PentaprismFacingDownward_UpsideDown = 0x04 1048 | 1049 | 1050 | # PropID.AutoPowerOffSetting 1051 | class AutoPowerOffSetting(IntEnum): 1052 | Disabled = 0x00 1053 | PowerOffNow = 0xffffffff # shutdown camera 1054 | 1055 | 1056 | # PropID.Aspect 1057 | Aspect = { 1058 | 0x00000000: "Full-frame", 1059 | 0x00000001: "1:1 (aspect ratio)", 1060 | 0x00000002: "4:3 (aspect ratio)", 1061 | 0x00000007: "16:9 (aspect ratio)", 1062 | 0x0000000d: "1.6x (crop)", 1063 | } 1064 | 1065 | 1066 | # PropID.StillMovieDivideSetting 1067 | class StillMovieDivideSetting(IntEnum): 1068 | Disabled = 0x00000000 1069 | Enabled = 0x00000001 1070 | 1071 | 1072 | # PropID.CardExtension 1073 | class CardExtension(IntEnum): 1074 | Standard = 0x00000000 1075 | RecordToMultiple = 0x00000001 1076 | RecordSeparately = 0x00000002 1077 | AutoSwitchCard = 0x00000003 1078 | 1079 | 1080 | # PropID.MovieCardExtension 1081 | class MovieCardExtension(IntEnum): 1082 | Standard = 0x00000000 1083 | RecordToMultiple = 0x00000001 1084 | Slow1Raw_Slot2MP4 = 0x00000002 1085 | AutoSwitchCard = 0x00000003 1086 | 1087 | 1088 | # PropID.StillCurrentMedia 1089 | class StillCurrentMedia(IntEnum): 1090 | Slot1 = 0x00000000 1091 | Slot2 = 0x00000001 1092 | 1093 | 1094 | # PropID.MovieCurrentMedia 1095 | class MediaCurrentMedia(IntEnum): 1096 | Slot1 = 0x00000000 1097 | Slot2 = 0x00000001 1098 | 1099 | 1100 | # PropID.MovieHFRSetting 1101 | class MovieHFRSetting(IntEnum): 1102 | Disabled = 0x00000000 1103 | Enabled = 0x00000001 1104 | 1105 | 1106 | # PropID.AFEyeDetect 1107 | class AFEyeDetect(IntEnum): 1108 | Disabled = 0x00000000 1109 | Enabled = 0x00000001 1110 | 1111 | 1112 | # PropID.MovieServoAf 1113 | class MovieServoAf(IntEnum): 1114 | Disabled = 0x00000000 1115 | Enabled = 0x00000001 1116 | -------------------------------------------------------------------------------- /edsdk/edsdk_python.cpp: -------------------------------------------------------------------------------- 1 | #include "edsdk_python.h" 2 | #include "datetime.h" 3 | 4 | #include "EDSDK.h" 5 | #include "edsdk_utils.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | typedef struct { 14 | PyObject_HEAD 15 | EdsBaseRef edsObj; 16 | } PyEdsObject; 17 | 18 | 19 | static void PyEdsObject_dealloc(PyEdsObject* self) 20 | { 21 | EdsRelease(self->edsObj); 22 | Py_TYPE(self)->tp_free((PyObject*) self); 23 | } 24 | 25 | 26 | static PyTypeObject PyEdsObjectType = { 27 | PyVarObject_HEAD_INIT(NULL, 0) 28 | "edsdk.api.EdsObject", /* tp_name */ 29 | sizeof(PyEdsObject), /* tp_basicsize */ 30 | 0, /* tp_itemsize */ 31 | (destructor)PyEdsObject_dealloc,/* tp_dealloc */ 32 | 0, /* tp_print */ 33 | 0, /* tp_getattr */ 34 | 0, /* tp_setattr */ 35 | 0, /* tp_reserved */ 36 | 0, /* tp_repr */ 37 | 0, /* tp_as_number */ 38 | 0, /* tp_as_sequence */ 39 | 0, /* tp_as_mapping */ 40 | 0, /* tp_hash */ 41 | 0, /* tp_call */ 42 | 0, /* tp_str */ 43 | 0, /* tp_getattro */ 44 | 0, /* tp_setattro */ 45 | 0, /* tp_as_buffer */ 46 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 47 | PyDoc_STR("EdsObject object"),/* tp_doc */ 48 | }; 49 | 50 | 51 | static PyObject *PyEdsError; 52 | 53 | 54 | static PyObject *PyEdsError_tp_str(PyObject *self) 55 | { 56 | if (!PyObject_HasAttrString(self, "args")) { 57 | // This should never happen 58 | return PyUnicode_FromString(""); 59 | } 60 | 61 | PyObject *ret = NULL; 62 | PyObject *args = PyObject_GetAttrString(self, "args"); 63 | if (PyTuple_Size(args) < 1) { 64 | ret = PyObject_Repr(args); 65 | } 66 | else { 67 | PyObject *str = PyTuple_GetItem(args, 0); 68 | ret = PyObject_Str(str); 69 | } 70 | Py_XDECREF(args); 71 | return ret; 72 | } 73 | 74 | 75 | 76 | static PyObject *PyEdsError_getcode(PyObject *self, void *Py_UNUSED(closure)) 77 | { 78 | // Like before, but with less checks, it is okay for this function to fail 79 | PyObject *args = PyObject_GetAttrString(self, "args"); 80 | if (!args) { 81 | return NULL; 82 | } 83 | 84 | PyObject *ret = PyTuple_GetItem(args, 1); 85 | Py_XINCREF(ret); 86 | Py_XDECREF(args); 87 | return ret; 88 | } 89 | 90 | 91 | static PyGetSetDef PyEdsError_getsetters[] = { 92 | {"code", PyEdsError_getcode, NULL, NULL, NULL}, 93 | {NULL} 94 | }; 95 | 96 | 97 | bool PyCallable_CheckNumberOfParameters(PyObject* callable, const long n){ 98 | bool result = false; 99 | if(PyObject* pyCode = PyObject_GetAttrString(callable, "__code__")) { 100 | if(PyObject* pyArgCount = PyObject_GetAttrString(pyCode, "co_argcount")) { 101 | const long argcount = PyLong_AsLong(pyArgCount); 102 | if (argcount == n) { 103 | result = true; 104 | } 105 | // check if the function accepts *args 106 | else if (PyObject* pyFlags = PyObject_GetAttrString(pyCode, "co_flags")) 107 | { 108 | const long flags = PyLong_AsLong(pyFlags); 109 | // bit CO_VARARGS is set if the function uses the *arguments syntax 110 | // to accept an arbitrary number of positional arguments 111 | if (argcount < n && flags & CO_VARARGS) { 112 | result = true; 113 | } 114 | Py_DECREF(pyFlags); 115 | } 116 | Py_DECREF(pyArgCount); 117 | } 118 | Py_DECREF(pyCode); 119 | } 120 | return result; 121 | } 122 | 123 | 124 | inline PyObject* PyEdsObject_New(EdsBaseRef inObject) { 125 | if (!inObject) { 126 | PyErr_Format(PyExc_TypeError, "EdsBaseRef expected %p", inObject); 127 | } 128 | PyEdsObject* pyObj = (PyEdsObject*)PyObject_New(PyEdsObject, &PyEdsObjectType); 129 | if (!pyObj) { 130 | PyErr_Format(PyExc_MemoryError, "failed to create EdsObject"); 131 | return nullptr; 132 | } 133 | pyObj->edsObj = inObject; 134 | return (PyObject*)pyObj; 135 | } 136 | 137 | 138 | inline PyEdsObject* PyToEds(PyObject* inObject) { 139 | if (!PyObject_TypeCheck(inObject, &PyEdsObjectType)) { 140 | PyErr_Format(PyExc_ValueError, "invalid EdsObject %p", inObject); 141 | return nullptr; 142 | } 143 | return reinterpret_cast(inObject); 144 | } 145 | 146 | 147 | template 148 | inline PyObject* GetEnum(const char* moduleName, const char* enumClassName, const T enumValue){ 149 | PyObject* module = PyImport_AddModule(moduleName); 150 | if (!module) { 151 | std::cout << "failed to import module " << moduleName << std::endl; 152 | PyErr_Format(PyExc_ValueError, "failed to import module %s", moduleName); 153 | return nullptr; 154 | } 155 | PyObject* enumClass = PyObject_GetAttrString(module, enumClassName); 156 | if (!enumClass) { 157 | std::cout << "failed to get enum class " << enumClassName << std::endl; 158 | PyErr_Format(PyExc_ValueError, "failed to get enum class %s", enumClassName); 159 | return nullptr; 160 | } 161 | PyObject* enumValueObj = PyObject_CallFunction(enumClass, "(i)", enumValue); 162 | if (!enumValueObj) { 163 | std::cout << "failed to call enum class " << enumClassName << std::endl; 164 | PyErr_Format(PyExc_ValueError, "failed to get enum value %s", enumValue); 165 | Py_DECREF(enumClass); 166 | return nullptr; 167 | } 168 | 169 | Py_DECREF(enumClass); 170 | return enumValueObj; 171 | } 172 | 173 | 174 | PyDoc_STRVAR(PyEds_InitializeSDK__doc__, 175 | "Initializes the libraries.\n" 176 | "When using the EDSDK libraries, you must call this API once\n" 177 | "\tbefore using EDSDK APIs.\n\n" 178 | ":raises EdsError: Any of the sdk errors."); 179 | 180 | static PyObject* PyEds_InitializeSDK(PyObject *Py_UNUSED(self)) { 181 | unsigned long retVal(EdsInitializeSDK()); 182 | PyCheck_EDSERROR(retVal); 183 | Py_RETURN_NONE; 184 | } 185 | 186 | 187 | PyDoc_STRVAR(PyEds_TerminateSDK__doc__, 188 | "Terminates use of the libraries.\n" 189 | "This function muse be called when ending the SDK.\n" 190 | "Calling this function releases all resources allocated by the libraries.\n\n" 191 | ":raises EdsError: Any of the sdk errors."); 192 | 193 | static PyObject* PyEds_TerminateSDK(PyObject *Py_UNUSED(self)) { 194 | unsigned long retVal(EdsTerminateSDK()); 195 | PyCheck_EDSERROR(retVal); 196 | Py_RETURN_NONE; 197 | } 198 | 199 | 200 | /****************************************************************************** 201 | ******************************************************************************* 202 | // 203 | // Item-tree operating functions 204 | // 205 | ******************************************************************************* 206 | ******************************************************************************/ 207 | 208 | PyDoc_STRVAR(PyEds_GetChildCount__doc__, 209 | "Gets the number of child objects of the designated object.\n" 210 | "Example: Number of files in a directory\n\n" 211 | ":param EdsObject parent: the list object.\n" 212 | ":raises EdsError: Any of the sdk errors.\n" 213 | ":return int: Number of elements in this list."); 214 | 215 | static PyObject* PyEds_GetChildCount(PyObject *Py_UNUSED(self), PyObject *args) { 216 | PyObject* pyObj; 217 | if (!PyArg_ParseTuple(args, "O:EdsGetChildCount", &pyObj)) { 218 | return nullptr; 219 | } 220 | PyEdsObject* edsObj = PyToEds(pyObj); 221 | if (!edsObj) { 222 | return nullptr; 223 | } 224 | unsigned long childCount; 225 | unsigned long retVal(EdsGetChildCount(edsObj->edsObj, &childCount)); 226 | PyCheck_EDSERROR(retVal); 227 | return PyLong_FromUnsignedLong(childCount); 228 | } 229 | 230 | 231 | PyDoc_STRVAR(PyEds_GetChildAtIndex__doc__, 232 | "Gets an indexed child object of the designated object\n\n" 233 | ":param EdsObject parent: the list object.\n" 234 | ":param int index: The index that is passed in, is zero based.\n" 235 | ":raises EdsError: Any of the sdk errors.\n" 236 | ":return EdsObject: the child object."); 237 | 238 | static PyObject* PyEds_GetChildAtIndex(PyObject *Py_UNUSED(self), PyObject *args) { 239 | PyObject* pyObj; 240 | long index; 241 | if (!PyArg_ParseTuple(args, "Ol:EdsGetChildAtIndex", &pyObj, &index)) { 242 | return nullptr; 243 | } 244 | PyEdsObject* edsObj = PyToEds(pyObj); 245 | if (!edsObj) { 246 | return nullptr; 247 | } 248 | EdsBaseRef child; 249 | unsigned long retVal(EdsGetChildAtIndex(edsObj->edsObj, index, &child)); 250 | PyCheck_EDSERROR(retVal); 251 | return PyEdsObject_New(child); 252 | } 253 | 254 | 255 | PyDoc_STRVAR(PyEds_GetParent__doc__, 256 | "Gets the parent object of the designated object.\n\n" 257 | ":param EdsObject item: the item object.\n" 258 | ":raises EdsError: Any of the sdk errors.\n" 259 | ":return EdsObject: the parent object."); 260 | 261 | static PyObject* PyEds_GetParent(PyObject *Py_UNUSED(self), PyObject *pyChildObj) { 262 | PyEdsObject* edsObj = PyToEds(pyChildObj); 263 | if (!edsObj) { 264 | return nullptr; 265 | } 266 | EdsBaseRef parent; 267 | unsigned long retVal(EdsGetParent(edsObj->edsObj, &parent)); 268 | PyCheck_EDSERROR(retVal); 269 | return PyEdsObject_New(parent); 270 | } 271 | 272 | 273 | /****************************************************************************** 274 | ******************************************************************************* 275 | // 276 | // Property operating functions 277 | // 278 | ******************************************************************************* 279 | ******************************************************************************/ 280 | 281 | PyDoc_STRVAR(PyEds_GetPropertySize__doc__, 282 | "Gets the byte size and data type of a designated property\n" 283 | "\tfrom a camera object or image object.\n\n" 284 | ":param EdsObject camera_or_image: the item object.\n" 285 | ":param PropID property_id: The property ID.\n" 286 | ":param int param: Specify an index in case there are two or\n" 287 | "\tmore values over the same ID, defaults to 0.\n" 288 | ":raises EdsError: Any of the sdk errors.\n" 289 | ":return Tuple[DataType, int]: the property DataType and size in bytes."); 290 | 291 | static PyObject* PyEds_GetPropertySize(PyObject *Py_UNUSED(self), PyObject *args) { 292 | PyObject* pyObj; 293 | unsigned long propertyID; 294 | long param = 0; 295 | if (!PyArg_ParseTuple(args, "Okl:EdsGetPropertySize", &pyObj, &propertyID, ¶m)) { 296 | return nullptr; 297 | } 298 | PyEdsObject* edsObj = PyToEds(pyObj); 299 | if (!edsObj) { 300 | return nullptr; 301 | } 302 | EdsDataType dataType; 303 | unsigned long dataSize; 304 | 305 | unsigned long retVal(EdsGetPropertySize(edsObj->edsObj, propertyID, param, &dataType, &dataSize)); 306 | PyCheck_EDSERROR(retVal); 307 | 308 | PyObject *pyEnumVal = GetEnum("edsdk.constants", "DataType", dataType); 309 | if (pyEnumVal == nullptr) { 310 | PyErr_Clear(); 311 | std::cout << "Unknown Data Type: " << dataType << std::endl; 312 | pyEnumVal = PyLong_FromUnsignedLong(dataType); 313 | } 314 | PyObject *result = PyTuple_New(2); 315 | PyTuple_SetItem(result, 0, pyEnumVal); 316 | PyTuple_SetItem(result, 1, PyLong_FromUnsignedLong(dataSize)); 317 | 318 | return result; 319 | } 320 | 321 | 322 | PyDoc_STRVAR(PyEds_GetPropertyData__doc__, 323 | "Gets property information from the designated object.\n\n" 324 | ":param EdsObject camera_or_image: The reference of the item.\n" 325 | ":param PropID property_id: The PropertyID.\n" 326 | ":param int param: Specify an index in case there are two or\n" 327 | "\tmore values over the same ID, defaults to 0.\n" 328 | ":raises EdsError: Any of the sdk errors.\n" 329 | ":return Any: The property value."); 330 | 331 | static PyObject* PyEds_GetPropertyData(PyObject *Py_UNUSED(self), PyObject *args) { 332 | PyObject* pyObj; 333 | unsigned long propertyID; 334 | long param = 0; 335 | if (!PyArg_ParseTuple(args, "Okl:EdsGetPropertyData", &pyObj, &propertyID, ¶m)) { 336 | return nullptr; 337 | } 338 | PyEdsObject* edsObj = PyToEds(pyObj); 339 | if (!edsObj) { 340 | return nullptr; 341 | } 342 | 343 | EdsDataType dataType; 344 | unsigned long dataSize; 345 | 346 | unsigned long retVal(EdsGetPropertySize(edsObj->edsObj, propertyID, param, &dataType, &dataSize)); 347 | PyCheck_EDSERROR(retVal); 348 | 349 | PyObject *pyPropertyData = nullptr; 350 | void *propertyData = new (std::nothrow) uint8_t[dataSize]; 351 | if (propertyData == nullptr) { 352 | PyErr_NoMemory(); 353 | return nullptr; 354 | } 355 | retVal = EdsGetPropertyData(edsObj->edsObj, propertyID, param, dataSize, propertyData); 356 | PyCheck_EDSERROR(retVal); 357 | switch (dataType){ 358 | case kEdsDataType_Bool: { 359 | pyPropertyData = PyBool_FromLong(*static_cast(propertyData)); 360 | break; 361 | } 362 | case kEdsDataType_String: { 363 | pyPropertyData = PyUnicode_DecodeFSDefault(static_cast(propertyData)); 364 | break; 365 | } 366 | case kEdsDataType_UInt8: 367 | case kEdsDataType_UInt16: 368 | case kEdsDataType_UInt32: { 369 | if (propertyID == kEdsPropID_BatteryQuality) { 370 | pyPropertyData = GetEnum("edsdk.constants", "BatteryQuality", *static_cast(propertyData)); 371 | if (pyPropertyData == nullptr) { 372 | PyErr_Clear(); 373 | std::cout << "Unknown Battery Quality: " << *static_cast(propertyData) << std::endl; 374 | pyPropertyData = PyLong_FromUnsignedLong(*static_cast(propertyData)); 375 | } 376 | break; 377 | } 378 | pyPropertyData = PyLong_FromUnsignedLong(*static_cast(propertyData)); 379 | break; 380 | } 381 | case kEdsDataType_UInt64: { 382 | pyPropertyData = PyLong_FromUnsignedLongLong(*static_cast(propertyData)); 383 | break; 384 | } 385 | case kEdsDataType_Int8: 386 | case kEdsDataType_Int16: 387 | case kEdsDataType_Int32: { 388 | pyPropertyData = PyLong_FromLong(*static_cast(propertyData)); 389 | break; 390 | } 391 | case kEdsDataType_Int64: { 392 | pyPropertyData = PyLong_FromLongLong(*static_cast(propertyData)); 393 | break; 394 | } 395 | case kEdsDataType_Float: 396 | case kEdsDataType_Double: { 397 | pyPropertyData = PyFloat_FromDouble(*static_cast(propertyData)); 398 | break; 399 | } 400 | case kEdsDataType_Rational: { 401 | EdsRational *rational = static_cast(propertyData); 402 | pyPropertyData = PyTuple_New(2); 403 | PyTuple_SetItem(pyPropertyData, 0, PyLong_FromLong(rational->numerator)); 404 | PyTuple_SetItem(pyPropertyData, 1, PyLong_FromUnsignedLong(rational->denominator)); 405 | break; 406 | } 407 | case kEdsDataType_Point: { 408 | EdsPoint *point = static_cast(propertyData); 409 | pyPropertyData = PyTuple_New(2); 410 | PyTuple_SetItem(pyPropertyData, 0, PyLong_FromLong(point->x)); 411 | PyTuple_SetItem(pyPropertyData, 1, PyLong_FromLong(point->y)); 412 | break; 413 | } 414 | case kEdsDataType_Rect: { 415 | EdsRect *rect = static_cast(propertyData); 416 | pyPropertyData = PyTuple_New(4); 417 | PyTuple_SetItem(pyPropertyData, 0, PyLong_FromLong(rect->point.x)); 418 | PyTuple_SetItem(pyPropertyData, 1, PyLong_FromLong(rect->point.y)); 419 | PyTuple_SetItem(pyPropertyData, 2, PyLong_FromLong(rect->size.width)); 420 | PyTuple_SetItem(pyPropertyData, 3, PyLong_FromLong(rect->size.height)); 421 | break; 422 | } 423 | case kEdsDataType_Time: { 424 | EdsTime *t = static_cast(propertyData); 425 | PyDateTime_IMPORT; 426 | pyPropertyData = PyDateTime_FromDateAndTime( 427 | static_cast(t->year), 428 | static_cast(t->month), 429 | static_cast(t->day), 430 | static_cast(t->hour), 431 | static_cast(t->minute), 432 | static_cast(t->second), 433 | static_cast(t->milliseconds)); 434 | break; 435 | } 436 | case kEdsDataType_ByteBlock: { 437 | pyPropertyData = PyBytes_FromStringAndSize(static_cast(propertyData), dataSize); 438 | break; 439 | } 440 | case kEdsDataType_FocusInfo:{ 441 | EdsFocusInfo *focusInfo = static_cast(propertyData); 442 | pyPropertyData = PyDict_New(); 443 | PyObject *pyImageRect = PyTuple_New(4); 444 | PyTuple_SetItem(pyImageRect, 0, PyLong_FromLong(focusInfo->imageRect.point.x)); 445 | PyTuple_SetItem(pyImageRect, 1, PyLong_FromLong(focusInfo->imageRect.point.y)); 446 | PyTuple_SetItem(pyImageRect, 2, PyLong_FromLong(focusInfo->imageRect.size.width)); 447 | PyTuple_SetItem(pyImageRect, 3, PyLong_FromLong(focusInfo->imageRect.size.height)); 448 | PyObject *pyFocusPointTuple = PyTuple_New(1053); 449 | for (int i = 0; i < 1053; i++) { 450 | PyObject *pyFocusPoint = PyDict_New(); 451 | PyDict_SetItemString(pyFocusPoint, "valid", PyLong_FromUnsignedLong(focusInfo->focusPoint[i].valid)); 452 | PyDict_SetItemString(pyFocusPoint, "selected", PyLong_FromUnsignedLong(focusInfo->focusPoint[i].selected)); 453 | PyDict_SetItemString(pyFocusPoint, "justFocus", PyLong_FromUnsignedLong(focusInfo->focusPoint[i].justFocus)); 454 | 455 | PyObject *pyRect = PyTuple_New(4); 456 | PyTuple_SetItem(pyRect, 0, PyLong_FromLong(focusInfo->focusPoint[i].rect.point.x)); 457 | PyTuple_SetItem(pyRect, 1, PyLong_FromLong(focusInfo->focusPoint[i].rect.point.y)); 458 | PyTuple_SetItem(pyRect, 2, PyLong_FromLong(focusInfo->focusPoint[i].rect.size.width)); 459 | PyTuple_SetItem(pyRect, 3, PyLong_FromLong(focusInfo->focusPoint[i].rect.size.height)); 460 | 461 | PyObject *pyReserved = PyLong_FromUnsignedLong(focusInfo->focusPoint[i].reserved); 462 | PyDict_SetItemString(pyFocusPoint, "rect", pyRect); 463 | PyDict_SetItemString(pyFocusPoint, "reserved", pyReserved); 464 | 465 | PyTuple_SetItem(pyFocusPointTuple, i, pyFocusPoint); 466 | 467 | Py_DECREF(pyRect); 468 | Py_DECREF(pyReserved); 469 | } 470 | PyObject *pyPointNumber = PyLong_FromUnsignedLong(focusInfo->pointNumber); 471 | PyObject *pyExecuteMode = PyLong_FromUnsignedLong(focusInfo->executeMode); 472 | 473 | PyDict_SetItemString(pyPropertyData, "imageRect", pyImageRect); 474 | PyDict_SetItemString(pyPropertyData, "pointNumber", pyPointNumber); 475 | PyDict_SetItemString(pyPropertyData, "focusPoint", pyFocusPointTuple); 476 | PyDict_SetItemString(pyPropertyData, "executeMode", pyExecuteMode); 477 | 478 | Py_DECREF(pyImageRect); 479 | Py_DECREF(pyPointNumber); 480 | Py_DECREF(pyFocusPointTuple); 481 | Py_DECREF(pyExecuteMode); 482 | break; 483 | } 484 | case kEdsDataType_PictureStyleDesc:{ 485 | EdsPictureStyleDesc *pictureStyleDesc = static_cast(propertyData); 486 | pyPropertyData = PyDict_New(); 487 | PyObject *pyContrast = PyLong_FromLong(pictureStyleDesc->contrast); 488 | PyDict_SetItemString(pyPropertyData, "contrast", pyContrast); 489 | PyObject *pySharpness = PyLong_FromUnsignedLong(pictureStyleDesc->sharpness); 490 | PyDict_SetItemString(pyPropertyData, "sharpness", pySharpness); 491 | PyObject *pySaturation = PyLong_FromLong(pictureStyleDesc->saturation); 492 | PyDict_SetItemString(pyPropertyData, "saturation", pySaturation); 493 | PyObject *pyColorTone = PyLong_FromLong(pictureStyleDesc->colorTone); 494 | PyDict_SetItemString(pyPropertyData, "colorTone", pyColorTone); 495 | PyObject *pyFilterEffect = PyLong_FromUnsignedLong(pictureStyleDesc->filterEffect); 496 | PyDict_SetItemString(pyPropertyData, "filterEffect", pyFilterEffect); 497 | PyObject *pyToningEffect = PyLong_FromUnsignedLong(pictureStyleDesc->toningEffect); 498 | PyDict_SetItemString(pyPropertyData, "toningEffect", pyToningEffect); 499 | PyObject *pySharpFineness = PyLong_FromUnsignedLong(pictureStyleDesc->sharpFineness); 500 | PyDict_SetItemString(pyPropertyData, "sharpFineness", pySharpFineness); 501 | PyObject *pySharpThreshold = PyLong_FromUnsignedLong(pictureStyleDesc->sharpThreshold); 502 | PyDict_SetItemString(pyPropertyData, "sharpThreshold", pySharpThreshold); 503 | 504 | Py_DECREF(pyContrast); 505 | Py_DECREF(pySharpness); 506 | Py_DECREF(pySaturation); 507 | Py_DECREF(pyColorTone); 508 | Py_DECREF(pyFilterEffect); 509 | Py_DECREF(pyToningEffect); 510 | Py_DECREF(pySharpFineness); 511 | Py_DECREF(pySharpThreshold); 512 | break; 513 | } 514 | case kEdsDataType_Unknown: 515 | case kEdsDataType_Bool_Array: 516 | case kEdsDataType_Int8_Array: 517 | case kEdsDataType_Int16_Array: 518 | case kEdsDataType_Int32_Array: 519 | case kEdsDataType_UInt8_Array: 520 | case kEdsDataType_UInt16_Array: 521 | case kEdsDataType_UInt32_Array: 522 | case kEdsDataType_Rational_Array:{ 523 | PyErr_Format(PyExc_NotImplementedError, "unable to get the property %ls", propertyID); 524 | delete propertyData; 525 | return nullptr; 526 | } 527 | } 528 | delete propertyData; 529 | return pyPropertyData; 530 | } 531 | 532 | 533 | PyDoc_STRVAR(PyEds_SetPropertyData__doc__, 534 | "Sets property data for the designated object.\n\n" 535 | ":param EdsObject camera_or_image: The item object.\n" 536 | ":param PropID property_id: The PropertyID.\n" 537 | ":param int param: Specify an index in case there are two or\n" 538 | "\tmore values over the same ID.\n" 539 | ":param Any data: The data to set.\n" 540 | ":raises EdsError: Any of the sdk errors."); 541 | 542 | static PyObject* PyEds_SetPropertyData(PyObject *Py_UNUSED(self), PyObject *args) { 543 | PyObject *pyObj; 544 | unsigned long propertyID; 545 | long param; 546 | PyObject *pyPropertyData; 547 | 548 | if (!PyArg_ParseTuple(args, "OklO:EdsSetPropertyData", &pyObj, &propertyID, ¶m, &pyPropertyData)) { 549 | return nullptr; 550 | } 551 | PyEdsObject* edsObj = PyToEds(pyObj); 552 | if (!edsObj) { 553 | return nullptr; 554 | } 555 | 556 | EdsDataType dataType; 557 | unsigned long dataSize; 558 | unsigned long retVal(EdsGetPropertySize(edsObj->edsObj, propertyID, param, &dataType, &dataSize)); 559 | PyCheck_EDSERROR(retVal); 560 | 561 | uint8_t *propertyData = nullptr; 562 | if (EDS::DataTypeSize.count(dataType)){ 563 | propertyData = new (std::nothrow) uint8_t[EDS::DataTypeSize.at(dataType)]; 564 | } 565 | switch (dataType){ 566 | case kEdsDataType_Bool: { 567 | if (!PyBool_Check(pyPropertyData)) 568 | { 569 | PyErr_Format(PyExc_TypeError, "Properppty %lu expects boolean", propertyID); 570 | delete propertyData; 571 | return nullptr; 572 | } 573 | *propertyData = PyObject_IsTrue(pyPropertyData) ? true : false; 574 | break; 575 | } 576 | case kEdsDataType_String: { 577 | if (!PyUnicode_Check(pyPropertyData)) { 578 | PyErr_Format(PyExc_TypeError, "Property %lu expects string", propertyID); 579 | return nullptr; 580 | } 581 | PyObject* pyString = PyUnicode_AsEncodedString(pyPropertyData, Py_FileSystemDefaultEncoding, Py_FileSystemDefaultEncodeErrors); 582 | propertyData = reinterpret_cast(strdup(PyBytes_AsString(pyString))); 583 | if (!propertyData) { 584 | propertyData = nullptr; // capture error later 585 | } 586 | Py_DecRef(pyString); 587 | break; 588 | } 589 | case kEdsDataType_UInt8: 590 | case kEdsDataType_UInt16: 591 | case kEdsDataType_UInt32: { 592 | if (!PyLong_Check(pyPropertyData)) { 593 | PyErr_Format(PyExc_TypeError, "Property %lu expects unsigned int", propertyID); 594 | delete propertyData; 595 | return nullptr; 596 | } 597 | unsigned long uLongVal = PyLong_AsUnsignedLong(pyPropertyData); 598 | memcpy_s(propertyData, EDS::DataTypeSize.at(dataType), &uLongVal, sizeof(unsigned long)); 599 | break; 600 | } 601 | case kEdsDataType_UInt64: { 602 | if (!PyLong_Check(pyPropertyData)) { 603 | PyErr_Format(PyExc_TypeError, "Property %lu expects unsigned int", propertyID); 604 | delete propertyData; 605 | return nullptr; 606 | } 607 | unsigned long long uLongLongVal = PyLong_AsUnsignedLongLong(pyPropertyData); 608 | memcpy_s(propertyData, EDS::DataTypeSize.at(dataType), &uLongLongVal, sizeof(unsigned long long)); 609 | break; 610 | } 611 | case kEdsDataType_Int8: 612 | case kEdsDataType_Int16: 613 | case kEdsDataType_Int32: { 614 | if (!PyLong_Check(pyPropertyData)) { 615 | PyErr_Format(PyExc_TypeError, "Property %lu expects int", propertyID); 616 | delete propertyData; 617 | return nullptr; 618 | } 619 | long longVal = PyLong_AsLong(pyPropertyData); 620 | memcpy_s(propertyData, EDS::DataTypeSize.at(dataType), &longVal, sizeof(long)); 621 | break; 622 | } 623 | case kEdsDataType_Int64: { 624 | if (!PyLong_Check(pyPropertyData)) { 625 | PyErr_Format(PyExc_TypeError, "Property %lu expects int", propertyID); 626 | delete propertyData; 627 | return nullptr; 628 | } 629 | long long longLongVal = PyLong_AsLongLong(pyPropertyData); 630 | memcpy_s(propertyData, EDS::DataTypeSize.at(dataType), &longLongVal, sizeof(long long)); 631 | break; 632 | } 633 | case kEdsDataType_Float: 634 | case kEdsDataType_Double: { 635 | if (!PyFloat_Check(pyPropertyData)) { 636 | PyErr_Format(PyExc_TypeError, "Property %lu expects float", propertyID); 637 | delete propertyData; 638 | return nullptr; 639 | } 640 | double doubleVal = PyFloat_AsDouble(pyPropertyData); 641 | memcpy_s(propertyData, EDS::DataTypeSize.at(dataType), &doubleVal, sizeof(double)); 642 | break; 643 | } 644 | case kEdsDataType_Rational: { 645 | PyObject *iter = PyObject_GetIter(pyPropertyData); 646 | bool error = false; 647 | EdsRational *rational = reinterpret_cast(propertyData); 648 | if (iter) { 649 | PyObject *item = PyIter_Next(iter); 650 | if (!item || !PyLong_Check(item)) { 651 | error = true; 652 | } 653 | else { 654 | rational->numerator = PyLong_AsLong(item); 655 | Py_DECREF(item); 656 | item = PyIter_Next(iter); 657 | if (!item || !PyLong_Check(item)) { 658 | error = true; 659 | } 660 | else { 661 | rational->denominator = PyLong_AsUnsignedLong(item); 662 | Py_DECREF(item); 663 | } 664 | } 665 | Py_DECREF(iter); 666 | } else { 667 | error = true; 668 | } 669 | if (error) { 670 | PyErr_Format(PyExc_TypeError, "Property %lu expects a sequence of two ints", propertyID); 671 | PyErr_Format(PyExc_TypeError, "Property %lu expects a sequence of two ints", propertyID); 672 | delete propertyData; 673 | return nullptr; 674 | } 675 | break; 676 | } 677 | case kEdsDataType_Unknown: 678 | case kEdsDataType_ByteBlock: 679 | case kEdsDataType_Point: 680 | case kEdsDataType_Rect: 681 | case kEdsDataType_Time: 682 | case kEdsDataType_FocusInfo: 683 | case kEdsDataType_PictureStyleDesc: 684 | case kEdsDataType_Bool_Array: 685 | case kEdsDataType_Int8_Array: 686 | case kEdsDataType_Int16_Array: 687 | case kEdsDataType_Int32_Array: 688 | case kEdsDataType_UInt8_Array: 689 | case kEdsDataType_UInt16_Array: 690 | case kEdsDataType_UInt32_Array: 691 | case kEdsDataType_Rational_Array:{ 692 | PyErr_Format(PyExc_NotImplementedError, "unable to get the property %ls", propertyID); 693 | delete propertyData; 694 | return nullptr; 695 | } 696 | } 697 | if (propertyData == nullptr) { 698 | PyErr_Format(PyExc_MemoryError, "failed to allocate memory"); 699 | return nullptr; 700 | } 701 | retVal = EdsSetPropertyData(edsObj->edsObj, propertyID, param, dataSize, propertyData); 702 | PyCheck_EDSERROR(retVal); 703 | 704 | Py_RETURN_NONE; 705 | } 706 | 707 | 708 | PyDoc_STRVAR(PyEds_GetPropertyDesc__doc__, 709 | "Gets a list of property data that can be set for the object\n" 710 | "\tdesignated in inRef, as well as maximum and minimum values.\n" 711 | "This API is intended for only some shooting-related properties.\n\n" 712 | ":param EdsObject camera: The camera item.\n" 713 | ":param PropID property_id: The Property ID.\n" 714 | ":raises EdsError: Any of the sdk errors.\n" 715 | ":return Dict[str: Any]: The values which can be set up."); 716 | 717 | static PyObject* PyEds_GetPropertyDesc(PyObject *Py_UNUSED(self), PyObject *args){ 718 | PyObject* pyCam; 719 | unsigned long propertyID; 720 | if (!PyArg_ParseTuple(args, "Ok:EdsSetObjectEventHandler", &pyCam, &propertyID)) { 721 | return nullptr; 722 | } 723 | 724 | PyEdsObject* edsObj = PyToEds(pyCam); 725 | if (!edsObj) { 726 | return nullptr; 727 | } 728 | 729 | EdsPropertyDesc propertyDesc; 730 | EdsError retVal = EdsGetPropertyDesc(edsObj->edsObj, propertyID, &propertyDesc); 731 | PyCheck_EDSERROR(retVal); 732 | 733 | PyObject *pyForm = PyLong_FromLong(propertyDesc.form); 734 | PyObject *pyAccess = PyLong_FromLong(propertyDesc.access); 735 | PyObject *pyPropDesc = PyTuple_New(propertyDesc.numElements); 736 | for (int i=0; i < propertyDesc.numElements; i++) { 737 | PyTuple_SetItem(pyPropDesc, i, PyLong_FromLong(propertyDesc.propDesc[i])); 738 | } 739 | 740 | PyObject *pyPropertyDesc = PyDict_New(); 741 | PyDict_SetItemString(pyPropertyDesc, "form", pyForm); 742 | PyDict_SetItemString(pyPropertyDesc, "access", pyAccess); 743 | PyDict_SetItemString(pyPropertyDesc, "propDesc", pyPropDesc); 744 | 745 | Py_DECREF(pyForm); 746 | Py_DECREF(pyAccess); 747 | Py_DECREF(pyPropDesc); 748 | return pyPropertyDesc; 749 | } 750 | 751 | 752 | /****************************************************************************** 753 | ******************************************************************************* 754 | // 755 | // Device-list and device operating functions 756 | // 757 | ******************************************************************************* 758 | ******************************************************************************/ 759 | 760 | PyDoc_STRVAR(PyEds_GetCameraList__doc__, 761 | "Gets camera list objects.\n\n" 762 | ":raises EdsError: Any of the sdk errors.\n" 763 | ":return EdsObject: the camera-list."); 764 | 765 | static PyObject* PyEds_GetCameraList(PyObject *Py_UNUSED(self)) { 766 | EdsCameraListRef cameraList; 767 | unsigned long retVal(EdsGetCameraList(&cameraList)); 768 | PyCheck_EDSERROR(retVal); 769 | return PyEdsObject_New(cameraList); 770 | } 771 | 772 | 773 | /****************************************************************************** 774 | ******************************************************************************* 775 | // 776 | // Camera operating functions 777 | // 778 | ******************************************************************************* 779 | ******************************************************************************/ 780 | 781 | PyDoc_STRVAR(PyEds_GetDeviceInfo__doc__, 782 | "Gets device information, such as the device name.\n" 783 | "Because device information of remote cameras is stored\n" 784 | "\ton the host computer, you can use this API\n" 785 | "\tbefore the camera object initiates communication\n" 786 | "\t(that is, before a session is opened).\n\n" 787 | ":param EdsObject camera: The camera object.\n" 788 | ":raises EdsError: Any of the sdk errors.\n" 789 | ":return Dict[str, Any]: The device information."); 790 | 791 | static PyObject* PyEds_GetDeviceInfo(PyObject *Py_UNUSED(self), PyObject *cam){ 792 | PyEdsObject *pyEdsCam = PyToEds(cam); 793 | if (!pyEdsCam) { 794 | return nullptr; 795 | } 796 | EdsDeviceInfo deviceInfo; 797 | unsigned long retVal(EdsGetDeviceInfo(pyEdsCam->edsObj, &deviceInfo)); 798 | PyCheck_EDSERROR(retVal); 799 | 800 | PyObject* pyDeviceSubtype = GetEnum("edsdk.constants", "DeviceSubType", deviceInfo.deviceSubType); 801 | if (pyDeviceSubtype == nullptr) { 802 | PyErr_Clear(); 803 | std::cout << "Unknown device subtype: " << deviceInfo.deviceSubType << std::endl; 804 | pyDeviceSubtype = PyLong_FromUnsignedLong(deviceInfo.deviceSubType); 805 | } 806 | PyObject *pySzPortName = PyUnicode_DecodeFSDefault(deviceInfo.szPortName); 807 | PyObject *pySzDeviceDescription = PyUnicode_DecodeFSDefault(deviceInfo.szDeviceDescription); 808 | PyObject *pyReserved = PyLong_FromUnsignedLong(deviceInfo.reserved); 809 | PyObject* pyDeviceInfo(PyDict_New()); 810 | PyDict_SetItemString(pyDeviceInfo, "szPortName", pySzPortName); 811 | PyDict_SetItemString(pyDeviceInfo, "szDeviceDescription", pySzDeviceDescription); 812 | PyDict_SetItemString(pyDeviceInfo, "deviceSubType", pyDeviceSubtype); 813 | PyDict_SetItemString(pyDeviceInfo, "reserved", pyReserved); 814 | Py_DECREF(pySzPortName); 815 | Py_DECREF(pySzDeviceDescription); 816 | Py_DECREF(pyDeviceSubtype); 817 | Py_DECREF(pyReserved); 818 | return pyDeviceInfo; 819 | } 820 | 821 | 822 | PyDoc_STRVAR(PyEds_OpenSession__doc__, 823 | "Establishes a logical connection with a remote camera.\n" 824 | "Use this API after getting the camera's EdsCamera object.\n\n" 825 | ":param EdsObject camera: the camera.\n" 826 | ":raises EdsError: Any of the sdk errors."); 827 | 828 | static PyObject* PyEds_OpenSession(PyObject *Py_UNUSED(self), PyObject *args) { 829 | PyObject* pyObj; 830 | if (!PyArg_ParseTuple(args, "O:EdsOpenSession", &pyObj)) { 831 | return nullptr; 832 | } 833 | PyEdsObject* edsObj = PyToEds(pyObj); 834 | if (!edsObj) { 835 | return nullptr; 836 | } 837 | unsigned long retVal(EdsOpenSession(edsObj->edsObj)); 838 | PyCheck_EDSERROR(retVal); 839 | Py_RETURN_NONE; 840 | } 841 | 842 | 843 | PyDoc_STRVAR(PyEds_CloseSession__doc__, 844 | "Closes a logical connection with a remote camera.\n\n" 845 | ":param EdsObject camera: the camera.\n" 846 | ":raises EdsError: Any of the sdk errors."); 847 | 848 | static PyObject* PyEds_CloseSession(PyObject *Py_UNUSED(self), PyObject *args) { 849 | PyObject* pyObj; 850 | if (!PyArg_ParseTuple(args, "O:EdsCloseSession", &pyObj)) { 851 | return nullptr; 852 | } 853 | PyEdsObject* edsObj = PyToEds(pyObj); 854 | if (!edsObj) { 855 | return nullptr; 856 | } 857 | unsigned long retVal(EdsCloseSession(edsObj->edsObj)); 858 | PyCheck_EDSERROR(retVal); 859 | Py_RETURN_NONE; 860 | } 861 | 862 | 863 | PyDoc_STRVAR(PyEds_SendCommand__doc__, 864 | "Sends a command such as \"Shoot\" to a remote camera.\n\n" 865 | ":param EdsObject camera: The camera object.\n" 866 | ":param CameraCommand command: Specifies the command to be sent.\n" 867 | ":param int param: Specifies additional command-specific information\n," 868 | "\tdefaults to 0.\n" 869 | ":raises EdsError: Any of the sdk errors."); 870 | 871 | static PyObject* PyEds_SendCommand(PyObject *Py_UNUSED(self), PyObject *args){ 872 | PyObject* pyCam; 873 | unsigned long command; 874 | long param = 0; 875 | if (!PyArg_ParseTuple(args, "Okl:EdsSendCommand", &pyCam, &command, ¶m)) { 876 | return nullptr; 877 | } 878 | PyEdsObject* cam(PyToEds(pyCam)); 879 | if (cam == nullptr) { 880 | return nullptr; 881 | } 882 | unsigned long retVal(EdsSendCommand(cam->edsObj, command, param)); 883 | PyCheck_EDSERROR(retVal); 884 | Py_RETURN_NONE; 885 | } 886 | 887 | 888 | PyDoc_STRVAR(PyEds_SendStatusCommand__doc__, 889 | "Sets the remote camera state or mode.\n\n" 890 | ":param EdsObject camera: The camera object.\n" 891 | ":param CameraStatusCommand command: Specifies the command to be sent.\n" 892 | ":param int param: Specifies additional command-specific information\n," 893 | "\tdefaults to 0.\n" 894 | ":raises EdsError: Any of the sdk errors."); 895 | 896 | static PyObject* PyEds_SendStatusCommand(PyObject *Py_UNUSED(self), PyObject *args){ 897 | PyObject* pyCam; 898 | unsigned long command; 899 | long param = 0; 900 | if (!PyArg_ParseTuple(args, "Okl:EdsSendStatusCommand", &pyCam, &command, ¶m)) { 901 | return nullptr; 902 | } 903 | PyEdsObject* cam(PyToEds(pyCam)); 904 | if (cam == nullptr) { 905 | return nullptr; 906 | } 907 | unsigned long retVal(EdsSendStatusCommand(cam->edsObj, command, param)); 908 | PyCheck_EDSERROR(retVal); 909 | Py_RETURN_NONE; 910 | } 911 | 912 | 913 | PyDoc_STRVAR(PyEds_SetCapacity__doc__, 914 | "Sets the remaining HDD capacity on the host computer\n" 915 | "\t(excluding the portion from image transfer),\n" 916 | "\tas calculated by subtracting the portion from the previous time.\n" 917 | "Set a reset flag initially and designate the cluster length\n" 918 | "\tand number of free clusters.\n" 919 | "Some type 2 protocol standard cameras can display the number of shots\n" 920 | "\tleft on the camera based on the available disk capacity\n" 921 | "\tof the host computer\n" 922 | "For these cameras, after the storage destination is set to the computer,\n" 923 | "\tuse this API to notify the camera of the available disk capacity\n" 924 | "\tof the host computer.\n\n" 925 | ":param EdsObject camera: The camera object.\n" 926 | ":param Dict[str, Any] capacity: The remaining capacity of a transmission place.\n" 927 | ":raises EdsError: Any of the sdk errors."); 928 | 929 | static PyObject* PyEds_SetCapacity(PyObject *Py_UNUSED(self), PyObject *args){ 930 | PyObject* pyCam; 931 | PyObject* pyCapacity; 932 | if (!PyArg_ParseTuple(args, "OO!:EdsSetCapacity", &pyCam, &PyDict_Type, &pyCapacity)) { 933 | return nullptr; 934 | } 935 | 936 | PyEdsObject* cam(PyToEds(pyCam)); 937 | if (cam == nullptr) { 938 | return nullptr; 939 | } 940 | 941 | PyObject* pyNumberOfFreeClusters = PyDict_GetItemString(pyCapacity, "numberOfFreeClusters"); 942 | PyObject* pyBytesPerSector = PyDict_GetItemString(pyCapacity, "bytesPerSector"); 943 | PyObject* pyReset = PyDict_GetItemString(pyCapacity, "reset"); 944 | if (!PyLong_Check(pyNumberOfFreeClusters) || !PyLong_Check(pyBytesPerSector) || !PyBool_Check(pyReset)){ 945 | PyErr_Format(PyExc_ValueError, "Invalid capacity"); 946 | return nullptr; 947 | } 948 | EdsCapacity capacity = { 949 | PyLong_AsLong(pyNumberOfFreeClusters), 950 | PyLong_AsLong(pyBytesPerSector), 951 | PyObject_IsTrue(pyReset), 952 | }; 953 | unsigned long retVal(EdsSetCapacity(cam->edsObj, capacity)); 954 | PyCheck_EDSERROR(retVal); 955 | Py_RETURN_NONE; 956 | } 957 | 958 | 959 | PyDoc_STRVAR(PyEds_GetVolumeInfo__doc__, 960 | "Gets volume information for a memory card in the camera.\n\n" 961 | ":param EdsObject volume: The volume item.\n" 962 | ":raises EdsError: Any of the sdk errors.\n" 963 | ":return Dict[str, Any]: Information of the volume."); 964 | 965 | static PyObject* PyEds_GetVolumeInfo(PyObject *Py_UNUSED(self), PyObject *pyVolume){ 966 | PyEdsObject* volume(PyToEds(pyVolume)); 967 | if (volume == nullptr) { 968 | return nullptr; 969 | } 970 | EdsVolumeInfo volumeInfo; 971 | unsigned long retVal(EdsGetVolumeInfo(volume->edsObj, &volumeInfo)); 972 | PyCheck_EDSERROR(retVal); 973 | 974 | PyObject *pyStorageType = GetEnum("constants", "StorageType", volumeInfo.storageType); 975 | if (pyStorageType == nullptr) { 976 | PyErr_Clear(); 977 | std::cout << "Unknown StorageType: " << volumeInfo.storageType << std::endl; 978 | pyStorageType = PyLong_FromUnsignedLong(volumeInfo.storageType); 979 | } 980 | PyObject *pyAccess = GetEnum("constants", "Access", volumeInfo.access); 981 | if (pyAccess == nullptr) { 982 | PyErr_Clear(); 983 | std::cout << "Unknown StorageType: " << volumeInfo.access << std::endl; 984 | pyAccess = PyLong_FromUnsignedLong(volumeInfo.access); 985 | } 986 | PyObject *pyMaxCapacity = PyLong_FromUnsignedLongLong(volumeInfo.maxCapacity); 987 | PyObject *pyFreeSpaceInBytes = PyLong_FromUnsignedLongLong(volumeInfo.freeSpaceInBytes); 988 | PyObject *pySzVolumeLabel = PyUnicode_DecodeFSDefault(volumeInfo.szVolumeLabel); 989 | 990 | PyObject* pyVolumeInfo(PyDict_New()); 991 | PyDict_SetItemString(pyVolumeInfo, "storageType", pyStorageType); 992 | PyDict_SetItemString(pyVolumeInfo, "access", pyAccess); 993 | PyDict_SetItemString(pyVolumeInfo, "maxCapacity", pyMaxCapacity); 994 | PyDict_SetItemString(pyVolumeInfo, "freeSpaceInBytes", pyFreeSpaceInBytes); 995 | PyDict_SetItemString(pyVolumeInfo, "szVolumeLabel", pySzVolumeLabel); 996 | 997 | Py_DECREF(pyStorageType); 998 | Py_DECREF(pyAccess); 999 | Py_DECREF(pyMaxCapacity); 1000 | Py_DECREF(pyFreeSpaceInBytes); 1001 | Py_DECREF(pySzVolumeLabel); 1002 | 1003 | return pyVolumeInfo; 1004 | } 1005 | 1006 | 1007 | PyDoc_STRVAR(PyEds_FormatVolume__doc__, 1008 | "Formats volumes of memory cards in a camera.\n\n" 1009 | ":param EdsObject volume: The volume item.\n" 1010 | ":raises EdsError: Any of the sdk errors.\n"); 1011 | 1012 | static PyObject* PyEds_FormatVolume(PyObject *Py_UNUSED(self), PyObject *pyVolume){ 1013 | PyEdsObject* volume(PyToEds(pyVolume)); 1014 | if (volume == nullptr) { 1015 | return nullptr; 1016 | } 1017 | unsigned long retVal(EdsFormatVolume(volume->edsObj)); 1018 | PyCheck_EDSERROR(retVal); 1019 | 1020 | Py_RETURN_NONE; 1021 | } 1022 | 1023 | 1024 | /****************************************************************************** 1025 | ******************************************************************************* 1026 | // 1027 | // Directory-item operating functions 1028 | // 1029 | ******************************************************************************* 1030 | ******************************************************************************/ 1031 | 1032 | PyDoc_STRVAR(PyEds_GetDirectoryItemInfo__doc__, 1033 | "Gets information about the directory or file objects\n" 1034 | "\ton the memory card (volume) in a remote camera.\n\n" 1035 | ":param EdsObject dir_item: The reference of the directory item.\n" 1036 | ":raises EdsError: Any of the sdk errors.\n" 1037 | ":return Dict[str, Any]: Information of the directory item."); 1038 | 1039 | static PyObject* PyEds_GetDirectoryItemInfo(PyObject *Py_UNUSED(self), PyObject *pyDirItem){ 1040 | PyEdsObject* dirItem(PyToEds(pyDirItem)); 1041 | if (dirItem == nullptr) { 1042 | return nullptr; 1043 | } 1044 | EdsDirectoryItemInfo dirItemInfo; 1045 | unsigned long retVal(EdsGetDirectoryItemInfo(dirItem->edsObj, &dirItemInfo)); 1046 | PyCheck_EDSERROR(retVal); 1047 | 1048 | PyObject *pySize = PyLong_FromUnsignedLongLong(dirItemInfo.size); 1049 | PyObject *pyIsFolder = PyBool_FromLong(dirItemInfo.isFolder); 1050 | PyObject *pyGroupID = PyLong_FromUnsignedLong(dirItemInfo.groupID); 1051 | PyObject *pyOption = PyLong_FromUnsignedLong(dirItemInfo.option); 1052 | PyObject *pySzFileName = PyUnicode_DecodeFSDefault(dirItemInfo.szFileName); 1053 | PyObject *pyFormat = GetEnum("constants", "ObjectFormat", dirItemInfo.format); 1054 | if (pyFormat == nullptr) { 1055 | PyErr_Clear(); 1056 | std::cout << "Unknown ObjectFormat: " << dirItemInfo.format << std::endl; 1057 | pyFormat = PyLong_FromUnsignedLong(dirItemInfo.format); 1058 | } 1059 | PyObject *pyDateTime = PyLong_FromUnsignedLong(dirItemInfo.dateTime); 1060 | 1061 | PyObject* pyDirItemInfo(PyDict_New()); 1062 | PyDict_SetItemString(pyDirItemInfo, "size", pySize); 1063 | PyDict_SetItemString(pyDirItemInfo, "isFolder", pyIsFolder); 1064 | PyDict_SetItemString(pyDirItemInfo, "groupID", pyGroupID); 1065 | PyDict_SetItemString(pyDirItemInfo, "option", pyOption); 1066 | PyDict_SetItemString(pyDirItemInfo, "szFileName", pySzFileName); 1067 | PyDict_SetItemString(pyDirItemInfo, "format", pyFormat); 1068 | PyDict_SetItemString(pyDirItemInfo, "dateTime", pyDateTime); 1069 | Py_DECREF(pySize); 1070 | Py_DECREF(pyIsFolder); 1071 | Py_DECREF(pyGroupID); 1072 | Py_DECREF(pyOption); 1073 | Py_DECREF(pySzFileName); 1074 | Py_DECREF(pyFormat); 1075 | Py_DECREF(pyDateTime); 1076 | return pyDirItemInfo; 1077 | } 1078 | 1079 | 1080 | PyDoc_STRVAR(PyEds_DeleteDirectoryItem__doc__, 1081 | "Deletes a camera folder or file.\n" 1082 | "If folders with subdirectories are designated, all files are deleted\n" 1083 | "\texcept protected files.\n" 1084 | "EdsDirectoryItem objects deleted by means of this API are implicitly\n" 1085 | "\treleased by the EDSDK.\n\n" 1086 | ":param EdsObject dir_item: The directory item.\n" 1087 | ":raises EdsError: Any of the sdk errors.\n"); 1088 | 1089 | static PyObject* PyEds_DeleteDirectoryItem(PyObject *Py_UNUSED(self), PyObject *pyDirItem){ 1090 | PyEdsObject* dirItem(PyToEds(pyDirItem)); 1091 | if (dirItem == nullptr) { 1092 | return nullptr; 1093 | } 1094 | unsigned long retVal(EdsDeleteDirectoryItem(dirItem->edsObj)); 1095 | PyCheck_EDSERROR(retVal); 1096 | 1097 | Py_RETURN_NONE; 1098 | } 1099 | 1100 | 1101 | PyDoc_STRVAR(PyEds_Download__doc__, 1102 | "Downloads a file on a remote camera\n" 1103 | "\t(in the camera memory or on a memory card) to the host computer.\n" 1104 | "The downloaded file is sent directly to a file stream created in advance.\n" 1105 | "When dividing the file being retrieved, call this API repeatedly.\n" 1106 | "Also in this case, make the data block size a multiple of 512 (bytes),\n" 1107 | "\texcluding the final block.\n\n" 1108 | ":param EdsObject dir_item: The directory item.\n" 1109 | ":param int size: The number of bytes to be retrieved.\n" 1110 | ":param EdsObject stream: The stream.\n" 1111 | ":raises EdsError: Any of the sdk errors."); 1112 | 1113 | 1114 | static PyObject* PyEds_Download(PyObject *Py_UNUSED(self), PyObject *args) { 1115 | PyObject *pyDirItemRef; 1116 | unsigned long long readSize; 1117 | PyObject *pyFileStream; 1118 | if (!PyArg_ParseTuple(args, "OkO:EdsDownload", &pyDirItemRef, &readSize, &pyFileStream)) { 1119 | return nullptr; 1120 | } 1121 | PyEdsObject* dirItem(PyToEds(pyDirItemRef)); 1122 | if (dirItem == nullptr) { 1123 | return nullptr; 1124 | } 1125 | PyEdsObject* fileStream(PyToEds(pyFileStream)); 1126 | if (fileStream == nullptr) { 1127 | return nullptr; 1128 | } 1129 | unsigned long retVal(EdsDownload(dirItem->edsObj, readSize, fileStream->edsObj)); 1130 | PyCheck_EDSERROR(retVal); 1131 | 1132 | Py_RETURN_NONE; 1133 | } 1134 | 1135 | 1136 | PyDoc_STRVAR(PyEds_DownloadCancel__doc__, 1137 | "Must be executed when downloading of a directory item is canceled.\n" 1138 | "Calling this API makes the camera cancel file transmission\n" 1139 | "It also releases resources.\n" 1140 | "\tThis operation need not be executed when using EdsDownloadThumbnail.\n\n" 1141 | ":param EdsObject dir_item: The directory item.\n" 1142 | ":raises EdsError: Any of the sdk errors."); 1143 | 1144 | static PyObject* PyEds_DownloadCancel(PyObject *Py_UNUSED(self), PyObject *pyDirItem){ 1145 | PyEdsObject* dirItem(PyToEds(pyDirItem)); 1146 | if (dirItem == nullptr) { 1147 | return nullptr; 1148 | } 1149 | unsigned long retVal(EdsDownloadCancel(dirItem->edsObj)); 1150 | PyCheck_EDSERROR(retVal); 1151 | 1152 | Py_RETURN_NONE; 1153 | } 1154 | 1155 | 1156 | PyDoc_STRVAR(PyEds_DownloadComplete__doc__, 1157 | "Must be called when downloading of directory items is complete.\n" 1158 | "\tExecuting this API makes the camera\n" 1159 | "\t\trecognize that file transmission is complete.\n" 1160 | "\tThis operation need not be executed when using EdsDownloadThumbnail.\n\n" 1161 | ":param EdsObject dir_item: The directory item.\n" 1162 | ":raises EdsError: Any of the sdk errors."); 1163 | 1164 | static PyObject* PyEds_DownloadComplete(PyObject *Py_UNUSED(self), PyObject *pyDirItem){ 1165 | PyEdsObject* dirItem(PyToEds(pyDirItem)); 1166 | if (dirItem == nullptr) { 1167 | return nullptr; 1168 | } 1169 | unsigned long retVal(EdsDownloadComplete(dirItem->edsObj)); 1170 | PyCheck_EDSERROR(retVal); 1171 | 1172 | Py_RETURN_NONE; 1173 | } 1174 | 1175 | 1176 | PyDoc_STRVAR(PyEds_DownloadThumbnail__doc__, 1177 | "Extracts and downloads thumbnail information from image files in a camera.\n" 1178 | "Thumbnail information in the camera's image files is downloaded\n" 1179 | "\tto the host computer.\n" 1180 | "Downloaded thumbnails are sent directly to a file stream created in advance.\n\n" 1181 | ":param EdsObject dir_item: The directory item.\n" 1182 | ":raises EdsError: Any of the sdk errors.\n" 1183 | ":return EdsObject: The stream.\n"); 1184 | 1185 | static PyObject* PyEds_DownloadThumbnail(PyObject *Py_UNUSED(self), PyObject *args) { 1186 | PyObject *pyDirItemRef; 1187 | PyObject *pyFileStream; 1188 | if (!PyArg_ParseTuple(args, "OkO:EdsDownloadThumbnail", &pyDirItemRef, &pyFileStream)) { 1189 | return nullptr; 1190 | } 1191 | PyEdsObject* dirItem(PyToEds(pyDirItemRef)); 1192 | if (dirItem == nullptr) { 1193 | return nullptr; 1194 | } 1195 | PyEdsObject* fileStream(PyToEds(pyFileStream)); 1196 | if (fileStream == nullptr) { 1197 | return nullptr; 1198 | } 1199 | unsigned long retVal(EdsDownloadThumbnail(dirItem->edsObj, fileStream->edsObj)); 1200 | PyCheck_EDSERROR(retVal); 1201 | 1202 | Py_RETURN_NONE; 1203 | } 1204 | 1205 | 1206 | PyDoc_STRVAR(PyEds_GetAttribute__doc__, 1207 | "Gets attributes of files on a camera.\n\n" 1208 | ":param EdsObject dir_item: The directory item.\n" 1209 | ":raises EdsError: Any of the sdk errors.\n" 1210 | ":return int: Indicates the file attributes.\n" 1211 | "\tAs for the file attributes, OR values of the value defined\n" 1212 | "\tby enum EdsFileAttributes can be retrieved. Thus, when\n" 1213 | "\tdetermining the file attributes, you must check\n" 1214 | "\tif an attribute flag is set for target attributes."); 1215 | 1216 | static PyObject* PyEds_GetAttribute(PyObject *Py_UNUSED(self), PyObject *pyDirItem){ 1217 | PyEdsObject* dirItem(PyToEds(pyDirItem)); 1218 | if (dirItem == nullptr) { 1219 | return nullptr; 1220 | } 1221 | EdsFileAttributes attr; 1222 | 1223 | EdsError retVal = EdsGetAttribute(dirItem->edsObj, &attr); 1224 | PyCheck_EDSERROR(retVal); 1225 | 1226 | return PyLong_FromUnsignedLong(attr); 1227 | } 1228 | 1229 | 1230 | PyDoc_STRVAR(PyEds_SetAttribute__doc__, 1231 | "Changes attributes of files on a camera.\n\n" 1232 | ":param EdsObject dir_item: The directory item.\n" 1233 | ":param int file_attributes: Indicates the file attributes.\n" 1234 | "\tAs for the file attributes, OR values of the value\n" 1235 | "\tdefined by enum FileAttributes can be retrieved.\n" 1236 | ":raises EdsError: Any of the sdk errors."); 1237 | 1238 | static PyObject* PyEds_SetAttribute(PyObject *Py_UNUSED(self), PyObject *args){ 1239 | PyObject* pyDirItem; 1240 | unsigned long fileAttribute; 1241 | 1242 | if (!PyArg_ParseTuple(args, "Ok:EdsSetAttribute", &pyDirItem, &fileAttribute)) { 1243 | return nullptr; 1244 | } 1245 | 1246 | PyEdsObject* dirItem(PyToEds(pyDirItem)); 1247 | if (dirItem == nullptr) { 1248 | return nullptr; 1249 | } 1250 | 1251 | EdsError retVal(EdsSetAttribute( 1252 | dirItem->edsObj, static_cast(fileAttribute))); 1253 | PyCheck_EDSERROR(retVal); 1254 | 1255 | Py_RETURN_NONE; 1256 | } 1257 | 1258 | 1259 | /****************************************************************************** 1260 | ******************************************************************************* 1261 | // 1262 | // Stream operating functions 1263 | // 1264 | ******************************************************************************* 1265 | ******************************************************************************/ 1266 | 1267 | 1268 | PyDoc_STRVAR(PyEds_CreateFileStream__doc__, 1269 | "Creates a new file on a host computer (or opens an existing file)\n" 1270 | "\tand creates a file stream for access to the file.\n" 1271 | "If a new file is designated before executing this API,\n" 1272 | "\tthe file is actually created following the timing of writing\n" 1273 | "\tby means of EdsWrite or the like with respect to an open stream.\n\n" 1274 | ":param str filename: the file name.\n" 1275 | ":param FileCreateDisposition disposition: Action to take on files that exist or not.\n" 1276 | ":param Access access: Access to the stream (reading, writing, or both).\n" 1277 | ":raises EdsError: Any of the sdk errors.\n" 1278 | ":return EdsObject: The stream."); 1279 | 1280 | static PyObject* PyEds_CreateFileStream(PyObject *Py_UNUSED(self), PyObject *args){ 1281 | PyObject* pyFilename; 1282 | unsigned long createDisposition; 1283 | unsigned long desiredAccess; 1284 | 1285 | if (!PyArg_ParseTuple(args, "Okk:CreateFileStream", &pyFilename, &createDisposition, &desiredAccess)) { 1286 | return nullptr; 1287 | } 1288 | 1289 | if (!PyUnicode_Check(pyFilename) || PyUnicode_GET_LENGTH(pyFilename) == 0) { 1290 | PyErr_SetString(PyExc_TypeError, "filename parameter must be a non-empty string"); 1291 | return nullptr; 1292 | } 1293 | PyObject *pyfilenameEncoded( 1294 | PyUnicode_AsEncodedString(pyFilename, 1295 | Py_FileSystemDefaultEncoding, 1296 | Py_FileSystemDefaultEncodeErrors)); 1297 | EdsStreamRef fileStream; 1298 | unsigned long retVal(EdsCreateFileStream( 1299 | PyBytes_AsString(pyfilenameEncoded), 1300 | static_cast(createDisposition), 1301 | static_cast(desiredAccess), 1302 | &fileStream)); 1303 | 1304 | if (retVal != EDS_ERR_OK) { 1305 | Py_DECREF(pyfilenameEncoded); 1306 | PyCheck_EDSERROR(retVal); 1307 | } 1308 | Py_DECREF(pyfilenameEncoded); 1309 | PyObject *pyFileStream = PyEdsObject_New(fileStream); 1310 | assert(pyFileStream); 1311 | return pyFileStream; 1312 | } 1313 | 1314 | 1315 | PyDoc_STRVAR(PyEds_CreateMemoryStream__doc__, 1316 | "Creates a stream in the memory of a host computer.\n" 1317 | "In the case of writing in excess of the allocated buffer size,\n" 1318 | "\tthe memory is automatically extended.\n\n" 1319 | ":param int buffer_size: The number of bytes of the memory to allocate.\n" 1320 | ":raises EdsError: Any of the sdk errors.\n" 1321 | ":return EdsObject: The stream."); 1322 | 1323 | static PyObject* PyEds_CreateMemoryStream(PyObject *Py_UNUSED(self), PyObject *pyBufferSize){ 1324 | if (!PyLong_Check(pyBufferSize)) { 1325 | PyErr_SetString(PyExc_TypeError, "buffer_size parameter must be an integer"); 1326 | return nullptr; 1327 | } 1328 | 1329 | EdsStreamRef fileStream; 1330 | unsigned long retVal(EdsCreateMemoryStream( 1331 | PyLong_AsUnsignedLongLong(pyBufferSize), &fileStream)); 1332 | PyCheck_EDSERROR(retVal); 1333 | 1334 | PyObject *pyFileStream = PyEdsObject_New(fileStream); 1335 | assert(pyFileStream); 1336 | return pyFileStream; 1337 | } 1338 | 1339 | 1340 | PyDoc_STRVAR(PyEds_CreateFileStreamEx__doc__, 1341 | "An extended version of EdsCreateStreamFromFile.\n" 1342 | "Use this function when working with Unicode file names.\n\n" 1343 | ":param str filename: the file name.\n" 1344 | ":param FileCreateDisposition disposition: Action to take on files that exist or not.\n" 1345 | ":param Access access: Access to the stream (reading, writing, or both).\n" 1346 | ":raises EdsError: Any of the sdk errors.\n" 1347 | ":return EdsObject: The stream."); 1348 | 1349 | static PyObject* PyEds_CreateFileStreamEx(PyObject *Py_UNUSED(self), PyObject *args){ 1350 | PyObject* pyFilename; 1351 | unsigned long createDisposition; 1352 | unsigned long desiredAccess; 1353 | 1354 | if (!PyArg_ParseTuple(args, "Okk:CreateFileStreamEx", &pyFilename, &createDisposition, &desiredAccess)) { 1355 | return nullptr; 1356 | } 1357 | 1358 | if (!PyUnicode_Check(pyFilename) || PyUnicode_GET_LENGTH(pyFilename) == 0) { 1359 | PyErr_SetString(PyExc_TypeError, "filename parameter must be a non-empty string"); 1360 | return nullptr; 1361 | } 1362 | 1363 | Py_ssize_t filenameLen(PyUnicode_GET_LENGTH(pyFilename)); 1364 | wchar_t *filenameEncoded(new (std::nothrow) wchar_t[filenameLen + 1]); 1365 | if (filenameEncoded == nullptr) { 1366 | PyErr_SetString(PyExc_MemoryError, "Could not allocate memory for filename"); 1367 | return nullptr; 1368 | } 1369 | 1370 | Py_ssize_t nrBytesCopied(PyUnicode_AsWideChar( 1371 | pyFilename, filenameEncoded, filenameLen)); 1372 | filenameEncoded[filenameLen] = L'\0'; 1373 | if (nrBytesCopied == -1) { 1374 | PyErr_SetString(PyExc_ValueError, "Could not convert filename to wide character string"); 1375 | delete[] filenameEncoded; 1376 | return nullptr; 1377 | } 1378 | 1379 | EdsStreamRef fileStream; 1380 | unsigned long retVal(EdsCreateFileStreamEx( 1381 | filenameEncoded, 1382 | static_cast(createDisposition), 1383 | static_cast(desiredAccess), 1384 | &fileStream)); 1385 | 1386 | delete[] filenameEncoded; 1387 | PyCheck_EDSERROR(retVal); 1388 | 1389 | PyObject *pyFileStream = PyEdsObject_New(fileStream); 1390 | assert(pyFileStream); 1391 | return pyFileStream; 1392 | } 1393 | 1394 | PyDoc_STRVAR(PyEds_CreateMemoryStreamFromPointer__doc__, 1395 | "Creates a stream from the memory buffer you prepare.\n" 1396 | "Unlike the buffer size of streams created by means of EdsCreateMemoryStream,\n" 1397 | "the buffer size you prepare for streams created this way does not expand.\n\n" 1398 | ":param Union[bytes, bytearray, memoryview] buffer: The buffer.\n" 1399 | ":raises EdsError: Any of the sdk errors.\n" 1400 | ":return EdsObject: The stream."); 1401 | 1402 | static PyObject* PyEds_CreateMemoryStreamFromPointer(PyObject *Py_UNUSED(self), PyObject *pyBufferLike){ 1403 | void * bufferPtr = nullptr; 1404 | Py_ssize_t bufferLen = 0; 1405 | 1406 | std::cout << "PyEds_CreateMemoryStreamFromPointer" << std::endl; 1407 | if (PyMemoryView_Check(pyBufferLike)) { 1408 | std::cout << "PyMemoryView_Check" << std::endl; 1409 | Py_buffer *pyBuffer = PyMemoryView_GET_BUFFER(pyBufferLike); 1410 | if (pyBuffer->readonly) { 1411 | PyErr_SetString(PyExc_ValueError, "Buffer is read-only"); 1412 | return nullptr; 1413 | } 1414 | std::cout << "PyMemoryView_GET_BUFFER" << std::endl; 1415 | bufferPtr = pyBuffer->buf; 1416 | bufferLen = pyBuffer->len; 1417 | } 1418 | else if (PyBytes_Check(pyBufferLike)) { 1419 | std::cout << "PyBytes_Check" << std::endl; 1420 | bufferPtr = PyBytes_AS_STRING(pyBufferLike); 1421 | bufferLen = PyBytes_GET_SIZE(pyBufferLike); 1422 | } 1423 | else if (PyByteArray_Check(pyBufferLike)) { 1424 | std::cout << "PyByteArray_Check" << std::endl; 1425 | bufferPtr = PyByteArray_AS_STRING(pyBufferLike); 1426 | bufferLen = PyByteArray_GET_SIZE(pyBufferLike); 1427 | } 1428 | else { 1429 | PyErr_SetString(PyExc_TypeError, "buffer parameter must be a bytes, bytearray, or memoryview"); 1430 | return nullptr; 1431 | } 1432 | std::cout << "Py_buffer" << std::endl; 1433 | EdsStreamRef fileStream; 1434 | 1435 | unsigned long retVal(EdsCreateMemoryStreamFromPointer( 1436 | bufferPtr, bufferLen, &fileStream)); 1437 | std::cout << "EdsCreateMemoryStreamFromPointer" << std::endl; 1438 | PyCheck_EDSERROR(retVal); 1439 | 1440 | PyObject *pyFileStream = PyEdsObject_New(fileStream); 1441 | assert(pyFileStream); 1442 | return pyFileStream; 1443 | } 1444 | 1445 | 1446 | PyDoc_STRVAR(PyEds_GetPosition__doc__, 1447 | "Gets the current read or write position of the stream\n" 1448 | "\t(that is, the file position indicator).\n\n" 1449 | ":param EdsObject stream_or_image: The stream or image.\n" 1450 | ":raises EdsError: Any of the sdk errors.\n" 1451 | ":return int: The current stream pointer."); 1452 | 1453 | static PyObject* PyEds_GetPosition(PyObject *Py_UNUSED(self), PyObject *pyStream){ 1454 | PyEdsObject *pyEdsObject(PyToEds(pyStream)); 1455 | if (pyEdsObject == nullptr) { 1456 | return nullptr; 1457 | } 1458 | EdsUInt64 position; 1459 | unsigned long retVal(EdsGetPosition(pyEdsObject->edsObj, &position)); 1460 | PyCheck_EDSERROR(retVal); 1461 | 1462 | return PyLong_FromUnsignedLongLong(position); 1463 | } 1464 | 1465 | 1466 | PyDoc_STRVAR(PyEds_GetLength__doc__, 1467 | "Gets the current read or write position of the stream.\n" 1468 | "\t(that is, the file position indicator).\n\n" 1469 | ":param EdsObject stream_or_image: The stream or image.\n" 1470 | ":raises EdsError: Any of the sdk errors.\n" 1471 | ":return int: The length of the stream."); 1472 | 1473 | static PyObject* PyEds_GetLength(PyObject *Py_UNUSED(self), PyObject *pyStream){ 1474 | PyEdsObject *pyEdsObject(PyToEds(pyStream)); 1475 | if (pyEdsObject == nullptr) { 1476 | return nullptr; 1477 | } 1478 | EdsUInt64 length; 1479 | unsigned long retVal(EdsGetLength(pyEdsObject->edsObj, &length)); 1480 | PyCheck_EDSERROR(retVal); 1481 | 1482 | return PyLong_FromUnsignedLongLong(length); 1483 | } 1484 | 1485 | 1486 | PyDoc_STRVAR(PyEds_CopyData__doc__, 1487 | "Copies data from the copy source stream to the copy destination stream.\n" 1488 | "The read or write position of the data to copy is determined from\n" 1489 | "\tthe current file read or write position of the respective stream.\n" 1490 | "After this API is executed, the read or write positions of the copy source\n" 1491 | "\tand copy destination streams are moved an amount corresponding to\n" 1492 | "\tinWriteSize in the positive direction.\n\n" 1493 | ":param EdsObject in_stream_or_image: The input stream or image.\n" 1494 | ":param int write_size: The number of bytes to copy.\n" 1495 | ":param EdsObject out_stream_or_image: The output stream or image."); 1496 | 1497 | static PyObject* PyEds_CopyData(PyObject *Py_UNUSED(self), PyObject *args){ 1498 | PyObject *pyInStream; 1499 | unsigned long long writeSize; 1500 | PyObject *pyOutStream; 1501 | 1502 | if (!PyArg_ParseTuple(args, "OKO:CopyData", &pyInStream, &writeSize, &pyOutStream)) { 1503 | return nullptr; 1504 | } 1505 | PyEdsObject *pyInEdsObject(PyToEds(pyInStream)); 1506 | PyEdsObject *pyOutEdsObject(PyToEds(pyOutStream)); 1507 | if (pyInEdsObject == nullptr || pyOutEdsObject == nullptr) { 1508 | return nullptr; 1509 | } 1510 | unsigned long retVal(EdsCopyData( 1511 | pyInEdsObject->edsObj, writeSize, pyOutEdsObject->edsObj)); 1512 | PyCheck_EDSERROR(retVal); 1513 | Py_RETURN_NONE; 1514 | } 1515 | 1516 | 1517 | static PyObject *pyProgressCallback[2] = {nullptr, nullptr}; 1518 | 1519 | PyDoc_STRVAR(PyEds_SetProgressCallback__doc__, 1520 | "Register a progress callback function.\n" 1521 | "An event is received as notification of progress during processing that\n" 1522 | "\ttakes a relatively long time, such as downloading files from a\n" 1523 | "\tremote camera.\n" 1524 | "If you register the callback function, the EDSDK calls the callback\n" 1525 | "\tfunction during execution or on completion of the following APIs.\n" 1526 | "This timing can be used in updating on-screen progress bars, for example.\n\n" 1527 | ":param EdsObject stream_or_image: the stream or image object.\n" 1528 | ":param Callable callback: the callback function.\n" 1529 | "\tExpected signature:\n" 1530 | "\t\t(percent: int, cancel: bool, context: Optional[Any] = None) -> int.\n" 1531 | ":param ProgressOption option: The option about progress is specified.\n" 1532 | "\tMust be one of the following values.\n" 1533 | "\t\tProgressOption.Done\n" 1534 | "\t\t\tWhen processing is completed,a callback function\n" 1535 | "\t\t\tis called only once.\n" 1536 | "\t\tProgressOption.Periodically\n" 1537 | "\t\t\tA callback function is performed periodically.\n" 1538 | ":raises EdsError: Any of the sdk errors."); 1539 | 1540 | static PyObject* PyEds_SetProgressCallback(PyObject *Py_UNUSED(self), PyObject *args) { 1541 | PyObject* pyStreamOrImage; 1542 | PyObject* pyCallable; 1543 | unsigned long progressOption; 1544 | PyObject* pyContext(nullptr); 1545 | 1546 | if (!PyArg_ParseTuple(args, "OOk|O:EdsSetProgressCallback", &pyStreamOrImage, &pyCallable, &progressOption, &pyContext)) { 1547 | return nullptr; 1548 | } 1549 | 1550 | PyEdsObject* edsObj = PyToEds(pyStreamOrImage); 1551 | if (!edsObj) { 1552 | return nullptr; 1553 | } 1554 | 1555 | if (pyCallable == Py_None || !PyCallable_Check(pyCallable)){ 1556 | PyErr_Format(PyExc_ValueError, "expected a callable object"); 1557 | return nullptr; 1558 | } 1559 | 1560 | if (!PyCallable_CheckNumberOfParameters(pyCallable, 2) && 1561 | !PyCallable_CheckNumberOfParameters(pyCallable, 3)) { 1562 | PyErr_Format( 1563 | PyExc_ValueError, 1564 | "expected a callable object 2 or 3 parameters " 1565 | "(percent: int, cancel: bool, context: Optional[Any] = None) -> int"); 1566 | return nullptr; 1567 | } 1568 | 1569 | Py_XDECREF(pyProgressCallback[0]); 1570 | Py_XDECREF(pyProgressCallback[1]); 1571 | 1572 | pyProgressCallback[0] = pyCallable; 1573 | pyProgressCallback[1] = pyContext; 1574 | 1575 | Py_INCREF(pyCallable); 1576 | Py_XINCREF(pyContext); 1577 | 1578 | auto callbackWrapper = [](EdsUInt32 inPercent, EdsVoid *inContext, EdsBool *outCancel) -> EdsError { 1579 | PyGILState_STATE gstate; 1580 | gstate = PyGILState_Ensure(); 1581 | 1582 | PyObject** pyContext(static_cast(inContext)); 1583 | PyObject* pyPercent(PyLong_FromUnsignedLong(inPercent)); 1584 | PyObject* pyCancel(PyBool_FromLong(*outCancel)); 1585 | PyObject* pyRetVal(nullptr); 1586 | if (pyContext[1] == nullptr) { 1587 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyPercent, pyCancel, nullptr); 1588 | } 1589 | else { 1590 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyPercent, pyCancel, pyContext[1], nullptr); 1591 | } 1592 | if (pyRetVal == nullptr) { 1593 | PyErr_Format(PyExc_ValueError, "unable to call the callback"); 1594 | Py_DECREF(pyPercent); 1595 | Py_DECREF(pyCancel); 1596 | return EDS_ERR_INVALID_FN_POINTER; 1597 | } 1598 | 1599 | unsigned long retVal(EDS_ERR_OK); 1600 | if (PyLong_Check(pyRetVal)) { 1601 | retVal = PyLong_AsUnsignedLong(pyRetVal); 1602 | } 1603 | Py_DECREF(pyRetVal); 1604 | Py_DECREF(pyPercent); 1605 | Py_DECREF(pyCancel); 1606 | 1607 | PyGILState_Release(gstate); 1608 | return retVal; 1609 | }; 1610 | 1611 | unsigned long retVal(EdsSetProgressCallback( 1612 | edsObj->edsObj, 1613 | callbackWrapper, 1614 | static_cast(progressOption), 1615 | pyProgressCallback)); 1616 | 1617 | if (retVal != EDS_ERR_OK) { 1618 | Py_DECREF(pyCallable); 1619 | Py_XDECREF(pyContext); 1620 | PyCheck_EDSERROR(retVal); 1621 | } 1622 | Py_RETURN_NONE; 1623 | } 1624 | 1625 | 1626 | PyDoc_STRVAR(PyEds_CreateImageRef__doc__, 1627 | "Creates an image object from an image file.\n" 1628 | "Without modification, stream objects cannot be worked with as images.\n" 1629 | "Thus, when extracting images from image files,\n" 1630 | "\tyou must use this API to create image objects.\n" 1631 | "The image object created this way can be used to get image information\n" 1632 | "\t(such as the height and width, number of color components, and\n" 1633 | "\tresolution), thumbnail image data, and the image data itself.\n\n" 1634 | ":param EdsObject stream: The stream.\n" 1635 | ":raises EdsError: Any of the sdk errors.\n" 1636 | ":return EdsObject: The image."); 1637 | 1638 | static PyObject* PyEds_CreateImageRef(PyObject *Py_UNUSED(self), PyObject *pyStream){ 1639 | PyEdsObject *pyEdsObject(PyToEds(pyStream)); 1640 | if (pyEdsObject == nullptr) { 1641 | return nullptr; 1642 | } 1643 | EdsImageRef outImage; 1644 | unsigned long retVal(EdsCreateImageRef(pyEdsObject->edsObj, &outImage)); 1645 | PyCheck_EDSERROR(retVal); 1646 | 1647 | PyObject *pyImage = PyEdsObject_New(outImage); 1648 | assert(pyImage); 1649 | return pyImage; 1650 | } 1651 | 1652 | 1653 | PyDoc_STRVAR(PyEds_GetImageInfo__doc__, 1654 | "Gets image information from a designated image object.\n" 1655 | "Here, image information means the image width and height,\n" 1656 | "\tnumber of color components, resolution, and effective image area.\n\n" 1657 | ":param EdsObject image: The image.\n" 1658 | ":param ImageSource image_source: Of the various image data items in the image file,\n" 1659 | "\tdesignate the type of image data representing the\n" 1660 | "\tinformation you want to get. Designate the image as\n" 1661 | "\tdefined in Enum ImageSource.\n" 1662 | "\t\tImageSource.FullView\n" 1663 | "\t\t\tThe image itself (a full-sized image)\n" 1664 | "\t\tImageSource.Thumbnail\n" 1665 | "\t\t\tA thumbnail image\n" 1666 | "\t\tImageSource.Preview\n" 1667 | "\t\t\tA preview image\n" 1668 | ":raises EdsError: Any of the sdk errors.\n" 1669 | ":return Dict[str, Any]: Stores the image data information designated\n" 1670 | "\tin inImageSource."); 1671 | 1672 | static PyObject* PyEds_GetImageInfo(PyObject *Py_UNUSED(self), PyObject *args){ 1673 | PyObject *pyImage; 1674 | unsigned long imageSource; 1675 | 1676 | if (!PyArg_ParseTuple(args, "OK:GetImageInfo", &pyImage, &imageSource)) { 1677 | return nullptr; 1678 | } 1679 | PyEdsObject *pyEdsObject(PyToEds(pyImage)); 1680 | if (pyEdsObject == nullptr) { 1681 | return nullptr; 1682 | } 1683 | 1684 | EdsImageInfo imageInfo; 1685 | unsigned long retVal(EdsGetImageInfo( 1686 | pyEdsObject->edsObj, static_cast(imageSource), &imageInfo)); 1687 | PyCheck_EDSERROR(retVal); 1688 | 1689 | PyObject *pyDirItemInfo = EDS::PyDict_FromEdsImageInfo(imageInfo); 1690 | return pyDirItemInfo; 1691 | } 1692 | 1693 | 1694 | PyDoc_STRVAR(PyEds_GetImage__doc__, 1695 | "Gets designated image data from an image file, in the form of a\n" 1696 | "\tdesignated rectangle.\n" 1697 | "Returns uncompressed results for JPEGs and processed results\n" 1698 | "\tin the designated pixel order (RGB, Top-down BGR, and so on) for\n" 1699 | "\tRAW images.\n" 1700 | "Additionally, by designating the input/output rectangle,\n" 1701 | "\tit is possible to get reduced, enlarged, or partial images.\n" 1702 | "However, because images corresponding to the designated output rectangle\n" 1703 | "\tare always returned by the SDK, the SDK does not take the aspect\n" 1704 | "\tratio into account.\n" 1705 | "To maintain the aspect ratio, you must keep the aspect ratio in mind\n" 1706 | "\twhen designating the rectangle.\n\n" 1707 | ":param EdsObject image: The image for which to get the image data.\n" 1708 | ":param ImageSource image_source: Designate the type of image data to get\n" 1709 | "\tfrom the image file (thumbnail, preview, and so on).\n" 1710 | ":param TargetImageType image_type: Designate the output image type. Because\n" 1711 | "\tthe output format of GetImage may only be RGB, only\n" 1712 | "\tTargetImageType.RGB or TargetImageType.RGB16 can be designated.\n" 1713 | "\tHowever, image types exceeding the resolution of" 1714 | "\timage_source cannot be designated.\n" 1715 | ":param Dict[str, Dict[str, int]] source_rect: Designate the coordinates\n" 1716 | "\tand size of the rectangle to be retrieved from the source image.\n" 1717 | ":param Dict[str, int] dest_size: Designate the rectangle size for output.\n" 1718 | ":raises EdsError: Any of the sdk errors.\n" 1719 | ":return EdsObject: the memory or file stream for output of the image."); 1720 | 1721 | static PyObject* PyEds_GetImage(PyObject *Py_UNUSED(self), PyObject *args){ 1722 | PyObject *pyImage; 1723 | unsigned long imageSource; 1724 | unsigned long imageType; 1725 | PyObject *pySourceRect; 1726 | PyObject *pyDestSize; 1727 | 1728 | if (!PyArg_ParseTuple( 1729 | args, "OKKOO:GetImage", &pyImage, &imageSource, &imageType, 1730 | &PyDict_Type, &pySourceRect, &PyDict_Type, &pyDestSize)) { 1731 | return nullptr; 1732 | } 1733 | 1734 | PyEdsObject *pyEdsObject(PyToEds(pyImage)); 1735 | EdsRect sourceRect; 1736 | EdsSize destSize; 1737 | EdsStreamRef streamRef(nullptr); 1738 | 1739 | if (pyEdsObject == nullptr || 1740 | !EDS::PyDict_ToEdsRect(pySourceRect, sourceRect) || 1741 | !EDS::PyDict_ToEdsSize(pyDestSize, destSize)) { 1742 | return nullptr; 1743 | } 1744 | 1745 | unsigned long retVal(EdsGetImage( 1746 | pyEdsObject->edsObj, 1747 | static_cast(imageSource), 1748 | static_cast(imageType), 1749 | sourceRect, destSize, streamRef)); 1750 | PyCheck_EDSERROR(retVal); 1751 | 1752 | PyObject *pyStream = PyEdsObject_New(streamRef); 1753 | assert(pyStream); 1754 | return pyStream; 1755 | } 1756 | 1757 | 1758 | PyDoc_STRVAR(PyEds_CreateEvfImageRef__doc__, 1759 | "Creates an object used to get the live view image data set.\n\n" 1760 | ":param EdsObject stream: The stream which opened to get EVF JPEG image.\n" 1761 | ":raises EdsError: Any of the sdk errors.\n" 1762 | ":return EdsObject: The EVFData."); 1763 | 1764 | static PyObject* PyEds_CreateEvfImageRef(PyObject *Py_UNUSED(self), PyObject *pyStream){ 1765 | PyEdsObject *pyEdsObject(PyToEds(pyStream)); 1766 | if (pyEdsObject == nullptr) { 1767 | return nullptr; 1768 | } 1769 | EdsEvfImageRef outImage; 1770 | unsigned long retVal(EdsCreateEvfImageRef(pyEdsObject->edsObj, &outImage)); 1771 | PyCheck_EDSERROR(retVal); 1772 | 1773 | PyObject *pyImage = PyEdsObject_New(outImage); 1774 | assert(pyImage); 1775 | return pyImage; 1776 | } 1777 | 1778 | 1779 | PyDoc_STRVAR(PyEds_DownloadEvfImage__doc__, 1780 | "Downloads the live view image data set for a camera currently in live view mode.\n" 1781 | "Live view can be started by using the property ID:PropID.Evf_OutputDevice and\n" 1782 | "data:OutputDevice.PC to call SetPropertyData.\n" 1783 | "In addition to image data, information such as zoom, focus position, and histogram data\n" 1784 | "is included in the image data set. Image data is saved in a stream maintained by EdsEvfImageRef.\n" 1785 | "GetPropertyData can be used to get information such as the zoom, focus position, etc.\n" 1786 | "Although the information of the zoom and focus position can be obtained from EvfImageRef,\n" 1787 | "settings are applied to EdsCameraRef.\n\n" 1788 | ":param EdsObject camera: The camera.\n" 1789 | ":param EdsObject evf_image: The EVFData.\n" 1790 | ":raises EdsError: Any of the sdk errors."); 1791 | 1792 | static PyObject* PyEds_DownloadEvfImage(PyObject *Py_UNUSED(self), PyObject *args){ 1793 | PyObject *pyCamera; 1794 | PyObject *pyEvfImage; 1795 | if (!PyArg_ParseTuple(args, "OO:DownloadEvfImage", &pyCamera, &pyEvfImage)) { 1796 | return nullptr; 1797 | } 1798 | PyEdsObject *pyEdsCamera(PyToEds(pyCamera)); 1799 | PyEdsObject *pyEdsEvfImage(PyToEds(pyEvfImage)); 1800 | if (pyEdsCamera == nullptr || pyEdsEvfImage == nullptr) { 1801 | return nullptr; 1802 | } 1803 | 1804 | unsigned long retVal(EdsDownloadEvfImage( 1805 | pyEdsCamera->edsObj, pyEdsEvfImage->edsObj)); 1806 | PyCheck_EDSERROR(retVal); 1807 | 1808 | Py_RETURN_NONE; 1809 | } 1810 | 1811 | 1812 | static PyObject *pyCameraAddedCallback[2] = {nullptr, nullptr}; 1813 | 1814 | PyDoc_STRVAR(PyEds_SetCameraAddedHandler__doc__, 1815 | "Registers a callback function for when a camera is detected.\n\n" 1816 | ":param Callable callback: the callback called when a camera is connected.\n" 1817 | "\tExpected signature (context: Any = None) -> int.\n" 1818 | ":raises EdsError: Any of the sdk errors."); 1819 | 1820 | static PyObject* PyEds_SetCameraAddedHandler(PyObject *Py_UNUSED(self), PyObject *args) { 1821 | PyObject* pyCallable; 1822 | PyObject* pyContext(nullptr); 1823 | 1824 | if (!PyArg_ParseTuple(args, "O|O:EdsSetCameraAddedHandler", &pyCallable, &pyContext)) { 1825 | return nullptr; 1826 | } 1827 | 1828 | if (pyCallable == Py_None || !PyCallable_Check(pyCallable)){ 1829 | PyErr_Format(PyExc_ValueError, "expected a callable object"); 1830 | return nullptr; 1831 | } 1832 | 1833 | if (!PyCallable_CheckNumberOfParameters(pyCallable, 0) || 1834 | !PyCallable_CheckNumberOfParameters(pyCallable, 1)) { 1835 | PyErr_Format(PyExc_ValueError, 1836 | "expected a callable object with 0 or 1 parameters" 1837 | "(context: Any = None) -> int"); 1838 | return nullptr; 1839 | } 1840 | 1841 | Py_XDECREF(pyCameraAddedCallback[0]); 1842 | Py_XDECREF(pyCameraAddedCallback[1]); 1843 | 1844 | pyCameraAddedCallback[0] = pyCallable; 1845 | pyCameraAddedCallback[1] = pyContext; 1846 | 1847 | Py_INCREF(pyCallable); 1848 | Py_XINCREF(pyContext); 1849 | 1850 | auto callbackWrapper = [](EdsVoid* inContext) -> EdsError { 1851 | PyGILState_STATE gstate; 1852 | gstate = PyGILState_Ensure(); 1853 | 1854 | PyObject** pyContext = static_cast(inContext); 1855 | PyObject* pyRetVal{nullptr}; 1856 | if (pyContext[1] == nullptr) { 1857 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], nullptr); 1858 | } 1859 | else { 1860 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyContext[1], nullptr); 1861 | } 1862 | if (pyRetVal == nullptr) { 1863 | PyErr_Format(PyExc_ValueError, "unable to call the callback"); 1864 | return EDS_ERR_INVALID_FN_POINTER; 1865 | } 1866 | unsigned long retVal(EDS_ERR_OK); 1867 | if (PyLong_Check(pyRetVal)) { 1868 | retVal = PyLong_AsUnsignedLong(pyRetVal); 1869 | } 1870 | Py_DECREF(pyRetVal); 1871 | 1872 | PyGILState_Release(gstate); 1873 | return retVal; 1874 | }; 1875 | 1876 | unsigned long retVal( 1877 | EdsSetCameraAddedHandler( 1878 | callbackWrapper, 1879 | pyCameraAddedCallback)); 1880 | 1881 | if (retVal != EDS_ERR_OK) { 1882 | Py_DECREF(pyCallable); 1883 | Py_XDECREF(pyContext); 1884 | PyCheck_EDSERROR(retVal); 1885 | } 1886 | Py_RETURN_NONE; 1887 | } 1888 | 1889 | 1890 | static PyObject *pySetPropertyCallback[2] = {nullptr, nullptr}; 1891 | 1892 | PyDoc_STRVAR(PyEds_SetPropertyEventHandler__doc__, 1893 | "Registers a callback function for receiving status\n" 1894 | "\tchange notification events for property states on a camera.\n\n" 1895 | ":param EdsObject camera: the camera object.\n" 1896 | ":param PropertyEvent event: the event to be supplemented.\n" 1897 | "\tTo designate all events, use PropertyEvent.All.\n" 1898 | ":param Callable callback: the callback for receiving events.\n" 1899 | "\tExpected signature\n" 1900 | "\t\t(event: StateEvent, prop_id: PropID, param: int, context: Any = None) -> int.\n" 1901 | ":raises EdsError: Any of the sdk errors."); 1902 | 1903 | static PyObject* PyEds_SetPropertyEventHandler(PyObject *Py_UNUSED(self), PyObject *args) { 1904 | PyObject* pyObj; 1905 | unsigned long event; 1906 | PyObject* pyCallable; 1907 | PyObject* pyContext(nullptr); 1908 | 1909 | if (!PyArg_ParseTuple(args, "OkO|O:EdsSetPropertyEventHandler", &pyObj, &event, &pyCallable, &pyContext)) { 1910 | return nullptr; 1911 | } 1912 | 1913 | PyEdsObject* edsObj = PyToEds(pyObj); 1914 | if (!edsObj) { 1915 | return nullptr; 1916 | } 1917 | 1918 | if (pyCallable == Py_None || !PyCallable_Check(pyCallable)){ 1919 | PyErr_Format(PyExc_ValueError, "expected a callable object"); 1920 | return nullptr; 1921 | } 1922 | 1923 | if (!PyCallable_CheckNumberOfParameters(pyCallable, 3) 1924 | && !PyCallable_CheckNumberOfParameters(pyCallable, 4)) { 1925 | PyErr_Format(PyExc_ValueError, 1926 | "expected a callable object with 3 or 4 parameters " 1927 | "(event: StateEvent, propertyID: PropID, param: int, context: Any = None) -> int"); 1928 | return nullptr; 1929 | } 1930 | 1931 | Py_XDECREF(pySetPropertyCallback[0]); 1932 | Py_XDECREF(pySetPropertyCallback[1]); 1933 | 1934 | pySetPropertyCallback[0] = pyCallable; 1935 | pySetPropertyCallback[1] = pyContext; 1936 | 1937 | Py_INCREF(pyCallable); 1938 | Py_XINCREF(pyContext); 1939 | 1940 | auto callbackWrapper = [](EdsPropertyEvent inEvent, EdsPropertyID inPropertyID, EdsUInt32 inParam, EdsVoid* inContext) -> EdsError { 1941 | 1942 | PyGILState_STATE gstate; 1943 | gstate = PyGILState_Ensure(); 1944 | 1945 | PyObject **pyContext = static_cast(inContext); 1946 | PyObject *pyEvent = GetEnum("edsdk.constants", "PropertyEvent", inEvent); 1947 | if (pyEvent == nullptr) { 1948 | PyErr_Clear(); 1949 | std::cout << "Unknown Property Event: " << inEvent << std::endl; 1950 | pyEvent = PyLong_FromUnsignedLong(inEvent); 1951 | } 1952 | PyObject *pyPropertyID = GetEnum("edsdk.constants", "PropID", inPropertyID); 1953 | if (pyPropertyID == nullptr) { 1954 | PyErr_Clear(); 1955 | std::cout << "Unknown Property ID: " << inPropertyID << std::endl; 1956 | pyPropertyID = PyLong_FromUnsignedLong(inPropertyID); 1957 | } 1958 | PyObject *pyParam = PyLong_FromUnsignedLong(inParam); 1959 | 1960 | PyObject *pyRetVal{nullptr}; 1961 | if (pyContext[1] == nullptr){ 1962 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyEvent, pyPropertyID, pyParam, nullptr); 1963 | } 1964 | else { 1965 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyEvent, pyPropertyID, pyParam, pyContext[1], nullptr); 1966 | } 1967 | if (pyRetVal == nullptr) { 1968 | PyErr_Format(PyExc_ValueError, "unable to call the callback"); 1969 | Py_DECREF(pyEvent); 1970 | Py_DECREF(pyPropertyID); 1971 | Py_DECREF(pyParam); 1972 | return EDS_ERR_INVALID_FN_POINTER; 1973 | } 1974 | 1975 | unsigned long retVal(EDS_ERR_OK); 1976 | if (PyLong_Check(pyRetVal)) { 1977 | retVal = PyLong_AsUnsignedLong(pyRetVal); 1978 | } 1979 | Py_DECREF(pyRetVal); 1980 | Py_DECREF(pyEvent); 1981 | Py_DECREF(pyParam); 1982 | Py_DECREF(pyPropertyID); 1983 | 1984 | PyGILState_Release(gstate); 1985 | return retVal; 1986 | }; 1987 | 1988 | unsigned long retVal(EdsSetPropertyEventHandler( 1989 | edsObj->edsObj, event, callbackWrapper, pySetPropertyCallback)); 1990 | 1991 | if (retVal != EDS_ERR_OK) { 1992 | Py_DECREF(pyCallable); 1993 | Py_XDECREF(pyContext); 1994 | PyCheck_EDSERROR(retVal); 1995 | } 1996 | Py_RETURN_NONE; 1997 | 1998 | } 1999 | 2000 | 2001 | static PyObject *pySetObjectCallback[2] = {nullptr, nullptr}; 2002 | 2003 | PyDoc_STRVAR(PyEds_SetObjectEventHandler__doc__, 2004 | "Registers a callback function for receiving status\n" 2005 | "\tchange notification events for objects on a remote camera\n" 2006 | "Here, object means volumes representing memory cards, files and directories,\n" 2007 | "\tand shot images stored in memory, in particular.\n\n" 2008 | ":param EdsObject camera: the camera object.\n" 2009 | ":param ObjectEvent event: the event to be supplemented.\n" 2010 | "\tTo designate all events, use ObjectEvent.All.\n" 2011 | ":param Callable callback: the callback for receiving events.\n" 2012 | "\tExpected signature (event: ObjectEvent, obj_ref: PyEdsObject, context: Any = None) -> int.\n" 2013 | ":raises EdsError: Any of the sdk errors."); 2014 | 2015 | static PyObject* PyEds_SetObjectEventHandler(PyObject *Py_UNUSED(self), PyObject *args) { 2016 | PyObject* pyObj; 2017 | unsigned long event; 2018 | PyObject* pyCallable; 2019 | PyObject* pyContext(nullptr); 2020 | if (!PyArg_ParseTuple(args, "OkO|O:EdsSetObjectEventHandler", &pyObj, &event, &pyCallable, &pyContext)) { 2021 | return nullptr; 2022 | } 2023 | 2024 | PyEdsObject* edsObj = PyToEds(pyObj); 2025 | if (!edsObj) { 2026 | return nullptr; 2027 | } 2028 | 2029 | if (pyCallable == Py_None || !PyCallable_Check(pyCallable)){ 2030 | PyErr_Format(PyExc_ValueError, "expected a callable object"); 2031 | return nullptr; 2032 | } 2033 | 2034 | if (!PyCallable_CheckNumberOfParameters(pyCallable, 2) && 2035 | !PyCallable_CheckNumberOfParameters(pyCallable, 3)) { 2036 | PyErr_Format(PyExc_ValueError, 2037 | "expected a callable object with 2 or 3 parameters " 2038 | "(event: ObjectEvent, obj_ref: PyEdsObject, context: Any = None) -> int"); 2039 | return nullptr; 2040 | } 2041 | 2042 | Py_XDECREF(pySetObjectCallback[0]); 2043 | Py_XDECREF(pySetObjectCallback[1]); 2044 | 2045 | pySetObjectCallback[0] = pyCallable; 2046 | pySetObjectCallback[1] = pyContext; 2047 | 2048 | Py_INCREF(pyCallable); 2049 | Py_XINCREF(pyContext); 2050 | 2051 | auto callbackWrapper = [](EdsStateEvent inEvent, EdsBaseRef inRef, EdsVoid* inContext) -> EdsError { 2052 | 2053 | PyGILState_STATE gstate; 2054 | gstate = PyGILState_Ensure(); 2055 | 2056 | PyObject **pyContext = static_cast(inContext); 2057 | PyObject *pyEvent = GetEnum("edsdk.constants", "ObjectEvent", inEvent); 2058 | if (pyEvent == nullptr) { 2059 | PyErr_Clear(); 2060 | std::cout << "Unknown Object Event: " << inEvent << std::endl; 2061 | pyEvent = PyLong_FromUnsignedLong(inEvent); 2062 | } 2063 | PyObject* pyInRef = PyEdsObject_New(inRef); 2064 | 2065 | PyObject* pyRetVal(nullptr); 2066 | if (pyContext[1] == nullptr){ 2067 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyEvent, pyInRef, nullptr); 2068 | } 2069 | else { 2070 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyEvent, pyInRef, pyContext[1], nullptr); 2071 | } 2072 | if (pyRetVal == nullptr) { 2073 | PyErr_Format(PyExc_ValueError, "unable to call the callback"); 2074 | Py_DECREF(pyEvent); 2075 | Py_DECREF(pyInRef); 2076 | return EDS_ERR_INVALID_FN_POINTER; 2077 | } 2078 | unsigned long retVal(EDS_ERR_OK); 2079 | if (PyLong_Check(pyRetVal)) { 2080 | retVal = PyLong_AsUnsignedLong(pyRetVal); 2081 | } 2082 | Py_DECREF(pyEvent); 2083 | Py_DECREF(pyInRef); 2084 | Py_DECREF(pyRetVal); 2085 | 2086 | PyGILState_Release(gstate); 2087 | return retVal; 2088 | }; 2089 | 2090 | unsigned long retVal(EdsSetObjectEventHandler( 2091 | edsObj->edsObj, event, callbackWrapper, pySetObjectCallback)); 2092 | 2093 | if (retVal != EDS_ERR_OK) { 2094 | Py_DECREF(pyCallable); 2095 | Py_XDECREF(pyContext); 2096 | PyCheck_EDSERROR(retVal); 2097 | } 2098 | Py_RETURN_NONE; 2099 | } 2100 | 2101 | 2102 | PyObject *pySetCameraStateCallback[2] = {nullptr, nullptr}; 2103 | 2104 | PyDoc_STRVAR(PyEds_SetCameraStateEventHandler__doc__, 2105 | "Registers a callback function for receiving status\n" 2106 | "\tchange notification events for property states on a camera\n\n" 2107 | ":param EdsObject camera: the camera object.\n" 2108 | ":param StateEvent event: the event to be supplemented.\n" 2109 | "\tTo designate all events, use StateEvent.All.\n" 2110 | ":param Callable callback: the callback for receiving the events.\n" 2111 | "\tExpected signature\n" 2112 | "\t\t(event: StateEvent, event_data: int, context: Any = None) -> int.\n" 2113 | ":raises EdsError: Any of the sdk errors."); 2114 | 2115 | static PyObject *PyEds_SetCameraStateEventHandler(PyObject *Py_UNUSED(self), PyObject *args) { 2116 | PyObject *pyObj; 2117 | unsigned long event; 2118 | PyObject *pyCallable; 2119 | PyObject* pyContext(nullptr); 2120 | if (!PyArg_ParseTuple(args, "OkO|O:EdsSetCameraStateEventHandler", &pyObj, &event, &pyCallable, &pyContext)) { 2121 | return nullptr; 2122 | } 2123 | PyEdsObject* edsObj = PyToEds(pyObj); 2124 | if (!edsObj) { 2125 | return nullptr; 2126 | } 2127 | 2128 | if (pyCallable == Py_None || !PyCallable_Check(pyCallable)){ 2129 | 2130 | PyErr_Format(PyExc_ValueError, "expected a callable object"); 2131 | return nullptr; 2132 | } 2133 | 2134 | if (!PyCallable_CheckNumberOfParameters(pyCallable, 2) 2135 | && !PyCallable_CheckNumberOfParameters(pyCallable, 3)) { 2136 | PyErr_Format(PyExc_ValueError, 2137 | "expected a callable object with 2 or 3 parameters " 2138 | "(event: StateEvent, event_data: int, context: Any = None) -> int"); 2139 | return nullptr; 2140 | } 2141 | 2142 | Py_XDECREF(pySetCameraStateCallback[0]); 2143 | Py_XDECREF(pySetCameraStateCallback[1]); 2144 | 2145 | pySetCameraStateCallback[0] = pyCallable; 2146 | pySetCameraStateCallback[1] = pyContext; 2147 | 2148 | Py_INCREF(pyCallable); 2149 | Py_XINCREF(pyContext); 2150 | 2151 | auto callbackWrapper = [](EdsStateEvent inEvent, EdsUInt32 inEventData, EdsVoid* inContext) -> EdsError { 2152 | PyGILState_STATE gstate; 2153 | gstate = PyGILState_Ensure(); 2154 | 2155 | PyObject *pyEvent = GetEnum("edsdk.constants", "StateEvent", inEvent); 2156 | if (pyEvent == nullptr) { 2157 | PyErr_Clear(); 2158 | std::cout << "Unknown State Event: " << inEvent << std::endl; 2159 | pyEvent = PyLong_FromUnsignedLong(inEvent); 2160 | } 2161 | PyObject *pyEventData = PyLong_FromUnsignedLong(inEventData); 2162 | PyObject **pyContext = static_cast(inContext); 2163 | PyObject *pyRetVal(nullptr); 2164 | if (pyContext[1] == nullptr) { 2165 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyEvent, pyEventData, nullptr); 2166 | } 2167 | else { 2168 | pyRetVal = PyObject_CallFunctionObjArgs(pyContext[0], pyEvent, pyEventData, pyContext[1], nullptr); 2169 | } 2170 | if (pyRetVal == nullptr) { 2171 | PyErr_Format(PyExc_ValueError, "unable to call the callback"); 2172 | Py_DECREF(pyEvent); 2173 | Py_DECREF(pyEventData); 2174 | return EDS_ERR_INVALID_FN_POINTER; 2175 | } 2176 | 2177 | unsigned long retVal(EDS_ERR_OK); 2178 | if (PyLong_Check(pyRetVal)) { 2179 | retVal = PyLong_AsUnsignedLong(pyRetVal); 2180 | } 2181 | Py_DECREF(pyEvent); 2182 | Py_DECREF(pyEventData); 2183 | Py_DECREF(pyRetVal); 2184 | 2185 | PyGILState_Release(gstate); 2186 | return retVal; 2187 | }; 2188 | 2189 | unsigned long retVal( 2190 | EdsSetCameraStateEventHandler( 2191 | edsObj->edsObj, event, 2192 | callbackWrapper, 2193 | pySetCameraStateCallback)); 2194 | 2195 | if (retVal != EDS_ERR_OK) { 2196 | Py_DECREF(pyCallable); 2197 | Py_XDECREF(pyContext); 2198 | PyCheck_EDSERROR(retVal); 2199 | } 2200 | Py_RETURN_NONE; 2201 | } 2202 | 2203 | 2204 | PyDoc_STRVAR(PyEds_GetEvent__doc__, 2205 | "This function acquires an event.\n" 2206 | "In console application, please call this function regularly to acquire\n" 2207 | "\tthe event from a camera.\n\n" 2208 | ":raises EdsError: Any of the sdk errors."); 2209 | 2210 | static PyObject* PyEds_GetEvent(PyObject *Py_UNUSED(self)) { 2211 | unsigned long retVal(EdsGetEvent()); 2212 | PyCheck_EDSERROR(retVal); 2213 | Py_RETURN_NONE; 2214 | } 2215 | 2216 | 2217 | PyMethodDef methodTable[] = { 2218 | // Basic functions 2219 | {"InitializeSDK", (PyCFunction) PyEds_InitializeSDK, METH_NOARGS, PyEds_InitializeSDK__doc__}, 2220 | {"TerminateSDK", (PyCFunction) PyEds_TerminateSDK, METH_NOARGS, PyEds_TerminateSDK__doc__}, 2221 | 2222 | // Item-tree operating functions 2223 | {"GetChildCount", (PyCFunction) PyEds_GetChildCount, METH_VARARGS, PyEds_GetChildCount__doc__}, 2224 | {"GetChildAtIndex", (PyCFunction) PyEds_GetChildAtIndex, METH_VARARGS, PyEds_GetChildAtIndex__doc__}, 2225 | {"GetParent", (PyCFunction) PyEds_GetParent, METH_O, PyEds_GetParent__doc__}, 2226 | 2227 | // Property operating functions 2228 | {"GetPropertySize", (PyCFunction) PyEds_GetPropertySize, METH_VARARGS, PyEds_GetPropertySize__doc__}, 2229 | {"GetPropertyData", (PyCFunction) PyEds_GetPropertyData, METH_VARARGS, PyEds_GetPropertyData__doc__}, 2230 | {"SetPropertyData", (PyCFunction) PyEds_SetPropertyData, METH_VARARGS, PyEds_SetPropertyData__doc__}, 2231 | {"GetPropertyDesc", (PyCFunction) PyEds_GetPropertyDesc, METH_VARARGS, PyEds_GetPropertyDesc__doc__}, 2232 | 2233 | // Device-list and device operating functions 2234 | {"GetCameraList", (PyCFunction) PyEds_GetCameraList, METH_NOARGS, PyEds_GetCameraList__doc__}, 2235 | 2236 | // Camera operating functions 2237 | {"GetDeviceInfo", (PyCFunction) PyEds_GetDeviceInfo, METH_O, PyEds_GetDeviceInfo__doc__}, 2238 | {"OpenSession", (PyCFunction) PyEds_OpenSession, METH_VARARGS, PyEds_OpenSession__doc__}, 2239 | {"CloseSession", (PyCFunction) PyEds_CloseSession, METH_VARARGS, PyEds_CloseSession__doc__}, 2240 | {"SendCommand", (PyCFunction) PyEds_SendCommand, METH_VARARGS, PyEds_SendCommand__doc__}, 2241 | {"SendStatusCommand", (PyCFunction) PyEds_SendStatusCommand, METH_VARARGS, PyEds_SendStatusCommand__doc__}, 2242 | {"SetCapacity", (PyCFunction) PyEds_SetCapacity, METH_VARARGS, PyEds_SetCapacity__doc__}, 2243 | 2244 | // Volume operating functions 2245 | {"GetVolumeInfo", (PyCFunction) PyEds_GetVolumeInfo, METH_O, PyEds_GetVolumeInfo__doc__}, 2246 | {"FormatVolume", (PyCFunction) PyEds_FormatVolume, METH_O, PyEds_FormatVolume__doc__}, 2247 | 2248 | // Directory-item operating functions 2249 | {"GetDirectoryItemInfo", (PyCFunction) PyEds_GetDirectoryItemInfo, METH_O, PyEds_GetDirectoryItemInfo__doc__}, 2250 | {"DeleteDirectoryItem", (PyCFunction) PyEds_DeleteDirectoryItem, METH_O, PyEds_DeleteDirectoryItem__doc__}, 2251 | {"Download", (PyCFunction) PyEds_Download, METH_VARARGS, PyEds_Download__doc__}, 2252 | {"DownloadCancel", (PyCFunction) PyEds_DownloadCancel, METH_O, PyEds_DownloadCancel__doc__}, 2253 | {"DownloadComplete", (PyCFunction) PyEds_DownloadComplete, METH_O, PyEds_DownloadComplete__doc__}, 2254 | {"DownloadThumbnail", (PyCFunction) PyEds_DownloadThumbnail, METH_VARARGS, PyEds_DownloadThumbnail__doc__}, 2255 | {"GetAttribute", (PyCFunction) PyEds_GetAttribute, METH_O, PyEds_GetAttribute__doc__}, 2256 | {"SetAttribute", (PyCFunction) PyEds_SetAttribute, METH_VARARGS, PyEds_SetAttribute__doc__}, 2257 | 2258 | // Stream operating functions 2259 | {"CreateFileStream", (PyCFunction) PyEds_CreateFileStream, METH_VARARGS, PyEds_CreateFileStream__doc__}, 2260 | {"CreateMemoryStream", (PyCFunction) PyEds_CreateMemoryStream, METH_O, PyEds_CreateMemoryStream__doc__}, 2261 | {"CreateFileStreamEx", (PyCFunction) PyEds_CreateFileStreamEx, METH_VARARGS, PyEds_CreateFileStreamEx__doc__}, 2262 | {"CreateMemoryStreamFromPointer", (PyCFunction) PyEds_CreateMemoryStreamFromPointer, METH_O, PyEds_CreateMemoryStreamFromPointer__doc__}, 2263 | // {"GetPointer", (PyCFunction) PyEds_GetPointer, METH_O, PyEds_GetPointer__doc__}, 2264 | // {"Read", (PyCFunction) PyEds_Read, METH_VARARGS, PyEds_Read__doc__}, 2265 | // {"Write", (PyCFunction) PyEds_Write, METH_VARARGS, PyEds_Write__doc__}, 2266 | // {"Seek", (PyCFunction) PyEds_Seek, METH_VARARGS, PyEds_Seek__doc__}, 2267 | {"GetPosition", (PyCFunction) PyEds_GetPosition, METH_O, PyEds_GetPosition__doc__}, 2268 | {"GetLength", (PyCFunction) PyEds_GetLength, METH_O, PyEds_GetLength__doc__}, 2269 | {"CopyData", (PyCFunction) PyEds_CopyData, METH_VARARGS, PyEds_CopyData__doc__}, 2270 | {"SetProgressCallback", (PyCFunction) PyEds_SetProgressCallback, METH_VARARGS, PyEds_SetProgressCallback__doc__}, 2271 | 2272 | // Image operating functions 2273 | {"CreateImageRef", (PyCFunction) PyEds_CreateImageRef, METH_O, PyEds_CreateImageRef__doc__}, 2274 | {"GetImageInfo", (PyCFunction) PyEds_GetImageInfo, METH_VARARGS, PyEds_GetImageInfo__doc__}, 2275 | {"GetImage", (PyCFunction) PyEds_GetImage, METH_VARARGS, PyEds_GetImage__doc__}, 2276 | {"CreateEvfImageRef", (PyCFunction) PyEds_CreateEvfImageRef, METH_O, PyEds_CreateEvfImageRef__doc__}, 2277 | {"DownloadEvfImage", (PyCFunction) PyEds_DownloadEvfImage, METH_VARARGS, PyEds_DownloadEvfImage__doc__}, 2278 | 2279 | // Event handler registering functions 2280 | {"SetCameraAddedHandler", (PyCFunction) PyEds_SetCameraAddedHandler, METH_VARARGS, PyEds_SetCameraAddedHandler__doc__}, 2281 | {"SetPropertyEventHandler", (PyCFunction) PyEds_SetPropertyEventHandler, METH_VARARGS, PyEds_SetPropertyEventHandler__doc__}, 2282 | {"SetObjectEventHandler", (PyCFunction) PyEds_SetObjectEventHandler, METH_VARARGS, PyEds_SetObjectEventHandler__doc__}, 2283 | {"SetCameraStateEventHandler", (PyCFunction) PyEds_SetCameraStateEventHandler, METH_VARARGS, PyEds_SetCameraStateEventHandler__doc__}, 2284 | 2285 | // {"CreateStream", (PyCFunction) PyEds_CreateStream, METH_O, PyEds_CreateStream__doc__}, 2286 | {"GetEvent", (PyCFunction) PyEds_GetEvent, METH_NOARGS, PyEds_GetEvent__doc__}, 2287 | // {"SetFramePoint", (PyCFunction) PyEds_SetFramePoint, METH_VARARGS, PyEds_SetFramePoint__doc__}, 2288 | 2289 | {nullptr, nullptr, 0, nullptr} // Sentinel value ending the table 2290 | }; 2291 | 2292 | 2293 | PyModuleDef edsdkModule = { 2294 | PyModuleDef_HEAD_INIT, 2295 | "api", // Module name 2296 | "Python Wrapper for the Canon EDSDK", 2297 | -1, // Optional size of the module state memory 2298 | methodTable, 2299 | NULL, // Optional slot definitions 2300 | NULL, // Optional traversal function 2301 | NULL, // Optional clear function 2302 | NULL // Optional module deallocation function 2303 | }; 2304 | 2305 | 2306 | // The module init function 2307 | PyMODINIT_FUNC PyInit_api(void) { 2308 | PyEdsObjectType.tp_new = PyType_GenericNew; 2309 | if (PyType_Ready(&PyEdsObjectType) < 0) { 2310 | return NULL; 2311 | } 2312 | 2313 | PyObject *module = PyModule_Create(&edsdkModule); 2314 | if (module == NULL) { 2315 | return NULL; 2316 | } 2317 | Py_INCREF(&PyEdsObjectType); 2318 | PyModule_AddObject(module, "EdsObject", (PyObject *)&PyEdsObjectType); 2319 | 2320 | // Import the enums module, where "somepackage.enums" 2321 | // is the full name of the enums module 2322 | PyObject *constants = PyImport_ImportModule("edsdk.constants"); 2323 | if (constants == NULL) { 2324 | Py_DECREF(module); 2325 | return nullptr; 2326 | } 2327 | Py_DECREF(constants); 2328 | 2329 | PyEdsError = PyErr_NewException("edsdk.EdsError", NULL, NULL); 2330 | Py_XINCREF(PyEdsError); 2331 | 2332 | if (PyModule_AddObject(module, "EdsError", PyEdsError) < 0) { 2333 | Py_XDECREF(PyEdsError); 2334 | Py_CLEAR(PyEdsError); 2335 | Py_DECREF(module); 2336 | return nullptr; 2337 | } 2338 | 2339 | PyTypeObject *pyEdsError_type = (PyTypeObject *)PyEdsError; 2340 | pyEdsError_type->tp_str = PyEdsError_tp_str; 2341 | 2342 | PyObject *pyEdsErrorDescr = PyDescr_NewGetSet(pyEdsError_type, PyEdsError_getsetters); 2343 | if (PyDict_SetItem(pyEdsError_type->tp_dict, PyDescr_NAME(pyEdsErrorDescr), pyEdsErrorDescr) < 0) { 2344 | Py_DECREF(PyEdsError); 2345 | Py_CLEAR(PyEdsError); 2346 | Py_DECREF(pyEdsErrorDescr); 2347 | Py_DECREF(module); 2348 | return nullptr; 2349 | } 2350 | Py_DECREF(pyEdsErrorDescr); 2351 | 2352 | if (!PyEval_ThreadsInitialized()) { 2353 | PyEval_InitThreads(); 2354 | } 2355 | 2356 | return module; 2357 | }; 2358 | -------------------------------------------------------------------------------- /edsdk/edsdk_python.h: -------------------------------------------------------------------------------- 1 | #define PY_SSIZE_T_CLEAN 2 | #include 3 | -------------------------------------------------------------------------------- /edsdk/edsdk_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "edsdk_utils.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "EDSDKErrors.h" 7 | 8 | 9 | namespace EDS { 10 | char const *errorMessage(EdsError const error) { 11 | static std::map const errorMap = { 12 | /*----------------------------------------------------------------------- 13 | ED-SDK Error Code Masks 14 | ------------------------------------------------------------------------*/ 15 | {0x80000000UL, "EDS_ISSPECIFIC_MASK"}, 16 | {0x7F000000L, "EDS_COMPONENTID_MASK"}, 17 | {0x00FF0000L, "EDS_RESERVED_MASK"}, 18 | {0x0000FFFFL, "EDS_ERRORID_MASK"}, 19 | 20 | /*----------------------------------------------------------------------- 21 | ED-SDK Base Component IDs 22 | ------------------------------------------------------------------------*/ 23 | {0x01000000L, "EDS_CMP_ID_CLIENT_COMPONENTID"}, 24 | {0x02000000L, "EDS_CMP_ID_LLSDK_COMPONENTID"}, 25 | {0x03000000L, "EDS_CMP_ID_HLSDK_COMPONENTID"}, 26 | 27 | /*----------------------------------------------------------------------- 28 | ED-SDK Functin Success Code 29 | ------------------------------------------------------------------------*/ 30 | {0x00000000L, "EDS_ERR_OK"}, 31 | 32 | /*----------------------------------------------------------------------- 33 | ED-SDK Generic Error IDs 34 | ------------------------------------------------------------------------*/ 35 | /* Miscellaneous errors */ 36 | {0x00000001L, "EDS_ERR_UNIMPLEMENTED"}, 37 | {0x00000002L, "EDS_ERR_INTERNAL_ERROR"}, 38 | {0x00000003L, "EDS_ERR_MEM_ALLOC_FAILED"}, 39 | {0x00000004L, "EDS_ERR_MEM_FREE_FAILED"}, 40 | {0x00000005L, "EDS_ERR_OPERATION_CANCELLED"}, 41 | {0x00000006L, "EDS_ERR_INCOMPATIBLE_VERSION"}, 42 | {0x00000007L, "EDS_ERR_NOT_SUPPORTED"}, 43 | {0x00000008L, "EDS_ERR_UNEXPECTED_EXCEPTION"}, 44 | {0x00000009L, "EDS_ERR_PROTECTION_VIOLATION"}, 45 | {0x0000000AL, "EDS_ERR_MISSING_SUBCOMPONENT"}, 46 | {0x0000000BL, "EDS_ERR_SELECTION_UNAVAILABLE"}, 47 | 48 | /* File errors */ 49 | {0x00000020L, "EDS_ERR_FILE_IO_ERROR"}, 50 | {0x00000021L, "EDS_ERR_FILE_TOO_MANY_OPEN"}, 51 | {0x00000022L, "EDS_ERR_FILE_NOT_FOUND"}, 52 | {0x00000023L, "EDS_ERR_FILE_OPEN_ERROR"}, 53 | {0x00000024L, "EDS_ERR_FILE_CLOSE_ERROR"}, 54 | {0x00000025L, "EDS_ERR_FILE_SEEK_ERROR"}, 55 | {0x00000026L, "EDS_ERR_FILE_TELL_ERROR"}, 56 | {0x00000027L, "EDS_ERR_FILE_READ_ERROR"}, 57 | {0x00000028L, "EDS_ERR_FILE_WRITE_ERROR"}, 58 | {0x00000029L, "EDS_ERR_FILE_PERMISSION_ERROR"}, 59 | {0x0000002AL, "EDS_ERR_FILE_DISK_FULL_ERROR"}, 60 | {0x0000002BL, "EDS_ERR_FILE_ALREADY_EXISTS"}, 61 | {0x0000002CL, "EDS_ERR_FILE_FORMAT_UNRECOGNIZED"}, 62 | {0x0000002DL, "EDS_ERR_FILE_DATA_CORRUPT"}, 63 | {0x0000002EL, "EDS_ERR_FILE_NAMING_NA"}, 64 | 65 | /* Directory errors */ 66 | {0x00000040L, "EDS_ERR_DIR_NOT_FOUND"}, 67 | {0x00000041L, "EDS_ERR_DIR_IO_ERROR"}, 68 | {0x00000042L, "EDS_ERR_DIR_ENTRY_NOT_FOUND"}, 69 | {0x00000043L, "EDS_ERR_DIR_ENTRY_EXISTS"}, 70 | {0x00000044L, "EDS_ERR_DIR_NOT_EMPTY"}, 71 | 72 | /* Property errors */ 73 | {0x00000050L, "EDS_ERR_PROPERTIES_UNAVAILABLE"}, 74 | {0x00000051L, "EDS_ERR_PROPERTIES_MISMATCH"}, 75 | {0x00000053L, "EDS_ERR_PROPERTIES_NOT_LOADED"}, 76 | 77 | /* Function Parameter errors */ 78 | {0x00000060L, "EDS_ERR_INVALID_PARAMETER"}, 79 | {0x00000061L, "EDS_ERR_INVALID_HANDLE"}, 80 | {0x00000062L, "EDS_ERR_INVALID_POINTER"}, 81 | {0x00000063L, "EDS_ERR_INVALID_INDEX"}, 82 | {0x00000064L, "EDS_ERR_INVALID_LENGTH"}, 83 | {0x00000065L, "EDS_ERR_INVALID_FN_POINTER"}, 84 | {0x00000066L, "EDS_ERR_INVALID_SORT_FN"}, 85 | 86 | /* Device errors */ 87 | {0x00000080L, "EDS_ERR_DEVICE_NOT_FOUND"}, 88 | {0x00000081L, "EDS_ERR_DEVICE_BUSY. Note: If a device busy error occurs, reissue the command after a while. The camera will become unstable."}, 89 | {0x00000082L, "EDS_ERR_DEVICE_INVALID"}, 90 | {0x00000083L, "EDS_ERR_DEVICE_EMERGENCY"}, 91 | {0x00000084L, "EDS_ERR_DEVICE_MEMORY_FULL"}, 92 | {0x00000085L, "EDS_ERR_DEVICE_INTERNAL_ERROR"}, 93 | {0x00000086L, "EDS_ERR_DEVICE_INVALID_PARAMETER"}, 94 | {0x00000087L, "EDS_ERR_DEVICE_NO_DISK"}, 95 | {0x00000088L, "EDS_ERR_DEVICE_DISK_ERROR"}, 96 | {0x00000089L, "EDS_ERR_DEVICE_CF_GATE_CHANGED"}, 97 | {0x0000008AL, "EDS_ERR_DEVICE_DIAL_CHANGED"}, 98 | {0x0000008BL, "EDS_ERR_DEVICE_NOT_INSTALLED"}, 99 | {0x0000008CL, "EDS_ERR_DEVICE_STAY_AWAKE"}, 100 | {0x0000008DL, "EDS_ERR_DEVICE_NOT_RELEASED"}, 101 | 102 | /* Stream errors */ 103 | {0x000000A0L, "EDS_ERR_STREAM_IO_ERROR"}, 104 | {0x000000A1L, "EDS_ERR_STREAM_NOT_OPEN"}, 105 | {0x000000A2L, "EDS_ERR_STREAM_ALREADY_OPEN"}, 106 | {0x000000A3L, "EDS_ERR_STREAM_OPEN_ERROR"}, 107 | {0x000000A4L, "EDS_ERR_STREAM_CLOSE_ERROR"}, 108 | {0x000000A5L, "EDS_ERR_STREAM_SEEK_ERROR"}, 109 | {0x000000A6L, "EDS_ERR_STREAM_TELL_ERROR"}, 110 | {0x000000A7L, "EDS_ERR_STREAM_READ_ERROR"}, 111 | {0x000000A8L, "EDS_ERR_STREAM_WRITE_ERROR"}, 112 | {0x000000A9L, "EDS_ERR_STREAM_PERMISSION_ERROR"}, 113 | {0x000000AAL, "EDS_ERR_STREAM_COULDNT_BEGIN_THREAD. Could not start reading thumbnail"}, 114 | {0x000000ABL, "EDS_ERR_STREAM_BAD_OPTIONS"}, 115 | {0x000000ACL, "EDS_ERR_STREAM_END_OF_STREAM"}, 116 | 117 | /* Communications errors */ 118 | {0x000000C0L, "EDS_ERR_COMM_PORT_IS_IN_USE"}, 119 | {0x000000C1L, "EDS_ERR_COMM_DISCONNECTED"}, 120 | {0x000000C2L, "EDS_ERR_COMM_DEVICE_INCOMPATIBLE"}, 121 | {0x000000C3L, "EDS_ERR_COMM_BUFFER_FULL"}, 122 | {0x000000C4L, "EDS_ERR_COMM_USB_BUS_ERR"}, 123 | 124 | /* Lock/Unlock */ 125 | {0x000000D0L, "EDS_ERR_USB_DEVICE_LOCK_ERROR"}, 126 | {0x000000D1L, "EDS_ERR_USB_DEVICE_UNLOCK_ERROR"}, 127 | 128 | /* STI/WIA */ 129 | {0x000000E0L, "EDS_ERR_STI_UNKNOWN_ERROR"}, 130 | {0x000000E1L, "EDS_ERR_STI_INTERNAL_ERROR"}, 131 | {0x000000E2L, "EDS_ERR_STI_DEVICE_CREATE_ERROR"}, 132 | {0x000000E3L, "EDS_ERR_STI_DEVICE_RELEASE_ERROR"}, 133 | {0x000000E4L, "EDS_ERR_DEVICE_NOT_LAUNCHED"}, 134 | 135 | {0x000000F0L, "EDS_ERR_ENUM_NA. Enumeration terminated (there was no suitable enumeration item)"}, 136 | {0x000000F1L, "EDS_ERR_INVALID_FN_CALL. Called in a mode when the function could not be used"}, 137 | {0x000000F2L, "EDS_ERR_HANDLE_NOT_FOUND"}, 138 | {0x000000F3L, "EDS_ERR_INVALID_ID"}, 139 | {0x000000F4L, "EDS_ERR_WAIT_TIMEOUT_ERROR"}, 140 | 141 | /* PTP */ 142 | {0x00002003, "EDS_ERR_SESSION_NOT_OPEN"}, 143 | {0x00002004, "EDS_ERR_INVALID_TRANSACTIONID"}, 144 | {0x00002007, "EDS_ERR_INCOMPLETE_TRANSFER"}, 145 | {0x00002008, "EDS_ERR_INVALID_STRAGEID. Storage error"}, 146 | {0x0000200A, "EDS_ERR_DEVICEPROP_NOT_SUPPORTED"}, 147 | {0x0000200B, "EDS_ERR_INVALID_OBJECTFORMATCODE"}, 148 | {0x00002011, "EDS_ERR_SELF_TEST_FAILED"}, 149 | {0x00002012, "EDS_ERR_PARTIAL_DELETION"}, 150 | {0x00002014, "EDS_ERR_SPECIFICATION_BY_FORMAT_UNSUPPORTED"}, 151 | {0x00002015, "EDS_ERR_NO_VALID_OBJECTINFO"}, 152 | {0x00002016, "EDS_ERR_INVALID_CODE_FORMAT"}, 153 | {0x00002017, "EDS_ERR_UNKNOWN_VENDOR_CODE"}, 154 | {0x00002018, "EDS_ERR_CAPTURE_ALREADY_TERMINATED"}, 155 | {0x00002019, "EDS_ERR_PTP_DEVICE_BUSY"}, 156 | {0x0000201A, "EDS_ERR_INVALID_PARENTOBJECT"}, 157 | {0x0000201B, "EDS_ERR_INVALID_DEVICEPROP_FORMAT"}, 158 | {0x0000201C, "EDS_ERR_INVALID_DEVICEPROP_VALUE"}, 159 | {0x0000201E, "EDS_ERR_SESSION_ALREADY_OPEN"}, 160 | {0x0000201F, "EDS_ERR_TRANSACTION_CANCELLED"}, 161 | {0x00002020, "EDS_ERR_SPECIFICATION_OF_DESTINATION_UNSUPPORTED"}, 162 | {0x00002021, "EDS_ERR_NOT_CAMERA_SUPPORT_SDK_VERSION"}, 163 | 164 | /* PTP Vendor */ 165 | {0x0000A001, "EDS_ERR_UNKNOWN_COMMAND"}, 166 | {0x0000A005, "EDS_ERR_OPERATION_REFUSED"}, 167 | {0x0000A006, "EDS_ERR_LENS_COVER_CLOSE"}, 168 | {0x0000A101, "EDS_ERR_LOW_BATTERY"}, 169 | {0x0000A102, "EDS_ERR_OBJECT_NOTREADY. Image data set not ready for live view"}, 170 | {0x0000A104, "EDS_ERR_CANNOT_MAKE_OBJECT"}, 171 | {0x0000A106, "EDS_ERR_MEMORYSTATUS_NOTREADY"}, 172 | 173 | /* Take Picture errors */ 174 | {0x00008D01L, "EDS_ERR_TAKE_PICTURE_AF_NG. Focus Failed"}, 175 | {0x00008D02L, "EDS_ERR_TAKE_PICTURE_RESERVED"}, 176 | {0x00008D03L, "EDS_ERR_TAKE_PICTURE_MIRROR_UP_NG. Currently configuring mirror up"}, 177 | {0x00008D04L, "EDS_ERR_TAKE_PICTURE_SENSOR_CLEANING_NG"}, 178 | {0x00008D05L, "EDS_ERR_TAKE_PICTURE_SILENCE_NG. Currently performing silent operations"}, 179 | {0x00008D06L, "EDS_ERR_TAKE_PICTURE_NO_CARD_NG"}, 180 | {0x00008D07L, "EDS_ERR_TAKE_PICTURE_CARD_NG. Error writing to card"}, 181 | {0x00008D08L, "EDS_ERR_TAKE_PICTURE_CARD_PROTECT_NG. Card write protected"}, 182 | {0x00008D09L, "EDS_ERR_TAKE_PICTURE_MOVIE_CROP_NG"}, 183 | {0x00008D0AL, "EDS_ERR_TAKE_PICTURE_STROBO_CHARGE_NG. Faild in flash off"}, 184 | {0x00008D0BL, "EDS_ERR_TAKE_PICTURE_NO_LENS_NG. Lens is not attached"}, 185 | {0x00008D0CL, "EDS_ERR_TAKE_PICTURE_SPECIAL_MOVIE_MODE_NG. Movie camera exceeds the limit"}, 186 | {0x00008D0DL, "EDS_ERR_TAKE_PICTURE_LV_REL_PROHIBIT_MODE_NG. Faild in live view preparing taking picture for changing AEmode(Candlelight only)"}, 187 | {0x00008D0EL, "EDS_ERR_TAKE_PICTURE_MOVIE_MODE_NG. Faild in taking still image with getting ready for movie mode"}, 188 | {0x00008D0FL, "EDS_ERR_TAKE_PICTURE_RETRUCTED_LENS_NG. Retructed lens is retracted"}, 189 | 190 | 191 | {0x000000F5L, "EDS_ERR_LAST_GENERIC_ERROR_PLUS_ONE"}, 192 | }; 193 | 194 | std::map::const_iterator it = errorMap.find(error); 195 | return it == errorMap.end() ? "Unknown error" : it->second; 196 | } 197 | 198 | 199 | PyObject *PyDict_FromEdsPoint(EdsPoint const &point) { 200 | PyObject *pyDict(PyDict_New()); 201 | PyObject *pyX(PyLong_FromLong(point.x)); 202 | PyObject *pyY(PyLong_FromLong(point.y)); 203 | PyDict_SetItemString(pyDict, "x", pyX); 204 | PyDict_SetItemString(pyDict, "y", pyY); 205 | Py_DECREF(pyX); 206 | Py_DECREF(pyY); 207 | return pyDict; 208 | } 209 | 210 | 211 | PyObject *PyDict_FromEdsSize(EdsSize const &size) { 212 | PyObject *pyDict(PyDict_New()); 213 | PyObject *pyWidth(PyLong_FromLong(size.width)); 214 | PyObject *pyHeight(PyLong_FromLong(size.height)); 215 | PyDict_SetItemString(pyDict, "width", pyWidth); 216 | PyDict_SetItemString(pyDict, "height", pyHeight); 217 | Py_DECREF(pyWidth); 218 | Py_DECREF(pyHeight); 219 | return pyDict; 220 | } 221 | 222 | 223 | PyObject *PyDict_FromEdsRect(EdsRect const &rect) { 224 | PyObject *pyDict(PyDict_New()); 225 | PyObject *pyPoint(PyDict_FromEdsPoint(rect.point)); 226 | PyObject *pySize(PyDict_FromEdsSize(rect.size)); 227 | PyDict_SetItemString(pyDict, "point", pyPoint); 228 | PyDict_SetItemString(pyDict, "size", pySize); 229 | Py_DECREF(pyPoint); 230 | Py_DECREF(pySize); 231 | return pyDict; 232 | } 233 | 234 | 235 | PyObject *PyDict_FromEdsImageInfo(EdsImageInfo const &imageInfo) { 236 | PyObject *pyWidth(PyLong_FromUnsignedLong(imageInfo.width)); 237 | PyObject *pyHeight(PyLong_FromUnsignedLong(imageInfo.height)); 238 | PyObject *pyNumOfComponents(PyLong_FromUnsignedLong(imageInfo.numOfComponents)); 239 | PyObject *pyComponentDepth(PyLong_FromUnsignedLong(imageInfo.componentDepth)); 240 | PyObject *pyEffectiveRect(PyDict_FromEdsRect(imageInfo.effectiveRect)); 241 | PyObject *pyReserved1(PyLong_FromUnsignedLong(imageInfo.reserved1)); 242 | PyObject *pyReserved2(PyLong_FromUnsignedLong(imageInfo.reserved2)); 243 | 244 | PyObject* pyImageInfo(PyDict_New()); 245 | PyDict_SetItemString(pyImageInfo, "width", pyWidth); 246 | PyDict_SetItemString(pyImageInfo, "height", pyHeight); 247 | PyDict_SetItemString(pyImageInfo, "numOfComponents", pyNumOfComponents); 248 | PyDict_SetItemString(pyImageInfo, "componentDepth", pyComponentDepth); 249 | PyDict_SetItemString(pyImageInfo, "effectiveRect", pyEffectiveRect); 250 | PyDict_SetItemString(pyImageInfo, "reserved1", pyReserved1); 251 | PyDict_SetItemString(pyImageInfo, "reserved2", pyReserved2); 252 | 253 | Py_DECREF(pyWidth); 254 | Py_DECREF(pyHeight); 255 | Py_DECREF(pyNumOfComponents); 256 | Py_DECREF(pyComponentDepth); 257 | Py_DECREF(pyEffectiveRect); 258 | Py_DECREF(pyReserved1); 259 | Py_DECREF(pyReserved2); 260 | return pyImageInfo; 261 | } 262 | 263 | 264 | bool PyDict_ToEdsPoint(PyObject *pyDict, EdsPoint &point) { 265 | // Check if the dictionary has the correct keys 266 | PyObject *pyX(PyDict_GetItemString(pyDict, "width")); 267 | PyObject *pyY(PyDict_GetItemString(pyDict, "height")); 268 | 269 | if (!pyX || !pyY || !PyLong_Check(pyX) || !PyLong_Check(pyY)) { 270 | PyErr_SetString( 271 | PyExc_TypeError, 272 | "Invalid EdsPoint, expected {\"x\": int, \"y\": int)"); 273 | return false; 274 | } 275 | point.x = PyLong_AsLong(pyX); 276 | point.y = PyLong_AsLong(pyY); 277 | return true; 278 | } 279 | 280 | 281 | bool PyDict_ToEdsSize(PyObject *pyDict, EdsSize &size) { 282 | PyObject *pyWidth(PyDict_GetItemString(pyDict, "width")); 283 | PyObject *pyHeight(PyDict_GetItemString(pyDict, "height")); 284 | 285 | if (!pyWidth || !pyHeight || !PyLong_Check(pyWidth) || !PyLong_Check(pyHeight)){ 286 | PyErr_SetString( 287 | PyExc_TypeError, 288 | "Invalid EdsSize, expected {\"width\": int, \"height\": int)"); 289 | return false; 290 | } 291 | size.width = PyLong_AsLong(pyWidth); 292 | size.height = PyLong_AsLong(pyHeight); 293 | return true; 294 | } 295 | 296 | 297 | bool PyDict_ToEdsRect(PyObject *pyDict, EdsRect &rect) { 298 | PyObject *pyPoint(PyDict_GetItemString(pyDict, "point")); 299 | PyObject *pySize(PyDict_GetItemString(pyDict, "size")); 300 | 301 | if (!PyDict_Check(pyPoint) || !PyDict_Check(pySize)){ 302 | PyErr_SetString( 303 | PyExc_TypeError, 304 | "Invalid EdsRect, expected {" 305 | "\"point\": {\"x\": int, \"y\": int}, " 306 | "\"size\": {\"width\": int, \"height\": int}}"); 307 | return false; 308 | } 309 | return PyDict_ToEdsPoint(pyDict, rect.point) && 310 | PyDict_ToEdsSize(pyDict, rect.size); 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /edsdk/edsdk_utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "EDSDKTypes.h" 6 | 7 | 8 | #define PyCheck_EDSERROR(err) \ 9 | if (err != EDS_ERR_OK) { \ 10 | PyObject *exc_args = PyTuple_New(2); \ 11 | PyTuple_SetItem(exc_args, 0, PyUnicode_FromString(EDS::errorMessage(err))); \ 12 | PyTuple_SetItem(exc_args, 1, PyLong_FromLong(err)); \ 13 | PyErr_SetObject(PyEdsError, exc_args); \ 14 | return nullptr; \ 15 | } 16 | 17 | 18 | namespace EDS { 19 | char const *errorMessage(EdsError const error); 20 | 21 | PyObject *PyDict_FromEdsPoint(EdsPoint const &point); 22 | PyObject *PyDict_FromEdsSize(EdsSize const &size); 23 | PyObject *PyDict_FromEdsRect(EdsRect const &rect); 24 | PyObject *PyDict_FromEdsImageInfo(EdsImageInfo const &imageInfo); 25 | 26 | bool PyDict_ToEdsPoint(PyObject *pyDict, EdsPoint &point); 27 | bool PyDict_ToEdsSize(PyObject *pyDict, EdsSize &size); 28 | bool PyDict_ToEdsRect(PyObject *pyDict, EdsRect &rect); 29 | 30 | std::map const DataTypeSize = { 31 | {kEdsDataType_Bool, sizeof(EdsBool)}, 32 | {kEdsDataType_Int8, sizeof(EdsInt8)}, 33 | {kEdsDataType_UInt8, sizeof(EdsUInt8)}, 34 | {kEdsDataType_Int16, sizeof(EdsInt16)}, 35 | {kEdsDataType_UInt16, sizeof(EdsUInt16)}, 36 | {kEdsDataType_Int32, sizeof(EdsInt32)}, 37 | {kEdsDataType_UInt32, sizeof(EdsUInt32)}, 38 | {kEdsDataType_Int64, sizeof(EdsInt64)}, 39 | {kEdsDataType_UInt64, sizeof(EdsUInt64)}, 40 | {kEdsDataType_Float, sizeof(EdsFloat)}, 41 | {kEdsDataType_Double, sizeof(EdsDouble)}, 42 | {kEdsDataType_Rational, sizeof(EdsRational)}, 43 | {kEdsDataType_Point, sizeof(EdsPoint)}, 44 | {kEdsDataType_Rect, sizeof(EdsRect)}, 45 | {kEdsDataType_Time, sizeof(EdsTime)}, 46 | {kEdsDataType_FocusInfo, sizeof(EdsFocusInfo)}, 47 | {kEdsDataType_PictureStyleDesc, sizeof(EdsPictureStyleDesc)}, 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /edsdk/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiloc/edsdk-python/129cadba64efe92776ce53a79127aa8dcf64b373/edsdk/py.typed -------------------------------------------------------------------------------- /examples/save_image.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import uuid 4 | 5 | import edsdk 6 | from edsdk import ( 7 | CameraCommand, 8 | ObjectEvent, 9 | PropID, 10 | FileCreateDisposition, 11 | Access, 12 | SaveTo, 13 | EdsObject, 14 | ) 15 | 16 | if os.name == "nt": 17 | # If you're using the EDSDK on Windows, 18 | # you have to have a Windows message loop in your main thread, 19 | # otherwise callbacks won't happen. 20 | # (This is because the EDSDK uses the obsolete COM STA threading model 21 | # instead of real threads.) 22 | import pythoncom 23 | 24 | 25 | def save_image(object_handle: EdsObject, save_to: str) -> int: 26 | dir_item_info = edsdk.GetDirectoryItemInfo(object_handle) 27 | out_stream = edsdk.CreateFileStream( 28 | os.path.join(save_to, str(uuid.uuid4()) + ".raw"), 29 | FileCreateDisposition.CreateAlways, 30 | Access.ReadWrite) 31 | edsdk.Download(object_handle, dir_item_info["size"], out_stream) 32 | edsdk.DownloadComplete(object_handle) 33 | return 0 34 | 35 | 36 | def callback_property(event: PropertyEvent, property_id: PropID, parameter: int) -> int: 37 | print("event: ", event) 38 | print("Property changed:", property_id) 39 | print("Parameter:", parameter) 40 | return 0 41 | 42 | 43 | def callback_object(event: ObjectEvent, object_handle: EdsObject) -> int: 44 | print("event: ", event, "object_handle:", object_handle) 45 | if event == ObjectEvent.DirItemRequestTransfer: 46 | save_image(object_handle, ".") 47 | return 0 48 | 49 | 50 | if __name__ == "__main__": 51 | edsdk.InitializeSDK() 52 | cam_list = edsdk.GetCameraList() 53 | nr_cameras = edsdk.GetChildCount(cam_list) 54 | 55 | if nr_cameras == 0: 56 | print("No cameras connected") 57 | exit(1) 58 | 59 | cam = edsdk.GetChildAtIndex(cam_list, 0) 60 | edsdk.OpenSession(cam) 61 | edsdk.SetObjectEventHandler(cam, ObjectEvent.All, callback_object) 62 | edsdk.SetPropertyData(cam, PropID.SaveTo, 0, SaveTo.Host) 63 | print(edsdk.GetPropertyData(cam, PropID.SaveTo)) 64 | 65 | # Sets HD Capacity to an arbitrary big value 66 | edsdk.SetCapacity( 67 | cam, {"reset": True, "bytesPerSector": 512, "numberOfFreeClusters": 2147483647} 68 | ) 69 | print(edsdk.GetDeviceInfo(cam)) 70 | 71 | edsdk.SendCommand(cam, CameraCommand.TakePicture, 0) 72 | 73 | time.sleep(4) 74 | if os.name == "nt": 75 | pythoncom.PumpWaitingMessages() 76 | edsdk.TerminateSDK() 77 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup, Extension, find_packages 3 | 4 | package_name = "edsdk-python" 5 | version = "0.1" 6 | 7 | here = os.path.abspath(os.path.dirname(__file__)) 8 | 9 | try: 10 | with open(os.path.join(here, "README.md"), encoding="utf-8") as f: 11 | long_description = "\n" + f.read() 12 | except FileNotFoundError: 13 | long_description = "" 14 | 15 | 16 | _DEBUG = True 17 | _DEBUG_LEVEL = 0 18 | 19 | extra_compile_args = [] 20 | if _DEBUG: 21 | extra_compile_args += ["/W4", "/DDEBUG=%s" % _DEBUG_LEVEL] 22 | else: 23 | extra_compile_args += ["/DNDEBUG"] 24 | 25 | 26 | EDSDK_PATH = "dependencies" 27 | # EDSDK_PATH = "dependencies/EDSDK_13.13.41_Win/" 28 | 29 | extension = Extension( 30 | "edsdk.api", 31 | libraries=["EDSDK"], 32 | include_dirs=[os.path.join(EDSDK_PATH, "EDSDK/Header")], 33 | library_dirs=[os.path.join(EDSDK_PATH, "EDSDK_64/Library")], 34 | depends=["edsdk/edsdk_python.h", "edsdk/edsdk_utils.h"], 35 | sources=["edsdk/edsdk_python.cpp","edsdk/edsdk_utils.cpp"], 36 | extra_compile_args=extra_compile_args, 37 | ) 38 | 39 | setup( 40 | name=package_name, 41 | version=version, 42 | author="Francesco Leacche", 43 | author_email="francescoleacche@gmail.com", 44 | url="https://github.com/jiloc/edsdk-python", 45 | description="Python wrapper for Canon EDSKD Library", 46 | long_description=long_description, 47 | ext_modules = [extension], 48 | install_requires=[ 49 | 'pywin32 >= 228 ; platform_system=="Windows"' 50 | ], 51 | setup_requires=["wheel"], 52 | packages=find_packages(), 53 | include_package_data=True, 54 | package_data={ 55 | "edsdk": ["py.typed", "api.pyi"], 56 | }, 57 | data_files = [("Lib/site-packages/edsdk", [ 58 | EDSDK_PATH + "/EDSDK_64/Dll/EDSDK.dll", 59 | EDSDK_PATH + "/EDSDK_64/Dll/EdsImage.dll"])], 60 | python_requires=">=3.8.0", 61 | long_description_content_type="text/markdown", 62 | classifiers=[ 63 | "License :: OSI Approved :: MIT License", 64 | "Intended Audience :: Developers", 65 | "Environment :: Win32 (MS Windows)", 66 | "Operating System :: Microsoft :: Windows", 67 | "Programming Language :: Python", 68 | "Programming Language :: Python :: 3", 69 | "Programming Language :: Python :: 3.8", 70 | "Programming Language :: Python :: 3.9", 71 | "Programming Language :: Python :: 3.10", 72 | "Programming Language :: Python :: Implementation :: CPython", 73 | "Topic :: System :: Hardware :: Universal Serial Bus (USB)", 74 | "Typing :: Stubs Only", 75 | ], 76 | keywords=["edsdk", "canon"], 77 | license="MIT", 78 | ) 79 | --------------------------------------------------------------------------------