xref: /haiku/src/servers/midi/DeviceWatcher.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
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