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