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
58bdc29e6aSFrançois Revolextern "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
67bdc29e6aSFrançois RevolESDSinkAddOn::~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
78bdc29e6aSFrançois RevolESDSinkAddOn::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
97bdc29e6aSFrançois Revolstatus_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
104bdc29e6aSFrançois Revolint32 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
111bdc29e6aSFrançois Revolstatus_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
122520d5f6eSFranç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
131bdc29e6aSFrançois RevolBMediaNode * 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
138520d5f6eSFrançois Revol	BString name = "ESounD Sink";
139bdc29e6aSFrançois Revol#ifdef MULTI_SAVE
140520d5f6eSFrançois Revol	ESDEndpoint *device = (ESDEndpoint *) fDevices.ItemAt(info->internal_id);
141520d5f6eSFrançois Revol	if (device)
142520d5f6eSFrançois Revol		device->GetFriendlyName(name);
143520d5f6eSFrançois Revol	if(fSettings.FindMessage(name.String(), config)==B_OK) {
144520d5f6eSFranç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,
151520d5f6eSFranç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 Revolstatus_t
163bdc29e6aSFrançois RevolESDSinkAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
164bdc29e6aSFrançois Revol{
165bdc29e6aSFrançois Revol	CALLED();
166bdc29e6aSFrançois Revol#ifdef MULTI_SAVE
167520d5f6eSFrançois Revol		if (!into_message)
168520d5f6eSFranç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.
180520d5f6eSFranç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);
187520d5f6eSFrançois Revol#endif
188520d5f6eSFrançois Revol	return B_ERROR;
189bdc29e6aSFrançois Revol}
190bdc29e6aSFrançois Revol
191bdc29e6aSFrançois Revol#if 0
192bdc29e6aSFrançois Revolbool ESDSinkAddOn::WantsAutoStart()
193bdc29e6aSFrançois Revol{
194bdc29e6aSFrançois Revol	CALLED();
195bdc29e6aSFrançois Revol	return true;//false;
196bdc29e6aSFrançois Revol}
197bdc29e6aSFrançois Revol
198bdc29e6aSFrançois Revolstatus_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 Revolstatus_t
226bdc29e6aSFrançois RevolESDSinkAddOn::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 Revolvoid
265bdc29e6aSFrançois RevolESDSinkAddOn::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 Revolvoid
279bdc29e6aSFrançois RevolESDSinkAddOn::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