1 /* 2 * Copyright (c) 2003 Matthijs Hollemans 3 * Copyright (c) 2003 Jerome Leveque 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #include <Application.h> 25 #include <Bitmap.h> 26 #include <Directory.h> 27 #include <Entry.h> 28 #include <File.h> 29 #include <Path.h> 30 #include <Resources.h> 31 #include <Roster.h> 32 33 #include "DeviceWatcher.h" 34 #include "PortDrivers.h" 35 #include "debug.h" 36 37 //------------------------------------------------------------------------------ 38 39 DeviceWatcher::DeviceWatcher() 40 { 41 largeIcon = new BBitmap(BRect(0, 0, 31, 31), B_CMAP8); 42 miniIcon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8); 43 44 app_info info; 45 be_app->GetAppInfo(&info); 46 BFile file(&info.ref, B_READ_ONLY); 47 48 BResources res; 49 if (res.SetTo(&file) == B_OK) 50 { 51 size_t size; 52 const void* bits; 53 54 bits = res.LoadResource(B_LARGE_ICON_TYPE, 10, &size); 55 largeIcon->SetBits(bits, size, 0, B_CMAP8); 56 57 bits = res.LoadResource(B_MINI_ICON_TYPE, 11, &size); 58 miniIcon->SetBits(bits, size, 0, B_CMAP8); 59 } 60 } 61 62 //------------------------------------------------------------------------------ 63 64 DeviceWatcher::~DeviceWatcher() 65 { 66 delete largeIcon; 67 delete miniIcon; 68 } 69 70 //------------------------------------------------------------------------------ 71 72 void DeviceWatcher::Start() 73 { 74 // We need to do this from a separate thread, otherwise we will deadlock. 75 // The reason is that we instantiate a BMidiRoster object, which sends a 76 // message to the midi_server to register itself, and blocks until it gets 77 // a response. But since we _are_ the midi_server we will never be able to 78 // send that response if our main thread is already blocking. 79 80 resume_thread(spawn_thread( 81 SpawnThread, "DeviceWatcher", B_NORMAL_PRIORITY, this)); 82 } 83 84 //------------------------------------------------------------------------------ 85 86 int32 DeviceWatcher::SpawnThread(void* data) 87 { 88 ((DeviceWatcher*) data)->ScanDevices("/dev/midi"); 89 return 0; 90 } 91 92 //------------------------------------------------------------------------------ 93 94 void DeviceWatcher::ScanDevices(const char* path) 95 { 96 BDirectory dir(path); 97 if (dir.InitCheck() == B_OK) 98 { 99 BEntry entry; 100 while (dir.GetNextEntry(&entry) == B_OK) 101 { 102 BPath name; 103 entry.GetPath(&name); 104 if (entry.IsDirectory()) 105 { 106 ScanDevices(name.Path()); 107 } 108 else 109 { 110 int fd = open(name.Path(), O_RDWR | O_EXCL); 111 if (fd >= 0) 112 { 113 BMidiEndpoint* endp; 114 115 endp = new MidiPortConsumer(fd, name.Path()); 116 SetIcons(endp); 117 endp->Register(); 118 119 endp = new MidiPortProducer(fd, name.Path()); 120 SetIcons(endp); 121 endp->Register(); 122 } 123 } 124 } 125 } 126 } 127 128 //------------------------------------------------------------------------------ 129 130 void DeviceWatcher::SetIcons(BMidiEndpoint* endp) 131 { 132 BMessage msg; 133 134 msg.AddData( 135 "be:large_icon", B_LARGE_ICON_TYPE, largeIcon->Bits(), largeIcon->BitsLength()); 136 137 msg.AddData( 138 "be:mini_icon", B_MINI_ICON_TYPE, miniIcon->Bits(), miniIcon->BitsLength()); 139 140 endp->SetProperties(&msg); 141 } 142 143 //------------------------------------------------------------------------------ 144