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 58extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) { 59 CALLED(); 60 return new ESDSinkAddOn(image); 61} 62 63// -------------------------------------------------------- // 64// ctor/dtor 65// -------------------------------------------------------- // 66 67ESDSinkAddOn::~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 78ESDSinkAddOn::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 97status_t ESDSinkAddOn::InitCheck( 98 const char ** out_failure_text) 99{ 100 CALLED(); 101 return B_OK; 102} 103 104int32 ESDSinkAddOn::CountFlavors() 105{ 106 CALLED(); 107 //return fDevices.CountItems(); 108 return 1; 109} 110 111status_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 131BMediaNode * 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 162status_t 163ESDSinkAddOn::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 192bool ESDSinkAddOn::WantsAutoStart() 193{ 194 CALLED(); 195 return true;//false; 196} 197 198status_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 225status_t 226ESDSinkAddOn::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 264void 265ESDSinkAddOn::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 278void 279ESDSinkAddOn::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