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:
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user