4
У меня есть следующие миди обертка для Python3:MIDIGetNumberOfDestinations возвращающиеся 0 при использовании Python C API
#include <Python.h>
#include "structmember.h"
#include <CoreMIDI/CoreMIDI.h>
#include "stdio.h"
#define MESSAGESIZE 3
// CFStringRef to char*
char * MYCFStringCopyUTF8String(CFStringRef aString) {
if (aString == NULL) {
return NULL;
}
CFIndex length = CFStringGetLength(aString);
CFIndex maxSize =
CFStringGetMaximumSizeForEncoding(length,
kCFStringEncodingUTF8);
char *buffer = (char *)malloc(maxSize);
if (CFStringGetCString(aString, buffer, maxSize,
kCFStringEncodingUTF8)) {
return buffer;
}
return NULL;
}
typedef struct {
PyObject_HEAD
} Midi;
static void Midi_dealloc(Midi* self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
static int Midi_init(Midi *self)
{
ItemCount nDests = MIDIGetNumberOfDestinations();
printf("INIT\n");
for (ItemCount i = 0 ; i < nDests ; ++i) {
// Grab a reference to current device
MIDIDeviceRef device = MIDIGetDevice(i);
CFStringRef name = nil;
MIDIObjectGetStringProperty(device, kMIDIPropertyName, &name);
printf("%s\n", MYCFStringCopyUTF8String(name));
}
printf("END\n");
return 0;
}
static PyObject * Midi_add(Midi* self, PyObject *args)
{
return Py_None;
}
static PyObject * Midi_bend(Midi* self, PyObject *args)
{
return Py_None;
}
static PyObject * Midi_play(Midi* self)
{
return Py_None;
}
static PyMethodDef Midi_methods[] =
{
{"add", (PyCFunction)Midi_add, METH_VARARGS, "Add note"},
{"bend", (PyCFunction)Midi_bend, METH_VARARGS, "Bend note"},
{"play", (PyCFunction)Midi_play, METH_NOARGS, "Play Notes"},
{NULL} /* Sentinel */
};
static PyTypeObject MidiType = {
PyVarObject_HEAD_INIT(NULL, 0)
"midi.Midi", /* tp_name */
sizeof(Midi), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)Midi_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE, /* tp_flags */
"Midi objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Midi_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Midi_init, /* tp_init */
};
static PyModuleDef midimodule = {
PyModuleDef_HEAD_INIT,
"midi",
"Midi Module",
-1,
NULL, NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC
PyInit_midi(void)
{
PyObject* m;
MidiType.tp_new = PyType_GenericNew;
if (PyType_Ready(&MidiType) < 0)
return NULL;
m = PyModule_Create(&midimodule);
if (m == NULL)
return NULL;
Py_INCREF(&MidiType);
PyModule_AddObject(m, "Midi", (PyObject *)&MidiType);
return m;
}
Со следующим setup.py файл:
from distutils.core import setup, Extension
module = Extension('midi', sources = ['midi.c'], extra_link_args=['-framework', 'CoreMIDI', '-framework', 'CoreFoundation'])
setup (name = 'Midi',
version = '1.0',
description = 'Midi Controller',
ext_modules = [module])
Я тогда запустить этот питон код, но это дает мне:
import midi
m = midi.Midi()
но он выводит просто на Mavericks:
INIT
END
I.e. он не находит устройств.
Я также попытался это:
#import <CoreMIDI/CoreMIDI.h>
char * MYCFStringCopyUTF8String(CFStringRef aString) {
if (aString == NULL) {
return NULL;
}
CFIndex length = CFStringGetLength(aString);
CFIndex maxSize =
CFStringGetMaximumSizeForEncoding(length,
kCFStringEncodingUTF8);
char *buffer = (char *)malloc(maxSize);
if (CFStringGetCString(aString, buffer, maxSize,
kCFStringEncodingUTF8)) {
return buffer;
}
return NULL;
}
int main(int argc, char *argv[])
{
// How many MIDI devices do we have?
ItemCount deviceCount = MIDIGetNumberOfDevices();
// Iterate through all MIDI devices
for (ItemCount i = 0 ; i < deviceCount ; ++i) {
// Grab a reference to current device
MIDIDeviceRef device = MIDIGetDevice(i);
CFStringRef name = nil;
MIDIObjectGetStringProperty(device, kMIDIPropertyName, &name);
printf("%s\n", MYCFStringCopyUTF8String(name));
}
}
С Нижеследующее файла:
SRCS = midi2.c
OBJS = midi2.o
LIBS = -framework CoreMIDI -framework CoreFoundation
TARGET = Midi2
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(SRCS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
Какие правильно перечислены мои миди устройства. Что я делаю не так?
MIDIGetNumberOfDestinations() возвращает «Число пунктов назначения в системе или 0, если произошла ошибка». Вы пытались каким-то образом отладить его? – twil
@twil Что я могу отлаживать? Функция возвращает 2 при ее вызове из очень простой функции c и 0 при вызове с использованием API-интерфейса Python. Я думаю, что проблема связана с компоновщиком, хотя я не получаю ошибок при запуске установки python. Например, я могу изменить «CoreMIDI» на «Foo» в файле setup.py, и я не получаю ошибок. – Baz
Почему вы вызываете 'MIDIGetNumberOfDestinations()' в примере Python, но 'MIDIGetNumberOfDevices()' в примере на C? –