Adds support for read or write-only midi devices entries.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40419 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2011-02-10 13:19:22 +00:00
parent 443a3c5991
commit 3db9c51d0f
+67 -45
View File
@@ -13,6 +13,8 @@
#include "DeviceWatcher.h" #include "DeviceWatcher.h"
#include "PortDrivers.h" #include "PortDrivers.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <new> #include <new>
@@ -43,7 +45,7 @@ public:
: fFD(fd), fConsumer(consumer), fProducer(producer) : fFD(fd), fConsumer(consumer), fProducer(producer)
{ {
} }
int fFD; int fFD;
MidiPortConsumer* fConsumer; MidiPortConsumer* fConsumer;
MidiPortProducer* fProducer; MidiPortProducer* fProducer;
@@ -53,7 +55,7 @@ public:
DeviceWatcher::DeviceWatcher() DeviceWatcher::DeviceWatcher()
: BLooper("MIDI devices watcher"), : BLooper("MIDI devices watcher"),
fDeviceEndpointsMap(), fVectorIconData(NULL), fVectorIconDataSize(0), fDeviceEndpointsMap(), fVectorIconData(NULL), fVectorIconDataSize(0),
fLargeIcon(NULL), fMiniIcon(NULL) fLargeIcon(NULL), fMiniIcon(NULL)
{ {
// Load midi endpoint vector icon data // Load midi endpoint vector icon data
@@ -67,10 +69,10 @@ DeviceWatcher::DeviceWatcher()
// Load MIDI port endpoint vector icon // Load MIDI port endpoint vector icon
const uint8* data = (const uint8*)resources.LoadResource( const uint8* data = (const uint8*)resources.LoadResource(
B_VECTOR_ICON_TYPE, "endpoint_vector_icon", &dataSize); B_VECTOR_ICON_TYPE, "endpoint_vector_icon", &dataSize);
if (data != NULL && dataSize > 0) if (data != NULL && dataSize > 0)
fVectorIconData = new(std::nothrow) uint8[dataSize]; fVectorIconData = new(std::nothrow) uint8[dataSize];
if (fVectorIconData) { if (fVectorIconData) {
// data is own by resources local object: copy its content for // data is own by resources local object: copy its content for
// later use // later use
@@ -79,17 +81,17 @@ DeviceWatcher::DeviceWatcher()
} }
} }
// Render 32x32 and 16x16 B_CMAP8 icons for R5 compatibility // Render 32x32 and 16x16 B_CMAP8 icons for R5 compatibility
if (fVectorIconData != NULL) { if (fVectorIconData != NULL) {
fLargeIcon = new(std::nothrow) BBitmap(BRect(0, 0, 31, 31), B_CMAP8); fLargeIcon = new(std::nothrow) BBitmap(BRect(0, 0, 31, 31), B_CMAP8);
fMiniIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_CMAP8); fMiniIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_CMAP8);
if (BIconUtils::GetVectorIcon(fVectorIconData, fVectorIconDataSize, if (BIconUtils::GetVectorIcon(fVectorIconData, fVectorIconDataSize,
fLargeIcon) != B_OK) { fLargeIcon) != B_OK) {
delete fLargeIcon; delete fLargeIcon;
fLargeIcon = NULL; fLargeIcon = NULL;
} }
if (BIconUtils::GetVectorIcon(fVectorIconData, fVectorIconDataSize, if (BIconUtils::GetVectorIcon(fVectorIconData, fVectorIconDataSize,
fMiniIcon) != B_OK) { fMiniIcon) != B_OK) {
delete fMiniIcon; delete fMiniIcon;
fMiniIcon = NULL; fMiniIcon = NULL;
@@ -103,14 +105,14 @@ DeviceWatcher::DeviceWatcher()
DeviceWatcher::~DeviceWatcher() DeviceWatcher::~DeviceWatcher()
{ {
Stop(); Stop();
delete fLargeIcon; delete fLargeIcon;
delete fMiniIcon; delete fMiniIcon;
delete[] fVectorIconData; delete[] fVectorIconData;
} }
status_t status_t
DeviceWatcher::Start() DeviceWatcher::Start()
{ {
// Do an initial scan // Do an initial scan
@@ -120,7 +122,7 @@ DeviceWatcher::Start()
// message to the midi_server to register itself, and blocks until it gets // message to the midi_server to register itself, and blocks until it gets
// a response. But since we _are_ the midi_server we will never be able to // a response. But since we _are_ the midi_server we will never be able to
// send that response if our main thread is already blocking. // send that response if our main thread is already blocking.
resume_thread(spawn_thread(_InitialDevicesScanThread, resume_thread(spawn_thread(_InitialDevicesScanThread,
"Initial devices scan", B_NORMAL_PRIORITY, this)); "Initial devices scan", B_NORMAL_PRIORITY, this));
@@ -131,7 +133,7 @@ DeviceWatcher::Start()
} }
status_t status_t
DeviceWatcher::Stop() DeviceWatcher::Stop()
{ {
return BPathMonitor::StopWatching(kDevicesRoot, this); return BPathMonitor::StopWatching(kDevicesRoot, this);
@@ -143,11 +145,11 @@ DeviceWatcher::MessageReceived(BMessage* message)
{ {
if (message->what != B_PATH_MONITOR) if (message->what != B_PATH_MONITOR)
return; return;
int32 opcode; int32 opcode;
if (message->FindInt32("opcode", &opcode) != B_OK) if (message->FindInt32("opcode", &opcode) != B_OK)
return; return;
// message->PrintToStream(); // message->PrintToStream();
const char* path; const char* path;
@@ -171,7 +173,7 @@ DeviceWatcher::MessageReceived(BMessage* message)
/* static */ /* static */
int32 int32
DeviceWatcher::_InitialDevicesScanThread(void* data) DeviceWatcher::_InitialDevicesScanThread(void* data)
{ {
((DeviceWatcher*)data)->_ScanDevices(kDevicesRoot); ((DeviceWatcher*)data)->_ScanDevices(kDevicesRoot);
@@ -179,15 +181,15 @@ DeviceWatcher::_InitialDevicesScanThread(void* data)
} }
void void
DeviceWatcher::_ScanDevices(const char* path) DeviceWatcher::_ScanDevices(const char* path)
{ {
TRACE(("DeviceWatcher::_ScanDevices(\"%s\");\n", path)); TRACE(("DeviceWatcher::_ScanDevices(\"%s\");\n", path));
BDirectory dir(path); BDirectory dir(path);
if (dir.InitCheck() != B_OK) if (dir.InitCheck() != B_OK)
return; return;
BEntry entry; BEntry entry;
while (dir.GetNextEntry(&entry) == B_OK) { while (dir.GetNextEntry(&entry) == B_OK) {
BPath name; BPath name;
@@ -210,12 +212,12 @@ DeviceWatcher::_AddDevice(const char* path)
TRACE(("already known...!\n")); 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()) {
BEntry symlink(path, true); BEntry symlink(path, true);
if (symlink.IsDirectory()) { if (symlink.IsDirectory()) {
@@ -225,24 +227,40 @@ 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; if (errno != EACCES)
return;
// maybe it's a input or output only port?
fd = open(path, O_RDONLY | O_EXCL);
if (fd < 0 && errno == EACCES)
fd = open(path, O_WRONLY | O_EXCL);
if (fd < 0)
return;
}
TRACE(("Doing _AddDevice(\"%s\"); fd=%d\n", path, fd)); TRACE(("Doing _AddDevice(\"%s\"); fd=%d\n", path, fd));
MidiPortConsumer* consumer = new MidiPortConsumer(fd, path); MidiPortConsumer* consumer = NULL;
_SetIcons(consumer); MidiPortProducer* producer = NULL;
TRACE(("Register %s MidiPortConsumer\n", consumer->Name()));
consumer->Register();
MidiPortProducer* producer = new MidiPortProducer(fd, path); int flags = fcntl(fd, F_GETFL);
_SetIcons(producer);
TRACE(("Register %s MidiPortProducer\n", producer->Name()));
producer->Register();
DeviceEndpoints* deviceEndpoints = new DeviceEndpoints(fd, consumer, producer); if ((flags & O_ACCMODE) != O_RDONLY) {
fDeviceEndpointsMap.Put(path, deviceEndpoints); consumer = new MidiPortConsumer(fd, path);
_SetIcons(consumer);
TRACE(("Register %s MidiPortConsumer\n", consumer->Name()));
consumer->Register();
}
if ((flags & O_ACCMODE) != O_WRONLY) {
producer = new MidiPortProducer(fd, path);
_SetIcons(producer);
TRACE(("Register %s MidiPortProducer\n", producer->Name()));
producer->Register();
}
fDeviceEndpointsMap.Put(path, new DeviceEndpoints(fd, consumer, producer));
TRACE(("Done _AddDevice(\"%s\")\n", path)); TRACE(("Done _AddDevice(\"%s\")\n", path));
} }
@@ -251,20 +269,24 @@ void
DeviceWatcher::_RemoveDevice(const char* path) 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)); TRACE(("_RemoveDevice(\"%s\") didn't find endpoint in map!!\n", path));
return; return;
} }
TRACE((" _RemoveDevice(\"%s\") unregistering\n", path)); TRACE((" _RemoveDevice(\"%s\") unregistering\n", path));
deviceEndpoints->fConsumer->Unregister(); if (deviceEndpoints->fConsumer)
deviceEndpoints->fProducer->Unregister(); deviceEndpoints->fConsumer->Unregister();
if (deviceEndpoints->fProducer)
deviceEndpoints->fProducer->Unregister();
TRACE((" _RemoveDevice(\"%s\") releasing\n", path)); TRACE((" _RemoveDevice(\"%s\") releasing\n", path));
deviceEndpoints->fConsumer->Release(); if (deviceEndpoints->fConsumer)
deviceEndpoints->fProducer->Release(); deviceEndpoints->fConsumer->Release();
if (deviceEndpoints->fProducer)
deviceEndpoints->fProducer->Release();
TRACE((" _RemoveDevice(\"%s\") removing from map\n", path)); TRACE((" _RemoveDevice(\"%s\") removing from map\n", path));
fDeviceEndpointsMap.Remove(path); fDeviceEndpointsMap.Remove(path);
@@ -272,23 +294,23 @@ DeviceWatcher::_RemoveDevice(const char* path)
} }
void void
DeviceWatcher::_SetIcons(BMidiEndpoint* endpoint) DeviceWatcher::_SetIcons(BMidiEndpoint* endpoint)
{ {
BMessage msg; BMessage msg;
if (fVectorIconData && fVectorIconDataSize > 0) { if (fVectorIconData && fVectorIconDataSize > 0) {
msg.AddData("icon", B_VECTOR_ICON_TYPE, fVectorIconData, msg.AddData("icon", B_VECTOR_ICON_TYPE, fVectorIconData,
fVectorIconDataSize); fVectorIconDataSize);
} }
if (fLargeIcon) { if (fLargeIcon) {
msg.AddData("be:large_icon", B_LARGE_ICON_TYPE, fLargeIcon->Bits(), msg.AddData("be:large_icon", B_LARGE_ICON_TYPE, fLargeIcon->Bits(),
fLargeIcon->BitsLength()); fLargeIcon->BitsLength());
} }
if (fMiniIcon) { if (fMiniIcon) {
msg.AddData("be:mini_icon", B_MINI_ICON_TYPE, fMiniIcon->Bits(), msg.AddData("be:mini_icon", B_MINI_ICON_TYPE, fMiniIcon->Bits(),
fMiniIcon->BitsLength()); fMiniIcon->BitsLength());
} }