xref: /haiku/src/apps/cortex/NodeManager/AddOnHost.cpp (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
1 #include "AddOnHost.h"
2 #include "AddOnHostProtocol.h"
3 
4 #include <Application.h>
5 #include <Debug.h>
6 #include <Entry.h>
7 #include <MediaNode.h>
8 #include <MediaRoster.h>
9 #include <Messenger.h>
10 #include <Path.h>
11 #include <Roster.h>
12 
13 #include <OS.h>
14 
15 #include <cstdlib>
16 #include <cstring>
17 
18 __USE_CORTEX_NAMESPACE
19 
20 // -------------------------------------------------------- //
21 // constants
22 // -------------------------------------------------------- //
23 
24 BMessenger AddOnHost::s_messenger;
25 
26 // -------------------------------------------------------- //
27 // *** static interface
28 // -------------------------------------------------------- //
29 
30 /*static*/
31 status_t AddOnHost::FindInstance(
32 	BMessenger*								outMessenger) {
33 
34 	status_t err;
35 
36 	// no current app? launch one
37 	if(!s_messenger.IsValid()) {
38 		s_messenger = BMessenger(
39 			addon_host::g_appSignature,
40 			-1,
41 			&err);
42 
43 		if(err < B_OK)
44 			return err;
45 		if(!s_messenger.IsValid())
46 			return B_ERROR;
47 	}
48 
49 	*outMessenger = s_messenger;
50 	return B_OK;
51 }
52 
53 /*static*/
54 status_t AddOnHost::Kill(
55 	bigtime_t									timeout) {
56 
57 	if(!s_messenger.IsValid())
58 		return B_NOT_ALLOWED;
59 
60 	status_t err = kill_team(s_messenger.Team());
61 	return err;
62 }
63 
64 /*static*/
65 status_t AddOnHost::Launch(
66 	BMessenger*								outMessenger) {
67 
68 	if(s_messenger.IsValid())
69 		return B_NOT_ALLOWED;
70 
71 	status_t err;
72 
73 	// find it
74 	entry_ref appRef;
75 	err = be_roster->FindApp(addon_host::g_appSignature, &appRef);
76 	if(err < B_OK)
77 		return err;
78 
79 	// start it
80 	team_id team;
81 	const char* arg = "--addon-host";
82 	err = be_roster->Launch(
83 		&appRef,
84 		1,
85 		&arg,
86 		&team);
87 	if(err < B_OK)
88 		return err;
89 
90 	// fetch messenger to the new app and return it
91 	s_messenger = BMessenger(
92 		addon_host::g_appSignature,
93 		team,
94 		&err);
95 
96 	if(err < B_OK)
97 		return err;
98 	if(!s_messenger.IsValid())
99 		return B_ERROR;
100 
101 	if(outMessenger)
102 		*outMessenger = s_messenger;
103 
104 	return B_OK;
105 }
106 
107 /*static*/
108 status_t AddOnHost::InstantiateDormantNode(
109 	const dormant_node_info&	info,
110 	media_node*								outNode,
111 	bigtime_t									timeout) {
112 
113 	status_t err;
114 
115 	if(!s_messenger.IsValid()) {
116 		err = Launch(0);
117 
118 		if(err < B_OK) {
119 			// give up
120 			PRINT((
121 				"!!! AddOnHost::InstantiateDormantNode(): Launch() failed:\n"
122 				"    %s\n",
123 				strerror(err)));
124 			return err;
125 		}
126 	}
127 
128 	// do it
129 	ASSERT(s_messenger.IsValid());
130 	BMessage request(addon_host::M_INSTANTIATE);
131 	request.AddData("info", B_RAW_TYPE, &info, sizeof(dormant_node_info));
132 
133 	BMessage reply(B_NO_REPLY);
134 	err = s_messenger.SendMessage(
135 		&request,
136 		&reply,
137 		timeout,
138 		timeout);
139 
140 //	PRINT((
141 //		"### SendMessage() returned '%s'\n", strerror(err)));
142 
143 	if(err < B_OK) {
144 		PRINT((
145 			"!!! AddOnHost::InstantiateDormantNode(): SendMessage() failed:\n"
146 			"    %s\n",
147 			strerror(err)));
148 		return err;
149 	}
150 
151 	if(reply.what == B_NO_REPLY) {
152 		PRINT((
153 			"!!! AddOnHost::InstantiateDormantNode(): no reply.\n"));
154 		return B_ERROR;
155 	}
156 
157 	if(reply.what == addon_host::M_INSTANTIATE_COMPLETE) {
158 		media_node_id nodeID;
159 
160 		// fetch node ID
161 		err = reply.FindInt32("node_id", &nodeID);
162 		if(err < B_OK) {
163 			PRINT((
164 				"!!! AddOnHost::InstantiateDormantNode(): 'node_id' missing from reply.\n"));
165 			return B_ERROR;
166 		}
167 
168 		// fetch node
169 		err = BMediaRoster::Roster()->GetNodeFor(nodeID, outNode);
170 		if(err < B_OK) {
171 			PRINT((
172 				"!!! AddOnHost::InstantiateDormantNode(): node missing!\n"));
173 			return B_ERROR;
174 		}
175 
176 //		// now solely owned by the add-on host team
177 //		BMediaRoster::Roster()->ReleaseNode(*outNode);
178 
179 		return B_OK;
180 	}
181 
182 	// failed:
183 	return (reply.FindInt32("error", &err) == B_OK) ? err : B_ERROR;
184 }
185 
186 /*static*/
187 status_t AddOnHost::ReleaseInternalNode(
188 	const live_node_info&			info,
189 	bigtime_t									timeout) {
190 
191 	status_t err;
192 
193 	if(!s_messenger.IsValid()) {
194 		err = Launch(0);
195 
196 		if(err < B_OK) {
197 			// give up
198 			PRINT((
199 				"!!! AddOnHost::ReleaseInternalNode(): Launch() failed:\n"
200 				"    %s\n",
201 				strerror(err)));
202 			return err;
203 		}
204 	}
205 
206 	// do it
207 	ASSERT(s_messenger.IsValid());
208 	BMessage request(addon_host::M_RELEASE);
209 	request.AddData("info", B_RAW_TYPE, &info, sizeof(live_node_info));
210 
211 	BMessage reply(B_NO_REPLY);
212 	err = s_messenger.SendMessage(
213 		&request,
214 		&reply,
215 		timeout,
216 		timeout);
217 
218 
219 	if(err < B_OK) {
220 		PRINT((
221 			"!!! AddOnHost::ReleaseInternalNode(): SendMessage() failed:\n"
222 			"    %s\n",
223 			strerror(err)));
224 		return err;
225 	}
226 
227 	if(reply.what == B_NO_REPLY) {
228 		PRINT((
229 			"!!! AddOnHost::InstantiateDormantNode(): no reply.\n"));
230 		return B_ERROR;
231 	}
232 
233 	if(reply.what == addon_host::M_RELEASE_COMPLETE) {
234 		return B_OK;
235 	}
236 
237 	// failed:
238 	return (reply.FindInt32("error", &err) == B_OK) ? err : B_ERROR;
239 }
240 
241