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
make_media_addon(image_id image)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
~ESDSinkAddOn()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
ESDSinkAddOn(image_id image)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
InitCheck(const char ** out_failure_text)97 status_t ESDSinkAddOn::InitCheck(
98 const char ** out_failure_text)
99 {
100 CALLED();
101 return B_OK;
102 }
103
CountFlavors()104 int32 ESDSinkAddOn::CountFlavors()
105 {
106 CALLED();
107 //return fDevices.CountItems();
108 return 1;
109 }
110
GetFlavorAt(int32 n,const flavor_info ** out_info)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
InstantiateNodeFor(const flavor_info * info,BMessage * config,status_t * out_error)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
GetConfigurationFor(BMediaNode * your_node,BMessage * into_message)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
SetupDefaultSinks()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
SaveSettings(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
LoadSettings(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