1use bitflags::bitflags;
5use libmtp_sys as ffi;
6use std::ffi::CStr;
7
8use crate::error::Error;
9use crate::Result;
10
11pub(crate) fn maybe_init() {
12 static mut ALREADY_INIT: bool = false;
13 unsafe {
14 if !ALREADY_INIT {
15 ffi::LIBMTP_Init();
16 ALREADY_INIT = true;
17 }
18 }
19}
20
21bitflags! {
22 pub struct DebugLevel: i32 {
32 const NONE = ffi::LIBMTP_DEBUG_NONE as i32;
33 const PTP = ffi::LIBMTP_DEBUG_PTP as i32;
34 const PLST = ffi::LIBMTP_DEBUG_PLST as i32;
35 const USB = ffi::LIBMTP_DEBUG_USB as i32;
36 const DATA = ffi::LIBMTP_DEBUG_DATA as i32;
37 const ALL = ffi::LIBMTP_DEBUG_ALL as i32;
38 }
39}
40
41pub fn set_debug(level: DebugLevel) {
53 maybe_init();
54
55 unsafe {
56 ffi::LIBMTP_Set_Debug(level.bits());
57 }
58}
59
60#[derive(Debug, Clone)]
63pub struct DeviceEntry {
64 pub vendor: &'static str,
65 pub vendor_id: u16,
66 pub product: &'static str,
67 pub product_id: u16,
68 pub device_flags: u32,
69}
70
71pub fn get_supported_devices() -> Result<Vec<DeviceEntry>> {
74 maybe_init();
75
76 let mut devices_ptr = std::ptr::null_mut();
77 let mut len = 0;
78
79 let res = unsafe { ffi::LIBMTP_Get_Supported_Devices_List(&mut devices_ptr, &mut len) };
80
81 if res != 0 {
82 Err(Error::Unknown)
83 } else {
84 let mut devices = Vec::new();
85 for offset in 0..len as isize {
86 unsafe {
87 let device = &*devices_ptr.offset(offset);
88 let vendor = CStr::from_ptr(device.vendor);
89 let product = CStr::from_ptr(device.product);
90
91 devices.push(DeviceEntry {
92 vendor: vendor.to_str().expect("Invalid UTF-8 in music-players.h?"),
93 vendor_id: device.vendor_id,
94 product: product.to_str().expect("Invalid UTF-8 in music-players.h?"),
95 product_id: device.product_id,
96 device_flags: device.device_flags,
97 });
98 }
99 }
100
101 Ok(devices)
102 }
103}