xref: /haiku/src/add-ons/media/media-add-ons/esound_sink/ESDSinkAddOn.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * ESounD media addon for BeOS
3  *
4  * Copyright (c) 2006 François Revol (revol@free.fr)
5  *
6  * Based on Multi Audio addon for Haiku,
7  * Copyright (c) 2002, 2003 Jerome Duval (jerome.duval@free.fr)
8  *
9  * All rights reserved.
10  * Redistribution and use in source and binary forms, with or without modification,
11  * are permitted provided that the following conditions are met:
12  *
13  * - Redistributions of source code must retain the above copyright notice,
14  *   this list of conditions and the following disclaimer.
15  * - Redistributions in binary form must reproduce the above copyright notice,
16  *   this list of conditions and the following disclaimer in the documentation
17  *   and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 #define _ZETA_TS_FIND_DIR_ 1
32 #include <MediaDefs.h>
33 #include <MediaAddOn.h>
34 #include <Errors.h>
35 #include <Node.h>
36 #include <Mime.h>
37 #include <StorageDefs.h>
38 #include <Path.h>
39 #include <Directory.h>
40 #include <Entry.h>
41 #include <FindDirectory.h>
42 
43 #include "ESDSinkNode.h"
44 #include "ESDSinkAddOn.h"
45 #include "ESDEndpoint.h"
46 
47 #include <limits.h>
48 #include <stdio.h>
49 #include <string.h>
50 //#undef DEBUG
51 //#define DEBUG 4
52 #include "debug.h"
53 #include <Debug.h>
54 
55 //#define MULTI_SAVE
56 
57 // instantiation function
58 extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) {
59 	CALLED();
60 	return new ESDSinkAddOn(image);
61 }
62 
63 // -------------------------------------------------------- //
64 // ctor/dtor
65 // -------------------------------------------------------- //
66 
67 ESDSinkAddOn::~ESDSinkAddOn()
68 {
69 	CALLED();
70 
71 	void *device = NULL;
72 	for ( int32 i = 0; (device = fDevices.ItemAt(i)); i++ )
73 		delete (ESDEndpoint *)device;
74 
75 	SaveSettings();
76 }
77 
78 ESDSinkAddOn::ESDSinkAddOn(image_id image) :
79 	BMediaAddOn(image),
80 	fDevices()
81 {
82 	CALLED();
83 	fInitCheckStatus = B_NO_INIT;
84 
85 	LoadSettings();
86 
87 	if(SetupDefaultSinks()!=B_OK)
88 		return;
89 
90 	fInitCheckStatus = B_OK;
91 }
92 
93 // -------------------------------------------------------- //
94 // BMediaAddOn impl
95 // -------------------------------------------------------- //
96 
97 status_t ESDSinkAddOn::InitCheck(
98 	const char ** out_failure_text)
99 {
100 	CALLED();
101 	return B_OK;
102 }
103 
104 int32 ESDSinkAddOn::CountFlavors()
105 {
106 	CALLED();
107 	//return fDevices.CountItems();
108 	return 1;
109 }
110 
111 status_t ESDSinkAddOn::GetFlavorAt(
112 	int32 n,
113 	const flavor_info ** out_info)
114 {
115 	CALLED();
116 	//if (n < 0 || n > fDevices.CountItems() - 1) {
117 	if (n < 0 || n > 1) {
118 		fprintf(stderr,"<- B_BAD_INDEX\n");
119 		return B_BAD_INDEX;
120 	}
121 
122 	//ESDEndpoint *device = (ESDEndpoint *) fDevices.ItemAt(n);
123 
124 	flavor_info * infos = new flavor_info[1];
125 	ESDSinkNode::GetFlavor(&infos[0], n);
126 //	infos[0].name = device->MD.friendly_name;
127 	(*out_info) = infos;
128 	return B_OK;
129 }
130 
131 BMediaNode * ESDSinkAddOn::InstantiateNodeFor(
132 				const flavor_info * info,
133 				BMessage * config,
134 				status_t * out_error)
135 {
136 	CALLED();
137 
138 	BString name = "ESounD Sink";
139 #ifdef MULTI_SAVE
140 	ESDEndpoint *device = (ESDEndpoint *) fDevices.ItemAt(info->internal_id);
141 	if (device)
142 		device->GetFriendlyName(name);
143 	if(fSettings.FindMessage(name.String(), config)==B_OK) {
144 		fSettings.RemoveData(name.String());
145 	}
146 #endif
147 
148 
149 	ESDSinkNode * node
150 		= new ESDSinkNode(this,
151 						  (char *)name.String(),
152 						  config);
153 	if (node == 0) {
154 		*out_error = B_NO_MEMORY;
155 		fprintf(stderr,"<- B_NO_MEMORY\n");
156 	} else {
157 		*out_error = node->InitCheck();
158 	}
159 	return node;
160 }
161 
162 status_t
163 ESDSinkAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
164 {
165 	CALLED();
166 #ifdef MULTI_SAVE
167 		if (!into_message)
168 			into_message = new BMessage();
169 		ESDSinkNode * node = dynamic_cast<ESDSinkNode*>(your_node);
170 		if (node == 0) {
171 			fprintf(stderr,"<- B_BAD_TYPE\n");
172 			return B_BAD_TYPE;
173 		}
174 		if(node->GetConfigurationFor(into_message)==B_OK) {
175 			fSettings.AddMessage(your_node->Name(), into_message);
176 		}
177 		return B_OK;
178 #endif
179 	// currently never called by the media kit. Seems it is not implemented.
180 #if 0
181 	ESDSinkNode * node = dynamic_cast<ESDSinkNode*>(your_node);
182 	if (node == 0) {
183 		fprintf(stderr,"<- B_BAD_TYPE\n");
184 		return B_BAD_TYPE;
185 	}
186 	return node->GetConfigurationFor(into_message);
187 #endif
188 	return B_ERROR;
189 }
190 
191 #if 0
192 bool ESDSinkAddOn::WantsAutoStart()
193 {
194 	CALLED();
195 	return true;//false;
196 }
197 
198 status_t ESDSinkAddOn::AutoStart(
199 				int in_count,
200 				BMediaNode ** out_node,
201 				int32 * out_internal_id,
202 				bool * out_has_more)
203 {
204 	CALLED();
205 	const flavor_info *fi;
206 	status_t err;
207 
208 	// XXX: LEAK!
209 	PRINT(("AutoStart: in_count=%d\n", in_count));
210 //	if (in_count < 1)
211 //		return EINVAL;
212 	*out_internal_id = 0;
213 	*out_has_more = false;
214 	err = GetFlavorAt(0, (const flavor_info **)&fi);
215 	if (err < 0)
216 		return err;
217 	*out_node = InstantiateNodeFor((const flavor_info *)fi, NULL, &err);
218 	delete fi;
219 	if (err < 0)
220 		return err;
221 	return B_OK+1;
222 }
223 #endif
224 
225 status_t
226 ESDSinkAddOn::SetupDefaultSinks()
227 {
228 	CALLED();
229 #if 0
230 	BDirectory root;
231 	if(rootEntry!=NULL)
232 		root.SetTo(rootEntry);
233 	else if(rootPath!=NULL) {
234 		root.SetTo(rootPath);
235 	} else {
236 		PRINT(("Error in ESDSinkAddOn::RecursiveScan null params\n"));
237 		return B_ERROR;
238 	}
239 
240 	BEntry entry;
241 
242 	while(root.GetNextEntry(&entry) > B_ERROR) {
243 
244 		if(entry.IsDirectory()) {
245 			RecursiveScan(rootPath, &entry);
246 		} else {
247 			BPath path;
248 			entry.GetPath(&path);
249 			ESDEndpoint *device = new ESDEndpoint(path.Path() + strlen(rootPath), path.Path());
250 			if (device) {
251 				if (device->InitCheck() == B_OK)
252 					fDevices.AddItem(device);
253 				else
254 					delete device;
255 			}
256 		}
257 	}
258 
259 #endif
260 	return B_OK;
261 }
262 
263 
264 void
265 ESDSinkAddOn::SaveSettings(void)
266 {
267 	CALLED();
268 	BPath path;
269 	if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
270 		path.Append(SETTINGS_FILE);
271 		BFile file(path.Path(),B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE);
272 		if(file.InitCheck()==B_OK)
273 			fSettings.Flatten(&file);
274 	}
275 }
276 
277 
278 void
279 ESDSinkAddOn::LoadSettings(void)
280 {
281 	CALLED();
282 	fSettings.MakeEmpty();
283 
284 	BPath path;
285 	if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
286 		path.Append(SETTINGS_FILE);
287 		BFile file(path.Path(),B_READ_ONLY);
288 		if((file.InitCheck()==B_OK)&&(fSettings.Unflatten(&file)==B_OK))
289 		{
290 			//fSettings.PrintToStream();
291 		} else {
292 			PRINT(("Error unflattening settings file %s\n",path.Path()));
293 		}
294 	}
295 }
296