Skip to content

Enumeration_C_QuickSpin

Enumeration_C_QuickSpin.c shows how to enumerate interfaces and cameras using the QuickSpin API. QuickSpin is a subset of the Spinnaker library that allows for simpler node access and control. This is a great example to start learning about QuickSpin.


//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================

/**
 *  @example Enumeration_C_QuickSpin.c
 *
 *  @brief Enumeration_C_QuickSpin.c shows how to enumerate interfaces
 *  and cameras using the QuickSpin API. QuickSpin is a subset of the Spinnaker
 *  library that allows for simpler node access and control. This is a great
 *  example to start learning about QuickSpin.
 *
 *  This example introduces the preparation, use, and cleanup of the system
 *  object, interface and camera lists, interfaces, and cameras. It also
 *  touches on retrieving information from pre-fetched nodes using QuickSpin.
 *  Retrieving node information is the only portion of the example that
 *  differs from Enumeration_C.
 *
 *  A much wider range of topics is covered in the full Spinnaker examples than
 *  in the QuickSpin ones. There are only enough QuickSpin examples to
 *  demonstrate node access and to get started with the API; please see full
 *  Spinnaker examples for further or specific knowledge on a topic.
 *
 *  Please leave us feedback at: https://www.surveymonkey.com/r/TDYMVAPI
 *  More source code examples at: https://github.com/Teledyne-MV/Spinnaker-Examples
 *  Need help? Check out our forum at: https://teledynevisionsolutions.zendesk.com/hc/en-us/community/topics
 */

#include "SpinnakerC.h"
#include "stdio.h"
#include "string.h"

// This macro helps with C-strings.
#define MAX_BUFF_LEN 256

