Apply patch (with changes) by Pete Goodeve: fix #4053.

Closing usb_midi now wake up midi_server port reader, as expected.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33782 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin 2009-10-26 22:28:47 +00:00
parent 912d4ba92b
commit 4c091ffef4
5 changed files with 109 additions and 90 deletions

View File

@ -3,7 +3,7 @@
* usb_midi.c * usb_midi.c
* *
* Copyright 2006-2009 Haiku Inc. All rights reserved. * Copyright 2006-2009 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT Licence. * Distributed under tthe terms of the MIT Licence.
* *
* Authors: * Authors:
* Jérôme Duval * Jérôme Duval
@ -17,10 +17,10 @@
*/ */
/*#define DEBUG 1*/ /* Define this to enable DPRINTF_INFO statements */ /* #define DEBUG 1 */ /* Define this to enable DPRINTF_INFO statements */
#include "usb_midi.h" #include "usb_midi.h"
#include <support/Debug.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -32,7 +32,6 @@
static int midi_device_number = 0; static int midi_device_number = 0;
const char* midi_base_name = "midi/usb/"; const char* midi_base_name = "midi/usb/";
usbmidi_device_info* usbmidi_device_info*
create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno) create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno)
{ {
@ -52,17 +51,9 @@ create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno)
if (my_dev == NULL) if (my_dev == NULL)
return NULL; return NULL;
my_dev->sem_cb = sem = create_sem(0, DRIVER_NAME "_cb");
if (sem < 0) {
DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem));
free(my_dev);
return NULL;
}
my_dev->sem_lock = sem = create_sem(1, DRIVER_NAME "_lock"); my_dev->sem_lock = sem = create_sem(1, DRIVER_NAME "_lock");
if (sem < 0) { if (sem < 0) {
DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem)); DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem));
delete_sem(my_dev->sem_cb);
free(my_dev); free(my_dev);
return NULL; return NULL;
} }
@ -73,7 +64,6 @@ create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno)
B_PAGE_SIZE, B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); B_PAGE_SIZE, B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
if (area < 0) { if (area < 0) {
DPRINTF_ERR((MY_ID "create_area() failed %d\n", (int)area)); DPRINTF_ERR((MY_ID "create_area() failed %d\n", (int)area));
delete_sem(my_dev->sem_cb);
delete_sem(my_dev->sem_lock); delete_sem(my_dev->sem_lock);
free(my_dev); free(my_dev);
return NULL; return NULL;
@ -83,7 +73,6 @@ create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno)
my_dev->sem_send = sem = create_sem(1, DRIVER_NAME "_send"); my_dev->sem_send = sem = create_sem(1, DRIVER_NAME "_send");
if (sem < 0) { if (sem < 0) {
DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem)); DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem));
delete_sem(my_dev->sem_cb);
delete_sem(my_dev->sem_lock); delete_sem(my_dev->sem_lock);
delete_area(area); delete_area(area);
free(my_dev); free(my_dev);
@ -92,7 +81,7 @@ create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno)
{ {
int32 bc; int32 bc;
get_sem_count(sem, &bc); get_sem_count(sem, &bc);
DPRINTF_INFO((MY_ID "Allocated %d write buffers\n", bc)); DPRINTF_INFO((MY_ID "Allocated %ld write buffers\n", bc));
} }
@ -100,11 +89,12 @@ create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno)
my_dev->dev = dev; my_dev->dev = dev;
my_dev->ifno = ifno; my_dev->ifno = ifno;
my_dev->open = 0; my_dev->open = 0;
my_dev->open_fds = NULL; my_dev->open_fd = NULL;
my_dev->active = true; my_dev->active = true;
my_dev->flags = 0; my_dev->flags = 0;
my_dev->rbuf = create_ring_buffer(1024); my_dev->rbuf = create_ring_buffer(1024);
my_dev->buffer_size = B_PAGE_SIZE/2; my_dev->buffer_size = B_PAGE_SIZE/2;
DPRINTF_INFO((MY_ID "Created device %p\n", my_dev);)
return my_dev; return my_dev;
} }
@ -118,21 +108,22 @@ remove_device(usbmidi_device_info* my_dev)
delete_ring_buffer(my_dev->rbuf); delete_ring_buffer(my_dev->rbuf);
my_dev->rbuf = NULL; my_dev->rbuf = NULL;
} }
DPRINTF_INFO((MY_ID "remove_device %p\n", my_dev);)
delete_area(my_dev->buffer_area); delete_area(my_dev->buffer_area);
delete_sem(my_dev->sem_cb);
delete_sem(my_dev->sem_lock); delete_sem(my_dev->sem_lock);
delete_sem(my_dev->sem_send); delete_sem(my_dev->sem_send);
free(my_dev); free(my_dev);
} }
/* driver cookie (per open) */ /* driver cookie (per open -- but only one open allowed!) */
typedef struct driver_cookie typedef struct driver_cookie
{ {
struct driver_cookie *next; struct driver_cookie *next;
usbmidi_device_info *my_dev; usbmidi_device_info *my_dev;
sem_id sem_cb;
} driver_cookie; } driver_cookie;
@ -174,7 +165,7 @@ interpret_midi_buffer(usbmidi_device_info* my_dev)
DPRINTF_INFO((MY_ID "received packet %x:%d %x %x %x\n", packet->cin, packet->cn, DPRINTF_INFO((MY_ID "received packet %x:%d %x %x %x\n", packet->cin, packet->cn,
packet->midi[0], packet->midi[1], packet->midi[2])); packet->midi[0], packet->midi[1], packet->midi[2]));
ring_buffer_write(my_dev->rbuf, packet->midi, pktlen); ring_buffer_write(my_dev->rbuf, packet->midi, pktlen);
release_sem_etc(my_dev->sem_cb, pktlen, B_DO_NOT_RESCHEDULE); release_sem_etc(my_dev->open_fd->sem_cb, pktlen, B_DO_NOT_RESCHEDULE);
packet++; packet++;
bytes_left -= sizeof(usb_midi_event_packet); bytes_left -= sizeof(usb_midi_event_packet);
} }
@ -193,19 +184,23 @@ midi_usb_read_callback(void* cookie, status_t status,
usbmidi_device_info* my_dev = cookie; usbmidi_device_info* my_dev = cookie;
assert(cookie != NULL); assert(cookie != NULL);
DPRINTF_INFO((MY_ID "midi_usb_read_callback() -- packet length %d\n", actual_len)); DPRINTF_INFO((MY_ID "midi_usb_read_callback() -- packet length %ld\n", actual_len));
acquire_sem(my_dev->sem_lock); acquire_sem(my_dev->sem_lock);
my_dev->actual_length = actual_len; my_dev->actual_length = actual_len;
my_dev->bus_status = status; /* B_USB_STATUS_* */ my_dev->bus_status = status; /* B_USB_STATUS_* */
if (status != B_OK) { if (status != B_OK) {
/* request failed */ /* request failed */
release_sem(my_dev->sem_lock); DPRINTF_INFO((MY_ID "bus status %d\n", (int)status)); /* previously DPRINTF_ERR */
DPRINTF_ERR((MY_ID "bus status %d\n", (int)status)); if (status == B_CANCELED || !my_dev->active) {
if (status == B_CANCELED) {
/* cancelled: device is unplugged */ /* cancelled: device is unplugged */
DPRINTF_INFO((MY_ID "midi_usb_read_callback: cancelled (status=%lx active=%d -- deleting sem_cb\n",
status, my_dev->active));
delete_sem(my_dev->open_fd->sem_cb); /* done here to ensure read is freed */
release_sem(my_dev->sem_lock);
return; return;
} }
release_sem(my_dev->sem_lock);
} else { } else {
/* got a report */ /* got a report */
#if 0 #if 0
@ -244,7 +239,7 @@ midi_usb_write_callback(void* cookie, status_t status,
#endif #endif
assert(cookie != NULL); assert(cookie != NULL);
DPRINTF_INFO((MY_ID "midi_usb_write_callback() status %ld length %d pkt %p cin %x\n", DPRINTF_INFO((MY_ID "midi_usb_write_callback() status %ld length %ld pkt %p cin %x\n",
status, actual_len, pkt, pkt->cin)); status, actual_len, pkt, pkt->cin));
release_sem(my_dev->sem_send); /* done with buffer */ release_sem(my_dev->sem_send); /* done with buffer */
} }
@ -266,7 +261,7 @@ usb_midi_added(const usb_device* dev, void** cookie)
int alt; int alt;
assert(dev != NULL && cookie != NULL); assert(dev != NULL && cookie != NULL);
DPRINTF_INFO((MY_ID "device_added()\n")); DPRINTF_INFO((MY_ID "usb_midi_added(%p, %p)\n", dev, cookie));
dev_desc = usb->get_device_descriptor(dev); dev_desc = usb->get_device_descriptor(dev);
@ -348,7 +343,7 @@ got_one:
add_device_info(my_dev); add_device_info(my_dev);
*cookie = my_dev; *cookie = my_dev;
DPRINTF_INFO((MY_ID "added %s\n", my_dev->name)); DPRINTF_INFO((MY_ID "usb_midi_added: added %s\n", my_dev->name));
return B_OK; return B_OK;
} }
@ -361,16 +356,19 @@ usb_midi_removed(void* cookie)
assert(cookie != NULL); assert(cookie != NULL);
DPRINTF_INFO((MY_ID "device_removed(%s)\n", my_dev->name)); DPRINTF_INFO((MY_ID "usb_midi_removed(%s)\n", my_dev->name));
acquire_sem(usbmidi_device_list_lock); /* convenient mutex for safety */
my_dev->active = false;
if (my_dev->open_fd) {
my_dev->open_fd->my_dev = NULL;
delete_sem(my_dev->open_fd->sem_cb); /* done here to ensure read is freed */
}
release_sem(usbmidi_device_list_lock);
usb->cancel_queued_transfers(my_dev->ept_in->handle); usb->cancel_queued_transfers(my_dev->ept_in->handle);
usb->cancel_queued_transfers(my_dev->ept_out->handle); usb->cancel_queued_transfers(my_dev->ept_out->handle);
DPRINTF_INFO((MY_ID "usb_midi_removed: removing info & device: %s\n", my_dev->name));
remove_device_info(my_dev); remove_device_info(my_dev);
if (my_dev->open == 0) { remove_device(my_dev);
remove_device(my_dev);
} else {
DPRINTF_INFO((MY_ID "%s still open\n", my_dev->name));
my_dev->active = false;
}
return B_OK; return B_OK;
} }
@ -400,22 +398,30 @@ usb_midi_open(const char* name, uint32 flags,
assert(name != NULL); assert(name != NULL);
assert(out_cookie != NULL); assert(out_cookie != NULL);
DPRINTF_INFO((MY_ID "open(%s)\n", name)); DPRINTF_INFO((MY_ID "usb_midi_open(%s)\n", name));
if ((my_dev = search_device_info(name)) == NULL) if ((my_dev = search_device_info(name)) == NULL)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
if (my_dev->open_fd != NULL)
return B_BUSY; /* there can only be one open channel to the device */
if ((cookie = malloc(sizeof(driver_cookie))) == NULL) if ((cookie = malloc(sizeof(driver_cookie))) == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
acquire_sem(my_dev->sem_lock); cookie->sem_cb = create_sem(0, DRIVER_NAME "_cb");
if (cookie->sem_cb < 0) {
DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)cookie->sem_cb));
free(cookie);
return B_ERROR;
}
acquire_sem(usbmidi_device_list_lock); /* use global mutex now */
cookie->my_dev = my_dev; cookie->my_dev = my_dev;
cookie->next = my_dev->open_fds; my_dev->open_fd = cookie;
my_dev->open_fds = cookie;
my_dev->open++; my_dev->open++;
release_sem(my_dev->sem_lock); release_sem(usbmidi_device_list_lock);
*out_cookie = cookie; *out_cookie = cookie;
DPRINTF_INFO((MY_ID "device %s open (%d)\n", name, my_dev->open)); DPRINTF_INFO((MY_ID "usb_midi_open: device %s open (%d)\n", name, my_dev->open));
return B_OK; return B_OK;
} }
@ -433,22 +439,35 @@ usb_midi_read(driver_cookie* cookie, off_t position,
assert(cookie != NULL); assert(cookie != NULL);
my_dev = cookie->my_dev; my_dev = cookie->my_dev;
assert(my_dev != NULL);
if (!my_dev->active) if (!my_dev || !my_dev->active)
return B_ERROR; /* already unplugged */ return B_ERROR; /* already unplugged */
DPRINTF_INFO((MY_ID "MIDI read (%d byte buffer at %ld cookie %p)\n", DPRINTF_INFO((MY_ID "usb_midi_read: (%ld byte buffer at %ld cookie %p)\n",
*num_bytes, (int32)position, cookie)); *num_bytes, (int32)position, cookie));
err = acquire_sem_etc(my_dev->sem_cb, 1, B_CAN_INTERRUPT, 0LL); while (my_dev && my_dev->active) {
if (err != B_OK) DPRINTF_INFOZ((MY_ID "waiting on acquire_sem_etc\n");)
return err; err = acquire_sem_etc(cookie->sem_cb, 1,
acquire_sem(my_dev->sem_lock); B_RELATIVE_TIMEOUT, 1000000);
ring_buffer_user_read(my_dev->rbuf, buf, 1); if (err == B_TIMED_OUT) {
release_sem(my_dev->sem_lock); DPRINTF_INFOZ((MY_ID "acquire_sem_etc timed out\n");)
*num_bytes = 1; continue; /* see if we're still active */
DPRINTF_INFO((MY_ID "read byte %x -- cookie %p)\n", *(uint8*)buf, cookie)); }
return err; if (err != B_OK) {
*num_bytes = 0;
DPRINTF_INFO((MY_ID "acquire_sem_etc aborted\n");)
break;
}
DPRINTF_INFO((MY_ID "reading from ringbuffer\n");)
acquire_sem(my_dev->sem_lock);
ring_buffer_user_read(my_dev->rbuf, buf, 1);
release_sem(my_dev->sem_lock);
*num_bytes = 1;
DPRINTF_INFO((MY_ID "read byte %x -- cookie %p)\n", *(uint8*)buf, cookie));
return B_OK;
}
DPRINTF_INFO((MY_ID "usb_midi_read: loop terminated -- Device no longer active\n");)
return B_CANCELED;
} }
@ -491,14 +510,13 @@ usb_midi_write(driver_cookie* cookie, off_t position,
assert(cookie != NULL); assert(cookie != NULL);
my_dev = cookie->my_dev; my_dev = cookie->my_dev;
assert(my_dev != NULL);
if (!my_dev->active) if (!my_dev || !my_dev->active)
return B_ERROR; /* already unplugged */ return B_ERROR; /* already unplugged */
buff_lim = my_dev->buffer_size * 3 / 4; /* max MIDI bytes buffer space */ buff_lim = my_dev->buffer_size * 3 / 4; /* max MIDI bytes buffer space */
DPRINTF_INFO((MY_ID "MIDI write (%d bytes at %ld)\n", *num_bytes, position)); DPRINTF_INFO((MY_ID "MIDI write (%ld bytes at %Ld)\n", *num_bytes, position));
if (*num_bytes > 3 && midicode != 0xF0) { if (*num_bytes > 3 && midicode != 0xF0) {
DPRINTF_ERR((MY_ID "Non-SysEx packet of %ld bytes -- too big to handle\n", DPRINTF_ERR((MY_ID "Non-SysEx packet of %ld bytes -- too big to handle\n",
*num_bytes)); *num_bytes));
@ -563,26 +581,20 @@ usb_midi_close(driver_cookie* cookie)
{ {
usbmidi_device_info* my_dev; usbmidi_device_info* my_dev;
assert(cookie != NULL && cookie->my_dev != NULL); assert(cookie != NULL);
delete_sem(cookie->sem_cb);
my_dev = cookie->my_dev; my_dev = cookie->my_dev;
DPRINTF_INFO((MY_ID "close(%s)\n", my_dev->name)); DPRINTF_INFO((MY_ID "usb_midi_close(%p device=%p)\n", cookie, my_dev));
/* detach the cookie from list */
acquire_sem(my_dev->sem_lock); acquire_sem(usbmidi_device_list_lock);
if (my_dev->open_fds == cookie) if (my_dev) {
my_dev->open_fds = cookie->next; /* detach the cookie from device */
else { my_dev->open_fd = NULL;
driver_cookie* p; --my_dev->open;
for (p = my_dev->open_fds; p != NULL; p = p->next) {
if (p->next == cookie) {
p->next = cookie->next;
break;
}
}
} }
--my_dev->open; release_sem(usbmidi_device_list_lock);
release_sem(my_dev->sem_lock); DPRINTF_INFO((MY_ID "usb_midi_close: complete\n");)
return B_OK; return B_OK;
} }
@ -598,17 +610,11 @@ usb_midi_free(driver_cookie* cookie)
{ {
usbmidi_device_info* my_dev; usbmidi_device_info* my_dev;
assert(cookie != NULL && cookie->my_dev != NULL); assert(cookie != NULL);
my_dev = cookie->my_dev; my_dev = cookie->my_dev;
DPRINTF_INFO((MY_ID "free(%s)\n", my_dev->name)); DPRINTF_INFO((MY_ID "usb_midi_free(%p device=%p)\n", cookie, my_dev));
free(cookie); free(cookie);
if (my_dev->open > 0)
DPRINTF_INFO((MY_ID "%d opens left\n", my_dev->open));
else if (!my_dev->active) {
DPRINTF_INFO((MY_ID "removed %s\n", my_dev->name));
remove_device(my_dev);
}
return B_OK; return B_OK;
} }
@ -683,6 +689,7 @@ uninit_driver(void)
delete_sem(usbmidi_device_list_lock); delete_sem(usbmidi_device_list_lock);
put_module(B_USB_MODULE_NAME); put_module(B_USB_MODULE_NAME);
free_device_names(); free_device_names();
DPRINTF_INFO((MY_ID "uninit complete\n"));
} }

View File

@ -62,7 +62,6 @@ typedef struct usbmidi_device_info
struct usbmidi_device_info* next; struct usbmidi_device_info* next;
/* maintain device */ /* maintain device */
sem_id sem_cb;
sem_id sem_lock; sem_id sem_lock;
sem_id sem_send; sem_id sem_send;
area_id buffer_area; area_id buffer_area;
@ -77,7 +76,7 @@ typedef struct usbmidi_device_info
bool active; bool active;
int open; int open;
struct driver_cookie* open_fds; struct driver_cookie* open_fd;
/* work area for transfer */ /* work area for transfer */
int usbd_status, bus_status, cmd_status; int usbd_status, bus_status, cmd_status;

View File

@ -8,7 +8,6 @@
* Philippe Houdoin * Philippe Houdoin
*/ */
#include "debug.h" #include "debug.h"
#include "DeviceWatcher.h" #include "DeviceWatcher.h"
#include "PortDrivers.h" #include "PortDrivers.h"
@ -32,8 +31,8 @@ using namespace BPrivate;
using BPrivate::HashMap; using BPrivate::HashMap;
using BPrivate::HashString; using BPrivate::HashString;
const char *kDevicesRoot = "/dev/midi"; const char *kDevicesRoot = "/dev/midi";
// const char *kDevicesRoot = "/Data/tmp";
class DeviceEndpoints { class DeviceEndpoints {
@ -185,12 +184,13 @@ DeviceWatcher::_AddDevice(const char* path)
if (fDeviceEndpointsMap.ContainsKey(path)) { if (fDeviceEndpointsMap.ContainsKey(path)) {
// Already known // Already known
TRACE(("already known...!\n"));
return; return;
} }
BEntry entry(path); BEntry entry(path);
if (entry.IsDirectory()) if (entry.IsDirectory())
// Invalid path ! // Invalid path!
return; return;
if (entry.IsSymLink()) { if (entry.IsSymLink()) {
@ -203,8 +203,11 @@ DeviceWatcher::_AddDevice(const char* path)
int fd = open(path, O_RDWR | O_EXCL); int fd = open(path, O_RDWR | O_EXCL);
if (fd < 0) if (fd < 0)
return; return;
TRACE(("Doing _AddDevice(\"%s\"); fd=%d\n", path, fd));
MidiPortConsumer* consumer = new MidiPortConsumer(fd, path); MidiPortConsumer* consumer = new MidiPortConsumer(fd, path);
_SetIcons(consumer); _SetIcons(consumer);
TRACE(("Register %s MidiPortConsumer\n", consumer->Name())); TRACE(("Register %s MidiPortConsumer\n", consumer->Name()));
@ -217,6 +220,7 @@ DeviceWatcher::_AddDevice(const char* path)
DeviceEndpoints* deviceEndpoints = new DeviceEndpoints(fd, consumer, producer); DeviceEndpoints* deviceEndpoints = new DeviceEndpoints(fd, consumer, producer);
fDeviceEndpointsMap.Put(path, deviceEndpoints); fDeviceEndpointsMap.Put(path, deviceEndpoints);
TRACE(("Done _AddDevice(\"%s\")\n", path));
} }
@ -226,18 +230,23 @@ DeviceWatcher::_RemoveDevice(const char* path)
TRACE(("DeviceWatcher::_RemoveDevice(\"%s\");\n", path)); TRACE(("DeviceWatcher::_RemoveDevice(\"%s\");\n", path));
DeviceEndpoints* deviceEndpoints = fDeviceEndpointsMap.Get(path); DeviceEndpoints* deviceEndpoints = fDeviceEndpointsMap.Get(path);
if (!deviceEndpoints) if (!deviceEndpoints) {
TRACE(("_RemoveDevice(\"%s\") didn't find endpoint in map!!\n", path));
return; return;
}
close(deviceEndpoints->fFD);
TRACE((" _RemoveDevice(\"%s\") unregistering\n", path));
deviceEndpoints->fConsumer->Unregister(); deviceEndpoints->fConsumer->Unregister();
deviceEndpoints->fProducer->Unregister(); deviceEndpoints->fProducer->Unregister();
TRACE((" _RemoveDevice(\"%s\") releasing\n", path));
deviceEndpoints->fConsumer->Release(); deviceEndpoints->fConsumer->Release();
deviceEndpoints->fProducer->Release(); deviceEndpoints->fProducer->Release();
TRACE((" _RemoveDevice(\"%s\") removing from map\n", path));
fDeviceEndpointsMap.Remove(path); fDeviceEndpointsMap.Remove(path);
TRACE(("Done _RemoveDevice(\"%s\")\n", path));
} }

View File

@ -15,6 +15,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <String.h> #include <String.h>
@ -90,7 +91,10 @@ MidiPortProducer::GetData()
while (fKeepRunning) { while (fKeepRunning) {
if (read(fFileDescriptor, &next, 1) != 1) { if (read(fFileDescriptor, &next, 1) != 1) {
perror("Error reading data from driver"); if (errno == B_CANCELED)
fKeepRunning = false;
else
perror("Error reading data from driver");
break; break;
} }
@ -234,5 +238,5 @@ MidiPortProducer::GetData()
if (haveSysEx) if (haveSysEx)
free(sysexBuf); free(sysexBuf);
return fKeepRunning ? B_ERROR : B_OK; return fKeepRunning ? errno : B_OK;
} }

View File

@ -10,7 +10,7 @@ resource app_version {
variety = B_APPV_ALPHA, variety = B_APPV_ALPHA,
internal = 0, internal = 0,
short_info = "midi_server", short_info = "midi_server",
long_info = "midi_server ©2002-2006 Haiku" long_info = "midi_server ©2002-2009 Haiku"
}; };
resource vector_icon array { resource vector_icon array {