/* this callback runs on the device handling thread, so it can call libmtp directly */ static void mtp_device_open_cb (LIBMTP_mtpdevice_t *device, RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); DeviceOpenedData *data; if (device == NULL) { /* can't delete the source on this thread, so move it to the main thread */ g_idle_add ((GSourceFunc) device_open_failed_idle, g_object_ref (source)); return; } /* set the source name to match the device, ignoring some * particular broken device names. */ data = g_new0 (DeviceOpenedData, 1); data->source = g_object_ref (source); data->name = LIBMTP_Get_Friendlyname (device); if (data->name == NULL || strcmp (data->name, "?????") == 0) { g_free (data->name); data->name = LIBMTP_Get_Modelname (device); } if (data->name == NULL) { data->name = g_strdup (_("Digital Audio Player")); } /* get some other device information that doesn't change */ priv->manufacturer = LIBMTP_Get_Manufacturername (device); priv->device_version = LIBMTP_Get_Deviceversion (device); priv->model_name = LIBMTP_Get_Modelname (device); priv->serial = LIBMTP_Get_Serialnumber (device); /* calculate the device capacity */ priv->capacity = 0; if (LIBMTP_Get_Storage (device, LIBMTP_STORAGE_SORTBY_NOTSORTED) == 0) { LIBMTP_devicestorage_t *storage; for (storage = device->storage; storage != NULL; storage = storage->next) { priv->capacity += storage->MaxCapacity; } } update_free_space_cb (device, RB_MTP_SOURCE (source)); /* figure out the set of formats supported by the device */ if (LIBMTP_Get_Supported_Filetypes (device, &data->types, &data->num_types) != 0) { rb_mtp_thread_report_errors (priv->device_thread, FALSE); } g_idle_add ((GSourceFunc) device_opened_idle, data); /* now get the track list */ rb_mtp_thread_get_track_list (priv->device_thread, (RBMtpTrackListCallback) mtp_tracklist_cb, g_object_ref (source), g_object_unref); }
void Plugin::Upload (const QString& localPath, const QString& origPath, const QByteArray& devId, const QByteArray& storageId) { qDebug () << Q_FUNC_INFO << IsPolling_ << localPath << devId; if (IsPolling_) { UploadQueue_.append ({ localPath, origPath, devId, storageId }); return; } if (!DevicesCache_.contains (devId)) { qDebug () << "device not in cache, opening..."; bool found = false; LIBMTP_raw_device_t *rawDevices; int numRawDevices = 0; LIBMTP_Detect_Raw_Devices (&rawDevices, &numRawDevices); for (int i = 0; i < numRawDevices; ++i) { std::shared_ptr<LIBMTP_mtpdevice_t> device (LIBMTP_Open_Raw_Device (&rawDevices [i]), LIBMTP_Release_Device); if (!device) continue; const auto& serial = LIBMTP_Get_Serialnumber (device.get ()); qDebug () << "matching against" << serial; if (serial == devId) { DevicesCache_ [devId] = DeviceCacheEntry { std::move (device) }; found = true; break; } } free (rawDevices); if (!found) { qWarning () << Q_FUNC_INFO << "unable to find device" << devId; emit uploadFinished (localPath, QFile::ResourceError, tr ("Unable to find the requested device.")); return; } } const auto& entry = DevicesCache_ [devId]; UploadTo (entry.Device_.get (), storageId, localPath, origPath); }
RBBrowserSource * rb_mtp_source_new (RBShell *shell, LIBMTP_mtpdevice_t *device, const char *udi) { RBMtpSource *source = NULL; RhythmDBEntryType entry_type; RhythmDB *db = NULL; char *name = NULL; g_object_get (shell, "db", &db, NULL); name = g_strdup_printf ("MTP-%s", LIBMTP_Get_Serialnumber (device)); entry_type = rhythmdb_entry_register_type (db, name); entry_type->save_to_disk = FALSE; entry_type->category = RHYTHMDB_ENTRY_NORMAL; entry_type->get_playback_uri = (RhythmDBEntryStringFunc)rb_mtp_source_get_playback_uri; g_free (name); g_object_unref (db); source = RB_MTP_SOURCE (g_object_new (RB_TYPE_MTP_SOURCE, "entry-type", entry_type, "shell", shell, "visibility", TRUE, "volume", NULL, "source-group", RB_SOURCE_GROUP_DEVICES, "libmtp-device", device, "udi", udi, NULL)); entry_type->get_playback_uri_data = source; rb_shell_register_entry_type_for_source (shell, RB_SOURCE (source), entry_type); return RB_BROWSER_SOURCE (source); }
/* this callback runs on the device handling thread, so it can call libmtp directly */ static void mtp_device_open_cb (LIBMTP_mtpdevice_t *device, RBMtpSource *source) { RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source); gboolean has_audio = FALSE; DeviceOpenedData *data; if (device == NULL) { /* can't delete the source on this thread, so move it to the main thread */ g_idle_add ((GSourceFunc) device_open_failed_idle, g_object_ref (source)); return; } /* set the source name to match the device, ignoring some * particular broken device names. */ data = g_new0 (DeviceOpenedData, 1); data->source = g_object_ref (source); data->name = LIBMTP_Get_Friendlyname (device); if (data->name == NULL || strcmp (data->name, "?????") == 0) { g_free (data->name); data->name = LIBMTP_Get_Modelname (device); } if (data->name == NULL) { data->name = g_strdup (_("Digital Audio Player")); } /* get some other device information that doesn't change */ priv->manufacturer = LIBMTP_Get_Manufacturername (device); priv->device_version = LIBMTP_Get_Deviceversion (device); priv->model_name = LIBMTP_Get_Modelname (device); priv->serial = LIBMTP_Get_Serialnumber (device); /* calculate the device capacity */ priv->capacity = 0; if (LIBMTP_Get_Storage (device, LIBMTP_STORAGE_SORTBY_NOTSORTED) == 0) { LIBMTP_devicestorage_t *storage; for (storage = device->storage; storage != NULL; storage = storage->next) { priv->capacity += storage->MaxCapacity; } } update_free_space_cb (device, RB_MTP_SOURCE (source)); /* figure out the set of formats supported by the device, ensuring there's at least * one audio format aside from WAV. the purpose of this is to exclude cameras and other * MTP devices that aren't interesting to us. */ if (LIBMTP_Get_Supported_Filetypes (device, &data->types, &data->num_types) != 0) { rb_mtp_thread_report_errors (priv->device_thread, FALSE); } else { int i; for (i = 0; i < data->num_types; i++) { if (data->types[i] != LIBMTP_FILETYPE_WAV && LIBMTP_FILETYPE_IS_AUDIO (data->types[i])) { has_audio = TRUE; break; } } } if (has_audio == FALSE) { rb_debug ("device doesn't support any audio formats"); g_idle_add ((GSourceFunc) device_open_ignore_idle, data); return; } g_idle_add ((GSourceFunc) device_opened_idle, data); /* now get the track list */ rb_mtp_thread_get_track_list (priv->device_thread, (RBMtpTrackListCallback) mtp_tracklist_cb, g_object_ref (source), g_object_unref); }
static int Device_init(Device *self, PyObject *args, PyObject *kwds) { unsigned long busnum; unsigned char devnum; unsigned short vendor_id, product_id; PyObject *usb_serialnum; char *vendor, *product, *friendly_name, *manufacturer_name, *model_name, *serial_number, *device_version; LIBMTP_raw_device_t *rawdevs = NULL, rdev; int numdevs, c, tried_count = 0; LIBMTP_mtpdevice_t *dev = NULL; LIBMTP_error_number_t err; if (!PyArg_ParseTuple(args, "kBHHssO", &busnum, &devnum, &vendor_id, &product_id, &vendor, &product, &usb_serialnum)) return -1; // We have to build and search the rawdevice list instead of creating a // rawdevice directly as otherwise, dynamic bug flag assignment in libmtp // does not work Py_BEGIN_ALLOW_THREADS; err = LIBMTP_Detect_Raw_Devices(&rawdevs, &numdevs); Py_END_ALLOW_THREADS; if (err == LIBMTP_ERROR_NO_DEVICE_ATTACHED) { PyErr_SetString(MTPError, "No raw devices found"); return -1; } if (err == LIBMTP_ERROR_CONNECTING) { PyErr_SetString(MTPError, "There has been an error connecting"); return -1; } if (err == LIBMTP_ERROR_MEMORY_ALLOCATION) { PyErr_NoMemory(); return -1; } if (err != LIBMTP_ERROR_NONE) { PyErr_SetString(MTPError, "Failed to detect raw MTP devices"); return -1; } for (c = 0; c < numdevs; c++) { rdev = rawdevs[c]; if (rdev.bus_location == (uint32_t)busnum && rdev.devnum == (uint8_t)devnum) { tried_count += 1; Py_BEGIN_ALLOW_THREADS; dev = LIBMTP_Open_Raw_Device_Uncached(&rdev); Py_END_ALLOW_THREADS; if (dev != NULL) break; } } if (rawdevs != NULL) free(rawdevs); if (dev == NULL) { if (tried_count == 0) PyErr_Format(MTPError, "No device with busnum=%lu and devnum=%u found", busnum, devnum); else PyErr_Format(MTPError, "Unable to open MTP device with busnum=%lu and devnum=%u, tried %d such devices", busnum, devnum, tried_count); return -1; } self->device = dev; self->ids = Py_BuildValue("kBHHO", busnum, devnum, vendor_id, product_id, usb_serialnum); if (self->ids == NULL) return -1; Py_BEGIN_ALLOW_THREADS; friendly_name = LIBMTP_Get_Friendlyname(self->device); manufacturer_name = LIBMTP_Get_Manufacturername(self->device); model_name = LIBMTP_Get_Modelname(self->device); serial_number = LIBMTP_Get_Serialnumber(self->device); device_version = LIBMTP_Get_Deviceversion(self->device); Py_END_ALLOW_THREADS; if (friendly_name != NULL) { self->friendly_name = PyUnicode_FromString(friendly_name); free(friendly_name); } if (self->friendly_name == NULL) { self->friendly_name = Py_None; Py_INCREF(Py_None); } if (manufacturer_name != NULL) { self->manufacturer_name = PyUnicode_FromString(manufacturer_name); free(manufacturer_name); } if (self->manufacturer_name == NULL) { self->manufacturer_name = Py_None; Py_INCREF(Py_None); } if (model_name != NULL) { self->model_name = PyUnicode_FromString(model_name); free(model_name); } if (self->model_name == NULL) { self->model_name = Py_None; Py_INCREF(Py_None); } if (serial_number != NULL) { self->serial_number = PyUnicode_FromString(serial_number); free(serial_number); } if (self->serial_number == NULL) { self->serial_number = Py_None; Py_INCREF(Py_None); } if (device_version != NULL) { self->device_version = PyUnicode_FromString(device_version); free(device_version); } if (self->device_version == NULL) { self->device_version = Py_None; Py_INCREF(Py_None); } return 0; }