Devices¶
Goal¶
This tutorial elaborates on how the interface for devices provides abstractions for physical or virtual devices that may be present in the system, such as cameras, microphones, DVD drives, or screen captures. After reading the tutorial you will know how to:
Enumerate the available devices
List devices properties
List the eventual output stream formats provided devices
Prerequisites¶
Walkthrough¶
Device enumeration is quite straightforward. flu_device_list_get returns a double-linked GList of pointers to FluDevice. Remember that, as usual, this list has to be freed calling its specific cleanup function, in this case flu_device_list_free
static void _enumerate_devices()
{
GList *devices = flu_device_list_get();
guint size = g_list_length(devices);
if (size > 0)
{
g_print("Devices list (%u):\n", size);
gint idx = 0;
for (GList *item = devices; item; item = item->next)
{
FluDevice *device = (FluDevice *)item->data;
_device_display_properties(device, idx++);
}
}
else
{
g_print("No devices available.\n");
}
flu_device_list_free(devices);
}
Device’s properties can be queried by calling flu_device_<property>_get
functions, passing them a pointer to FluDevice.
static void _device_display_properties(const FluDevice *device, gint idx)
{
g_print("\n #%03d => name: %s\n"
" fake: %s\n"
" type: %s\n"
" label: %s\n"
" id: %s\n"
" uri: %s\n",
idx++,
STRING_OR_NONE(flu_device_name_get(device)),
YES_OR_NO(flu_device_is_fake(device)),
flu_device_type_name_get(flu_device_type_get(device)),
STRING_OR_NONE(flu_device_label_get(device)),
STRING_OR_NONE(flu_device_current_media_id_get(device)),
STRING_OR_NONE(flu_device_uri_get(device)));
Some devices are fake devices. These devices are intended for debug, and can be used, for example, to impersonate real devices in testing, when the real devices are not available.
A device can provide zero or many output formats. To get a list of available formats, use flu_device_output_formats_get.
static void _device_display_output_formats(const FluDevice *device)
{
const GList *formats = flu_device_output_formats_get((FluDevice *)device);
if (formats)
{
const GList *l;
for (l = formats; l != NULL; l = l->next)
{
const FluStreamInfo *format_info = (const FluStreamInfo *)l->data;
const FluStreamInfoData *format_data = &format_info->data;
_stream_info_display(format_info);
switch (format_info->type)
{
case FLU_STREAM_TYPE_VIDEO:
_stream_info_video_display_format((const FluStreamVideoInfo *)format_data);
break;
case FLU_STREAM_TYPE_AUDIO:
_stream_info_audio_display_format((const FluStreamAudioInfo *)format_data);
break;
case FLU_STREAM_TYPE_TEXT:
break;
case FLU_STREAM_TYPE_DATA:
break;
default:
g_abort();
}
}
}
}
The returned FluStreamInfoData is an union, and has
to be cast to the corresponding FluStream<Type>Info
struct by querying the
type
member. A similar logic is also done in the
Print for each stream part of the
Stream Management tutorial.
Finally, it’s possible to inspect specific features of a given format. Please keep in mind that not all struct fields have a sense for all devices. In real-world code, you must inspect only those fields that have a role in your device.
static void _stream_info_video_display_format(const FluStreamVideoInfo *info)
{
g_print(" "
" video format: %dx%d@%.1f,"
" bitrate: %d,"
" aspect ratio: %.1f,"
" codec: %s\n",
info->width,
info->height,
_fraction(info->fps_n, info->fps_d),
info->bitrate,
_fraction(info->par_n, info->par_d),
STRING_OR_NONE(info->codec));
}
Full source code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | #include <fluendo-sdk.h>
#include <stdio.h>
#define STRING_OR_NONE(str) ((str) && (str)[0]) ? (str) : "none"
#define YES_OR_NO(val) ((val)) ? "yes" : "no"
static float _fraction(gint d, gint n)
{
if (n == 0)
{
return 0.0f;
}
return (float)d / (float)n;
}
static const char *_verbose_channels(gint channels)
{
switch (channels)
{
case 0:
return "none";
case 1:
return "mono";
case 2:
return "stereo";
case 6:
return "5.1";
default:
return "Unknow";
}
}
static void _stream_info_video_display_format(const FluStreamVideoInfo *info)
{
g_print(" "
" video format: %dx%d@%.1f,"
" bitrate: %d,"
" aspect ratio: %.1f,"
" codec: %s\n",
info->width,
info->height,
_fraction(info->fps_n, info->fps_d),
info->bitrate,
_fraction(info->par_n, info->par_d),
STRING_OR_NONE(info->codec));
}
static void _stream_info_audio_display_format(const FluStreamAudioInfo *info)
{
g_print(" "
" audio format: %s@%dhz,"
" width: %d"
" bitrate: %d,"
" lang: %s[%s],"
" codec: %s,"
" extension: %d,"
" description: %d\n",
_verbose_channels(info->channels),
info->rate,
info->width,
info->bitrate,
STRING_OR_NONE(info->language),
STRING_OR_NONE(info->iso),
STRING_OR_NONE(info->codec),
info->extension,
info->audio_description);
}
static void _stream_info_display(const FluStreamInfo *info)
{
g_print(" "
" "
" Stream index: %d,"
" group index: %d,"
" encrypted: %s\n",
info->index,
info->group_index,
YES_OR_NO(info->is_encrypted));
}
static void _device_display_output_formats(const FluDevice *device)
{
const GList *formats = flu_device_output_formats_get((FluDevice *)device);
if (formats)
{
const GList *l;
for (l = formats; l != NULL; l = l->next)
{
const FluStreamInfo *format_info = (const FluStreamInfo *)l->data;
const FluStreamInfoData *format_data = &format_info->data;
_stream_info_display(format_info);
switch (format_info->type)
{
case FLU_STREAM_TYPE_VIDEO:
_stream_info_video_display_format((const FluStreamVideoInfo *)format_data);
break;
case FLU_STREAM_TYPE_AUDIO:
_stream_info_audio_display_format((const FluStreamAudioInfo *)format_data);
break;
case FLU_STREAM_TYPE_TEXT:
break;
case FLU_STREAM_TYPE_DATA:
break;
default:
g_abort();
}
}
}
}
static void _device_display_properties(const FluDevice *device, gint idx)
{
g_print("\n #%03d => name: %s\n"
" fake: %s\n"
" type: %s\n"
" label: %s\n"
" id: %s\n"
" uri: %s\n",
idx++,
STRING_OR_NONE(flu_device_name_get(device)),
YES_OR_NO(flu_device_is_fake(device)),
flu_device_type_name_get(flu_device_type_get(device)),
STRING_OR_NONE(flu_device_label_get(device)),
STRING_OR_NONE(flu_device_current_media_id_get(device)),
STRING_OR_NONE(flu_device_uri_get(device)));
_device_display_output_formats(device);
}
static void _enumerate_devices()
{
GList *devices = flu_device_list_get();
guint size = g_list_length(devices);
if (size > 0)
{
g_print("Devices list (%u):\n", size);
gint idx = 0;
for (GList *item = devices; item; item = item->next)
{
FluDevice *device = (FluDevice *)item->data;
_device_display_properties(device, idx++);
}
}
else
{
g_print("No devices available.\n");
}
flu_device_list_free(devices);
}
int main(void)
{
/* Initialize Fluendo SDK */
flu_initialize();
_enumerate_devices();
/* Shutdowns library */
flu_shutdown();
return 0;
}
|
You can download it here.
Building¶
This source code along with the rest of tutorials can be compiled using the following commands.
On Linux:
mkdir fluendo-sdk-tutorials && cd fluendo-sdk-tutorials
meson /opt/fluendo-sdk/share/doc/fluendo-sdk/tutorials/src
ninja
On Windows:
mkdir fluendo-sdk-tutorials
cd fluendo-sdk-tutorials
meson C:\fluendo-sdk\<version>\<x86/x86_64>\share\doc\fluendo-sdk\tutorials\src
ninja
To generate a Visual Studio project, you can pass the --backend=vs
option
to meson.
Conclusions¶
During this tutorial the following concepts have been consolidated:
How to get the GList of FluDevice’s using flu_device_list_get and free it using flu_device_list_free
How to use the
flu_device_<property>_get
functions family to get different properties of a device:flu_device_name_get to get a human-readable name
flu_device_is_fake to know whether it is a fake device
flu_device_type_name_get to get a human-readable name
flu_device_label_get to get the media label
flu_device_current_media_id_get to get the unique ID for the media currently inserted in the device (for devices with removable media, like DVDs, for example) or the name of the GStreamer plugin used to provide a device interface (for hardware devices like a camera or a microphone, for example).
flu_device_uri_get to get the URI