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