mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Use bulk fetch for list_folder by name
This commit is contained in:
parent
f19ca06b86
commit
b8c92ac9ce
@ -7,6 +7,7 @@
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include <dictobject.h>
|
||||
#include <new>
|
||||
|
||||
namespace wpd {
|
||||
@ -169,12 +170,14 @@ private:
|
||||
if (PyDict_SetItem(this->items, object_id.ptr(), obj.ptr()) != 0) { PyErr_Clear(); return; }
|
||||
} else Py_INCREF(obj.ptr());
|
||||
set_properties(obj.ptr(), properties);
|
||||
pyobject_raii r(PyObject_CallFunction(callback, "OI", obj.ptr(), this->level));
|
||||
if (!r) PyErr_Clear();
|
||||
else if (r && PyObject_IsTrue(r.ptr())) {
|
||||
PyObject *borrowed = PyDict_GetItemString(obj.ptr(), "id");
|
||||
if (borrowed) if (PyList_Append(this->subfolders, borrowed) != 0) PyErr_Clear();
|
||||
}
|
||||
if (callback) {
|
||||
pyobject_raii r(PyObject_CallFunction(callback, "OI", obj.ptr(), this->level));
|
||||
if (!r) PyErr_Clear();
|
||||
else if (r && PyObject_IsTrue(r.ptr())) {
|
||||
PyObject *borrowed = PyDict_GetItemString(obj.ptr(), "id");
|
||||
if (borrowed) if (PyList_Append(this->subfolders, borrowed) != 0) PyErr_Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_values(IPortableDeviceValuesCollection* values) {
|
||||
@ -422,9 +425,11 @@ single_get_filesystem(unsigned int level, CComPtr<IPortableDeviceContent> &conte
|
||||
if (SUCCEEDED(hr) && pv.pwszVal != NULL) {
|
||||
pyobject_raii item(get_object_properties(devprops, properties, pv.pwszVal));
|
||||
if (!item) return false;
|
||||
pyobject_raii r(PyObject_CallFunction(callback, "OI", item.ptr(), level));
|
||||
if (PyDict_SetItem(ans, PyDict_GetItemString(item.ptr(), "id"), item.ptr()) != 0) return false;
|
||||
if (r && PyObject_IsTrue(r.ptr())) recurse.attach(item.detach());
|
||||
if (callback) {
|
||||
pyobject_raii r(PyObject_CallFunction(callback, "OI", item.ptr(), level));
|
||||
if (r && PyObject_IsTrue(r.ptr())) recurse.attach(item.detach());
|
||||
}
|
||||
} else { hresult_set_exc("Failed to get item from IPortableDevicePropVariantCollection", hr); return false; }
|
||||
|
||||
if (recurse) {
|
||||
@ -468,42 +473,28 @@ create_object_properties(const wchar_t *parent_id, const wchar_t *name, const GU
|
||||
} // }}}
|
||||
|
||||
PyObject*
|
||||
list_folder(CComPtr<IPortableDeviceContent> &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *folder_id) {
|
||||
list_folder(IPortableDevice *device, CComPtr<IPortableDeviceContent> &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *folder_id) {
|
||||
HRESULT hr;
|
||||
CComPtr<IPortableDevicePropVariantCollection> object_ids;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
hr = object_ids.CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); return NULL; }
|
||||
pyobject_raii ans(PyDict_New()); if (!ans) return NULL;
|
||||
|
||||
bool enum_failed = false;
|
||||
if (!find_objects_in(content, object_ids, folder_id, &enum_failed)) return NULL;
|
||||
DWORD num;
|
||||
CComPtr<IPortableDeviceProperties> devprops;
|
||||
|
||||
hr = content->Properties(&devprops);
|
||||
if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); return NULL; }
|
||||
|
||||
CComPtr<IPortableDeviceKeyCollection> properties(create_filesystem_properties_collection());
|
||||
if (!properties) return NULL;
|
||||
hr = object_ids->GetCount(&num);
|
||||
if (FAILED(hr)) { hresult_set_exc("Failed to get object id count", hr); return NULL; }
|
||||
pyobject_raii ans(PyList_New(0)); if (!ans) return NULL;
|
||||
|
||||
for (DWORD i = 0; i < num; i++) {
|
||||
prop_variant pv;
|
||||
hr = object_ids->GetAt(i, &pv);
|
||||
if (SUCCEEDED(hr) && pv.pwszVal != NULL) {
|
||||
pyobject_raii item(get_object_properties(devprops, properties, pv.pwszVal));
|
||||
if (!item) return NULL;
|
||||
if (PyList_Append(ans.ptr(), item.ptr()) != 0) return NULL;
|
||||
}
|
||||
if (bulk_properties) {
|
||||
if (!bulk_get_filesystem(0, device, bulk_properties, object_ids, NULL, ans.ptr(), NULL)) return NULL;
|
||||
} else {
|
||||
if (!single_get_filesystem(0, content, object_ids, NULL, ans.ptr(), NULL)) return NULL;
|
||||
}
|
||||
return ans.detach();
|
||||
}
|
||||
|
||||
PyObject*
|
||||
find_in_parent(CComPtr<IPortableDeviceContent> &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *parent_id, PyObject *name) {
|
||||
find_in_parent(CComPtr<IPortableDeviceContent> &content, const wchar_t *parent_id, PyObject *name) {
|
||||
HRESULT hr;
|
||||
CComPtr<IPortableDevicePropVariantCollection> object_ids;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
|
@ -97,7 +97,7 @@ list_folder_by_name(Device *self, PyObject *args) {
|
||||
PyObject *k = PyTuple_GET_ITEM(names, i);
|
||||
if (!PyUnicode_Check(k)) { PyErr_SetString(PyExc_TypeError, "names must contain only unicode strings"); return NULL; }
|
||||
pyobject_raii l(PyObject_CallMethod(k, "lower", NULL)); if (!l) return NULL;
|
||||
pyobject_raii object_id(wpd::find_in_parent(content, self->bulk_properties, parent_id.ptr(), l.ptr()));
|
||||
pyobject_raii object_id(wpd::find_in_parent(content, parent_id.ptr(), l.ptr()));
|
||||
if (!object_id) {
|
||||
if (PyErr_Occurred()) return NULL;
|
||||
Py_RETURN_NONE;
|
||||
@ -106,7 +106,7 @@ list_folder_by_name(Device *self, PyObject *args) {
|
||||
found = true;
|
||||
}
|
||||
if (!found) Py_RETURN_NONE;
|
||||
return wpd::list_folder(content, self->bulk_properties, parent_id.ptr());
|
||||
return wpd::list_folder(self->device, content, self->bulk_properties, parent_id.ptr());
|
||||
} // }}}
|
||||
|
||||
// create_folder() {{{
|
||||
|
@ -398,7 +398,7 @@ class MTP_DEVICE(MTPDeviceBase):
|
||||
x = self.dev.list_folder_by_name(parent.object_id, names)
|
||||
if x is None:
|
||||
raise DeviceError(f'Could not find folder named: {"/".join(names)} in {parent.full_path}')
|
||||
return x
|
||||
return list(x.values())
|
||||
|
||||
@same_thread
|
||||
def get_mtp_file(self, f, stream=None, callback=None):
|
||||
|
@ -50,7 +50,8 @@ extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id
|
||||
extern PyObject* delete_object(IPortableDevice *device, const wchar_t *object_id);
|
||||
extern PyObject* put_file(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name, PyObject *src, unsigned PY_LONG_LONG size, PyObject *callback);
|
||||
extern PyObject* find_in_parent(
|
||||
CComPtr<IPortableDeviceContent> &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *parent_id, PyObject *name);
|
||||
CComPtr<IPortableDeviceContent> &content, const wchar_t *parent_id, PyObject *name);
|
||||
extern PyObject* list_folder(
|
||||
CComPtr<IPortableDeviceContent> &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *folder_id);
|
||||
IPortableDevice *device, CComPtr<IPortableDeviceContent> &content, IPortableDevicePropertiesBulk *bulk_properties,
|
||||
const wchar_t *folder_id);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user