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