// This function queries an interface for its cameras and then prints out
// device information.
spinError QueryInterface(spinInterface hInterface)
{
    spinError err = SPINNAKER_ERR_SUCCESS;
    unsigned int i = 0;

    //
    // Pre-fetch TL interface nodes
    //
    // *** NOTES ***
    // In order to use QuickSpin in C, it is required to manually pre-fetch
    // all available nodes into a QuickSpin struct, which then acts as the
    // means of accessing its nodes.
    //
    quickSpinTLInterface qsI;

    err = quickSpinTLInterfaceInit(hInterface, &qsI);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to pre-fetch TL interface nodes. Aborting with error %d...\n\n", err);
        return err;
    }

    //
    // Print interface display name
    //
    // *** NOTES ***
    // QuickSpin allows for the retrieval of interface information directly
    // from an initialized quickSpinTLInterface struct. Because interface
    // information is made available on the transport layer, camera
    // initialization is not required.
    //
    bool8_t interfaceDisplayNameIsReadable = False;
    char interfaceDisplayName[MAX_BUFF_LEN];
    size_t lenInterfaceDisplayName = MAX_BUFF_LEN;

    // Check readability
    err = spinNodeIsReadable(qsI.InterfaceDisplayName, &interfaceDisplayNameIsReadable);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to check node readability (interface display name). Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve and print
    if (interfaceDisplayNameIsReadable)
    {
        err = spinStringGetValue(qsI.InterfaceDisplayName, interfaceDisplayName, &lenInterfaceDisplayName);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to retrieve value (interface display name). Aborting with error %d...\n\n", err);
            return err;
        }
    }
    else
    {
        strcpy(interfaceDisplayName, "Interface display name not readable");
    }

    printf("%s\n", interfaceDisplayName);

    //
    // Retrieve list of cameras from the interface
    //
    // *** NOTES ***
    // Camera lists can be retrieved from an interface or the system object.
    // Camera lists retrieved from an interface, such as this one, only return
    // cameras attached on that specific interface whereas camera lists
    // retrieved from the system will return all cameras on all interfaces.
    //
    // *** LATER ***
    // Camera lists must be cleared manually. This must be done prior to
    // releasing the system and while the camera list is still in scope.
    //
    spinCameraList hCameraList = NULL;
    size_t numCameras = 0;

    // Create empty camera list
    err = spinCameraListCreateEmpty(&hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to create camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve cameras
    err = spinInterfaceGetCameras(hInterface, hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve number of cameras
    err = spinCameraListGetSize(hCameraList, &numCameras);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve number of cameras. Aborting with error %d...\n\n", err);
        return err;
    }

    // Return if no cameras detected
    if (numCameras == 0)
    {
        printf("\tNo devices detected.\n\n");

        //
        // Clear and destroy camera list before losing scope
        //
        // *** NOTES ***
        // Camera lists do not automatically clean themselves up. This must be done
        // manually. The same is true of interface lists.
        //
        err = spinCameraListClear(hCameraList);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to clear camera list. Aborting with error %d...\n\n", err);
            return err;
        }

        err = spinCameraListDestroy(hCameraList);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to destroy camera list. Aborting with error %d...\n\n", err);
            return err;
        }
        return err;
    }

    // Print device vendor and model name for each camera on the interface
    for (i = 0; i < numCameras; i++)
    {
        //
        // Select camera
        //
        // *** NOTES ***
        // Each camera is retrieved from a camera list with an index. If the
        // index is out of range, an exception is thrown.
        //
        // *** LATER ***
        // Each camera handle needs to be released before losing scope or the
        // system is released.
        //
        spinCamera hCam = NULL;

        err = spinCameraListGet(hCameraList, i, &hCam);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to retrieve camera. Aborting with error %d...\n\n", err);
            return err;
        }

        // Pre-fetch TL device nodes; please see NodeMapInfo_C_QuickSpin example
        // for more in-depth comments on pre-fetching nodes
        quickSpinTLDevice qsD;

        err = quickSpinTLDeviceInit(hCam, &qsD);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to pre-fetch TL device nodes. Aborting with error %d...\n\n", err);
            return err;
        }

        //
        // Retrieve device vendor name
        //
        // *** NOTES ***
        // A node is distinguished by type, which is related to its value's
        // data type. Also, they can be checked for availability and
        // readability/writability prior to making an attempt to read
        // from or write to a node.
        //
        bool8_t deviceVendorNameIsReadable = False;

        // Check readability
        err = spinNodeIsReadable(qsD.DeviceVendorName, &deviceVendorNameIsReadable);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to check readability (vendor name). Aborting with error %d...\n\n", err);
            return err;
        }

        //
        // Retrieve device model name
        //
        // *** NOTES ***
        // Because C has no try-catch blocks, each functions returns an error
        // code to suggest whether an error has occurred. Errors can be
        // sufficiently handled with these return codes. Checking availabily
        // and readability/writability makes for safer and more complete code;
        // however, keeping in mind example conciseness and legibility, only
        // this example and NodeMapInfo_C_QuickSpin demonstrate checking node
        // availability and readability/writability while other examples
        // handle errors with error codes alone.
        //
        bool8_t deviceModelNameIsReadable = False;

        // Check readability
        err = spinNodeIsReadable(qsD.DeviceModelName, &deviceModelNameIsReadable);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to check readability (model name). Aborting with error %d...\n\n", err);
            return err;
        }

        //
        // Print device vendor and model names
        //
        // *** NOTES ***
        // Generally it is best to check readability when it is required to read
        // information from a node and writability when it is required to write
        // to a node. For most nodes, writability implies readability while
        // readability does not imply writability.
        //
        char deviceVendorName[MAX_BUFF_LEN];
        size_t lenDeviceVendorName = MAX_BUFF_LEN;
        char deviceModelName[MAX_BUFF_LEN];
        size_t lenDeviceModelName = MAX_BUFF_LEN;

        // Print device vendor name
        if (deviceVendorNameIsReadable)
        {
            err = spinStringGetValue(qsD.DeviceVendorName, deviceVendorName, &lenDeviceVendorName);
            if (err != SPINNAKER_ERR_SUCCESS)
            {
                printf("Unable to retrieve device information (vendor name value). Aborting with error %d...\n\n", err);
                return err;
            }
        }
        else
        {
            strcpy(deviceVendorName, "Not readable");
        }

        // Print device model name
        if (deviceModelNameIsReadable)
        {
            err = spinStringGetValue(qsD.DeviceModelName, deviceModelName, &lenDeviceModelName);
            if (err != SPINNAKER_ERR_SUCCESS)
            {
                printf("Unable to retrieve device information (model name value). Aborting with error %d...\n\n", err);
                return err;
            }
        }
        else
        {
            strcpy(deviceModelName, "Not readable");
        }

        printf("\tDevice %d %s %s\n\n", i, deviceVendorName, deviceModelName);

        //
        // Release camera before losing scope
        //
        // *** NOTES ***
        // Every handle that is created for a camera must be released before
        // the system is released or an exception will be thrown.
        //
        err = spinCameraRelease(hCam);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to release camera. Aborting with error %d...\n\n", err);
            return err;
        }
    }

    //
    // Clear and destroy camera list before losing scope
    //
    // *** NOTES ***
    // Camera lists do not automatically clean themselves up. This must be done
    // manually. The same is true of interface lists.
    //
    err = spinCameraListClear(hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to clear camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    err = spinCameraListDestroy(hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to destroy camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    return err;
}

// Example entry point; this function sets up the system and retrieves
// interfaces for the example.
int main(/*int argc, char** argv*/)
{
    spinError errReturn = SPINNAKER_ERR_SUCCESS;
    spinError err = SPINNAKER_ERR_SUCCESS;
    unsigned int i = 0;

    // Print application build information
    printf("Application build date: %s %s \n\n", __DATE__, __TIME__);

    //
    // Retrieve singleton reference to system object
    //
    // *** NOTES ***
    // Everything originates with the system object. It is important to notice
    // that it has a singleton implementation, so it is impossible to have
    // multiple system objects at the same time.
    //
    // *** LATER ***
    // The system object should be cleared prior to program completion.  If not
    // released explicitly, it will be released automatically.
    //
    spinSystem hSystem = NULL;

    err = spinSystemGetInstance(&hSystem);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve system instance. Aborting with error %d...\n\n", err);
        return err;
    }

    // Print out current library version
    spinLibraryVersion hLibraryVersion;

    spinSystemGetLibraryVersion(hSystem, &hLibraryVersion);
    printf(
        "Spinnaker library version: %d.%d.%d.%d\n\n",
        hLibraryVersion.major,
        hLibraryVersion.minor,
        hLibraryVersion.type,
        hLibraryVersion.build);

    //
    // Retrieve list of interfaces from the system
    //
    // *** NOTES ***
    // Interface lists are retrieved from the system object.
    //
    // *** LATER ***
    // Interface lists must be cleared and destroyed manually. This must be
    // done prior to releasing the system and while the interface list is still
    // in scope.
    //
    spinInterfaceList hInterfaceList = NULL;
    size_t numInterfaces = 0;

    // Create empty interface list
    err = spinInterfaceListCreateEmpty(&hInterfaceList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to create empty interface list. Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve interfaces from system
    err = spinSystemGetInterfaces(hSystem, hInterfaceList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve interface list. Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve number of interfaces
    err = spinInterfaceListGetSize(hInterfaceList, &numInterfaces);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve number of interfaces. Aborting with err %d...\n\n", err);
        return err;
    }

    printf("Number of interfaces detected: %u\n\n", (unsigned int)numInterfaces);

    //
    // Retrieve list of cameras from the system
    //
    // *** NOTES ***
    // Camera lists can be retrieved from an interface or the system object.
    // Camera lists retrieved from the system, such as this one, return all
    // cameras available on the system.
    //
    // *** LATER ***
    // Camera lists must be cleared and destroyed manually. This must be done
    // prior to releasing the system and while the camera list is still in
    // scope.
    //
    spinCameraList hCameraList = NULL;
    size_t numCameras = 0;

    // Create empty camera list
    err = spinCameraListCreateEmpty(&hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to create camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve cameras from system
    err = spinSystemGetCameras(hSystem, hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    // Retrieve number of cameras
    err = spinCameraListGetSize(hCameraList, &numCameras);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to retrieve number of cameras. Aborting with  error %d...\n\n", err);
        return err;
    }

    printf("Number of cameras detected: %u\n\n", (unsigned int)numCameras);

    // Finish if there are no cameras
    if (numCameras == 0 || numInterfaces == 0)
    {
        // Clear and destroy camera list before releasing system
        err = spinCameraListClear(hCameraList);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to clear camera list. Aborting with error %d...\n\n", err);
            return err;
        }

        err = spinCameraListDestroy(hCameraList);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to destroy camera list. Aborting with error %d...\n\n", err);
            return err;
        }

        // Clear and destroy interface list before releasing system
        err = spinInterfaceListClear(hInterfaceList);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to clear interface list. Aborting with error %d...\n\n", err);
            return err;
        }

        err = spinInterfaceListDestroy(hInterfaceList);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to destroy interface list. Aborting with error %d...\n\n", err);
            return err;
        }

        // Release system
        err = spinSystemReleaseInstance(hSystem);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to release system instance. Aborting with  error %d...\n\n", err);
            return err;
        }

        printf("\nNot enough cameras/interfaces!\n");
        printf("Done! Press Enter to exit...\n");
        getchar();

        return -1;
    }

    printf("\n*** QUERYING INTERFACES ***\n\n");

    //
    // Run example on each interface
    //
    // *** NOTES ***
    // In order to run all interfaces in a loop, each interface needs to
    // retrieved using its index.
    //
    for (i = 0; i < numInterfaces; i++)
    {
        // Select interface
        spinInterface hInterface = NULL;

        err = spinInterfaceListGet(hInterfaceList, i, &hInterface);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            printf("Unable to retrieve interface from list (error %d)...\n", err);
            errReturn = err;
            continue;
        }

        // Run example
        err = QueryInterface(hInterface);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            errReturn = err;
        }

        // Release interface
        err = spinInterfaceRelease(hInterface);
        if (err != SPINNAKER_ERR_SUCCESS)
        {
            errReturn = err;
        }
    }

    //
    // Clear and destroy camera list before releasing system
    //
    // *** NOTES ***
    // Camera lists are not shared pointers and do not automatically clean
    // themselves up and break their own references. Therefore, this must be
    // done manually. The same is true of interface lists.
    //
    err = spinCameraListClear(hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to clear camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    err = spinCameraListDestroy(hCameraList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to destroy camera list. Aborting with error %d...\n\n", err);
        return err;
    }

    //
    // Clear and destroy interface list before releasing system
    //
    // *** NOTES ***
    // Interface lists are not shared pointers and do not automatically clean
    // themselves up and break their own references. Therefore, this must be
    // done manually. The same is true of camera lists.
    //
    err = spinInterfaceListClear(hInterfaceList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to clear interface list. Aborting with error %d...\n\n", err);
        return err;
    }

    err = spinInterfaceListDestroy(hInterfaceList);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to destroy interface list. Aborting with error %d...\n\n", err);
        return err;
    }

    //
    // Release system
    //
    // *** NOTES ***
    // The system should be released, but if it is not, it will do so itself.
    // It is often at the release of the system (whether manual or automatic)
    // that unbroken references and still registered events will throw an
    // exception.
    //
    err = spinSystemReleaseInstance(hSystem);
    if (err != SPINNAKER_ERR_SUCCESS)
    {
        printf("Unable to release system instance. Aborting with  error %d...\n\n", err);
        return err;
    }

    printf("\nDone! Press Enter to exit...\n");
    getchar();

    return errReturn;
}