diff --git a/src/servers/midi/DeviceWatcher.cpp b/src/servers/midi/DeviceWatcher.cpp index c7c7299ab8..b25a2c2a60 100644 --- a/src/servers/midi/DeviceWatcher.cpp +++ b/src/servers/midi/DeviceWatcher.cpp @@ -1,26 +1,17 @@ /* - * Copyright (c) 2003 Matthijs Hollemans - * Copyright (c) 2003 Jerome Leveque + * Copyright 2004-2009, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * Authors: + * Matthijs Hollemans + * Jerome Leveque + * Philippe Houdoin */ +#include "DeviceWatcher.h" +#include "PortDrivers.h" +#include "debug.h" + #include #include #include @@ -30,114 +21,164 @@ #include #include -#include "DeviceWatcher.h" -#include "PortDrivers.h" -#include "debug.h" +#include -//------------------------------------------------------------------------------ +using namespace BPrivate; + +const char *kDevicesRoot = "/dev/midi"; DeviceWatcher::DeviceWatcher() + : BLooper("MIDI devices watcher") { - largeIcon = new BBitmap(BRect(0, 0, 31, 31), B_CMAP8); - miniIcon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8); + // TODO: add support for vector icons + + fLargeIcon = new BBitmap(BRect(0, 0, 31, 31), B_CMAP8); + fMiniIcon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8); app_info info; be_app->GetAppInfo(&info); BFile file(&info.ref, B_READ_ONLY); BResources res; - if (res.SetTo(&file) == B_OK) - { + if (res.SetTo(&file) == B_OK) { size_t size; const void* bits; bits = res.LoadResource(B_LARGE_ICON_TYPE, 10, &size); - largeIcon->SetBits(bits, size, 0, B_CMAP8); + fLargeIcon->SetBits(bits, size, 0, B_CMAP8); bits = res.LoadResource(B_MINI_ICON_TYPE, 11, &size); - miniIcon->SetBits(bits, size, 0, B_CMAP8); + fMiniIcon->SetBits(bits, size, 0, B_CMAP8); } + + Start(); } -//------------------------------------------------------------------------------ DeviceWatcher::~DeviceWatcher() { - delete largeIcon; - delete miniIcon; + Stop(); + + delete fLargeIcon; + delete fMiniIcon; } -//------------------------------------------------------------------------------ -void DeviceWatcher::Start() +status_t +DeviceWatcher::Start() { - // We need to do this from a separate thread, otherwise we will deadlock. - // The reason is that we instantiate a BMidiRoster object, which sends a - // 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 - // send that response if our main thread is already blocking. + // Do an initial scan + _ScanDevices(kDevicesRoot); - resume_thread(spawn_thread( - SpawnThread, "DeviceWatcher", B_NORMAL_PRIORITY, this)); + // Okay, now just watch for any change + return BPathMonitor::StartWatching(kDevicesRoot, B_ENTRY_CREATED + | B_ENTRY_REMOVED | B_ENTRY_MOVED | B_WATCH_FILES_ONLY + | B_WATCH_RECURSIVELY, this); } -//------------------------------------------------------------------------------ -int32 DeviceWatcher::SpawnThread(void* data) +status_t +DeviceWatcher::Stop() { - ((DeviceWatcher*) data)->ScanDevices("/dev/midi"); - return 0; + return BPathMonitor::StopWatching(kDevicesRoot, this); } -//------------------------------------------------------------------------------ -void DeviceWatcher::ScanDevices(const char* path) +void +DeviceWatcher::MessageReceived(BMessage* message) { - BDirectory dir(path); - if (dir.InitCheck() == B_OK) - { - BEntry entry; - while (dir.GetNextEntry(&entry) == B_OK) - { - BPath name; - entry.GetPath(&name); - if (entry.IsDirectory()) - { - ScanDevices(name.Path()); - } - else - { - int fd = open(name.Path(), O_RDWR | O_EXCL); - if (fd >= 0) - { - BMidiEndpoint* endp; + if (message->what != B_PATH_MONITOR) + return; + + int32 opcode; + if (message->FindInt32("opcode", &opcode) != B_OK) + return; + + // message->PrintToStream(); - endp = new MidiPortConsumer(fd, name.Path()); - SetIcons(endp); - endp->Register(); + const char* path; + if (message->FindString("path", &path) != B_OK) + return; - endp = new MidiPortProducer(fd, name.Path()); - SetIcons(endp); - endp->Register(); - } - } + switch (opcode) { + case B_ENTRY_CREATED: { + _AddDevice(path); + break; + } + case B_ENTRY_REMOVED: { + _RemoveDevice(path); + break; } } } -//------------------------------------------------------------------------------ -void DeviceWatcher::SetIcons(BMidiEndpoint* endp) +// #pragma mark - + + +void +DeviceWatcher::_ScanDevices(const char* path) +{ + BDirectory dir(path); + if (dir.InitCheck() != B_OK) + return; + + BEntry entry; + while (dir.GetNextEntry(&entry) == B_OK) { + BPath name; + entry.GetPath(&name); + if (entry.IsDirectory()) + _ScanDevices(name.Path()); + else + _AddDevice(name.Path()); + } +} + + +void +DeviceWatcher::_AddDevice(const char* path) +{ + int fd = open(path, O_RDWR | O_EXCL); + if (fd < 0) + return; + + // printf("DeviceWatcher::_AddDevice(\"%s\");\n", path); + + BMidiEndpoint* endpoint; + + endpoint = new MidiPortConsumer(fd, path); + _SetIcons(endpoint); + printf("Register %s MidiPortConsumer\n", endpoint->Name()); + endpoint->Register(); + + endpoint = new MidiPortProducer(fd, path); + _SetIcons(endpoint); + printf("Register %s MidiPortProducer\n", endpoint->Name()); + endpoint->Register(); +} + + +void +DeviceWatcher::_RemoveDevice(const char* path) +{ + // printf("DeviceWatcher::_RemoveDevice(\"%s\");\n", path); + + // TODO: handle device removing +} + + +void +DeviceWatcher::_SetIcons(BMidiEndpoint* endpoint) { BMessage msg; - msg.AddData( - "be:large_icon", B_LARGE_ICON_TYPE, largeIcon->Bits(), largeIcon->BitsLength()); + // TODO: handle Haiku vector icon type + + msg.AddData("be:large_icon", B_LARGE_ICON_TYPE, fLargeIcon->Bits(), + fLargeIcon->BitsLength()); - msg.AddData( - "be:mini_icon", B_MINI_ICON_TYPE, miniIcon->Bits(), miniIcon->BitsLength()); + msg.AddData("be:mini_icon", B_MINI_ICON_TYPE, fMiniIcon->Bits(), + fMiniIcon->BitsLength()); - endp->SetProperties(&msg); + endpoint->SetProperties(&msg); } - -//------------------------------------------------------------------------------ diff --git a/src/servers/midi/DeviceWatcher.h b/src/servers/midi/DeviceWatcher.h index 9ca4ebcc60..4d5f67d436 100644 --- a/src/servers/midi/DeviceWatcher.h +++ b/src/servers/midi/DeviceWatcher.h @@ -1,47 +1,39 @@ /* - * Copyright (c) 2003 Matthijs Hollemans - * Copyright (c) 2003 Jerome Leveque + * Copyright 2004-2009, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * Authors: + * Matthijs Hollemans + * Jerome Leveque + * Philippe Houdoin */ - #ifndef DEVICE_WATCHER_H #define DEVICE_WATCHER_H +#include + + class BBitmap; class BMidiEndpoint; -class DeviceWatcher -{ +class DeviceWatcher : public BLooper { public: - DeviceWatcher(); - ~DeviceWatcher(); + DeviceWatcher(); + ~DeviceWatcher(); + + void MessageReceived(BMessage* message); - void Start(); + status_t Start(); + status_t Stop(); private: - static int32 SpawnThread(void* data); - void ScanDevices(const char* path); - void SetIcons(BMidiEndpoint* endp); + void _ScanDevices(const char* path); + void _AddDevice(const char* path); + void _RemoveDevice(const char* path); + void _SetIcons(BMidiEndpoint* endp); - BBitmap* largeIcon; - BBitmap* miniIcon; + BBitmap* fLargeIcon; + BBitmap* fMiniIcon; }; #endif // DEVICE_WATCHER_H diff --git a/src/servers/midi/Jamfile b/src/servers/midi/Jamfile index f81095d5e2..c7e075b5e1 100644 --- a/src/servers/midi/Jamfile +++ b/src/servers/midi/Jamfile @@ -2,13 +2,19 @@ SubDir HAIKU_TOP src servers midi ; SetSubDirSupportedPlatformsBeOSCompatible ; -UsePrivateHeaders midi ; +UsePrivateHeaders midi storage ; Server midi_server : MidiServerApp.cpp DeviceWatcher.cpp PortDrivers.cpp - : be midi2 $(TARGET_LIBSUPC++) + + # storage + NodeMonitorHandler.cpp + + : be midi2 $(TARGET_LIBSTDC++) : midi_server.rdef ; +SEARCH on [ FGristFiles NodeMonitorHandler.cpp ] + += [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) kits storage ] ; diff --git a/src/servers/midi/MidiServerApp.cpp b/src/servers/midi/MidiServerApp.cpp index 0177510a63..28fa74ac7c 100644 --- a/src/servers/midi/MidiServerApp.cpp +++ b/src/servers/midi/MidiServerApp.cpp @@ -20,14 +20,17 @@ * DEALINGS IN THE SOFTWARE. */ -#include - #include "debug.h" #include "MidiServerApp.h" #include "PortDrivers.h" #include "ServerDefs.h" #include "protocol.h" +#include + +#include + +using std::nothrow; MidiServerApp::MidiServerApp() : BApplication(MIDI_SERVER_SIGNATURE) @@ -35,12 +38,17 @@ MidiServerApp::MidiServerApp() TRACE(("Running Haiku MIDI server")) nextId = 1; - devWatcher.Start(); + fDeviceWatcher = new(std::nothrow) DeviceWatcher(); + if (fDeviceWatcher != NULL) + fDeviceWatcher->Run(); } MidiServerApp::~MidiServerApp() { + if (fDeviceWatcher && fDeviceWatcher->Lock()) + fDeviceWatcher->Quit(); + for (int32 t = 0; t < CountApps(); ++t) { delete AppAt(t); } diff --git a/src/servers/midi/MidiServerApp.h b/src/servers/midi/MidiServerApp.h index bc431af803..2e2b5bfbbb 100644 --- a/src/servers/midi/MidiServerApp.h +++ b/src/servers/midi/MidiServerApp.h @@ -1,25 +1,10 @@ /* - * Copyright (c) 2002-2003 Matthijs Hollemans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * Copyright 2002-2009, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Matthijs Hollemans */ - #ifndef MIDI_SERVER_APP_H #define MIDI_SERVER_APP_H @@ -139,8 +124,8 @@ private: // The ID we will assign to the next new endpoint. int32 nextId; - // Creates endpoints for /dev/midi drivers. - DeviceWatcher devWatcher; + // Watch endpoints from /dev/midi drivers. + DeviceWatcher* fDeviceWatcher; #ifdef DEBUG void DumpApps();