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 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 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 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 97 status_t ESDSinkAddOn::InitCheck( 98 const char ** out_failure_text) 99 { 100 CALLED(); 101 return B_OK; 102 } 103 104 int32 ESDSinkAddOn::CountFlavors() 105 { 106 CALLED(); 107 //return fDevices.CountItems(); 108 return 1; 109 } 110 111 status_t ESDSinkAddOn::GetFlavorAt( 112 int32 n, 113 const flavor_info ** out_info) 114 { 115 CALLED(); 116 if (out_info == 0) { 117 fprintf(stderr,"<- B_BAD_VALUE\n"); 118 return B_BAD_VALUE; // we refuse to crash because you were stupid 119 } 120 //if (n < 0 || n > fDevices.CountItems() - 1) { 121 if (n < 0 || n > 1) { 122 fprintf(stderr,"<- B_BAD_INDEX\n"); 123 return B_BAD_INDEX; 124 } 125 126 ESDEndpoint *device = (ESDEndpoint *) fDevices.ItemAt(n); 127 128 flavor_info * infos = new flavor_info[1]; 129 ESDSinkNode::GetFlavor(&infos[0], n); 130 // infos[0].name = device->MD.friendly_name; 131 infos[0].name = "ESounD Out"; 132 (*out_info) = infos; 133 return B_OK; 134 } 135 136 BMediaNode * ESDSinkAddOn::InstantiateNodeFor( 137 const flavor_info * info, 138 BMessage * config, 139 status_t * out_error) 140 { 141 CALLED(); 142 if (out_error == 0) { 143 fprintf(stderr,"<- NULL\n"); 144 return 0; // we refuse to crash because you were stupid 145 } 146 147 BMessage defaults; 148 if (!config) 149 config = &defaults; 150 151 #ifdef MULTI_SAVE 152 if(fSettings.FindMessage(device->MD.friendly_name, config)==B_OK) { 153 fSettings.RemoveData(device->MD.friendly_name); 154 } 155 #endif 156 157 158 ESDSinkNode * node 159 = new ESDSinkNode(this, 160 "ESounD Sink", 161 config); 162 if (node == 0) { 163 *out_error = B_NO_MEMORY; 164 fprintf(stderr,"<- B_NO_MEMORY\n"); 165 } else { 166 *out_error = node->InitCheck(); 167 } 168 return node; 169 } 170 171 status_t 172 ESDSinkAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message) 173 { 174 CALLED(); 175 #ifdef MULTI_SAVE 176 if (into_message == 0) { 177 into_message = new BMessage(); 178 ESDSinkNode * node = dynamic_cast<ESDSinkNode*>(your_node); 179 if (node == 0) { 180 fprintf(stderr,"<- B_BAD_TYPE\n"); 181 return B_BAD_TYPE; 182 } 183 if(node->GetConfigurationFor(into_message)==B_OK) { 184 fSettings.AddMessage(your_node->Name(), into_message); 185 } 186 return B_OK; 187 } 188 #endif 189 // currently never called by the media kit. Seems it is not implemented. 190 if (into_message == 0) { 191 fprintf(stderr,"<- B_BAD_VALUE\n"); 192 return B_BAD_VALUE; // we refuse to crash because you were stupid 193 } 194 ESDSinkNode * node = dynamic_cast<ESDSinkNode*>(your_node); 195 if (node == 0) { 196 fprintf(stderr,"<- B_BAD_TYPE\n"); 197 return B_BAD_TYPE; 198 } 199 return node->GetConfigurationFor(into_message); 200 } 201 202 #if 0 203 bool ESDSinkAddOn::WantsAutoStart() 204 { 205 CALLED(); 206 return true;//false; 207 } 208 209 status_t ESDSinkAddOn::AutoStart( 210 int in_count, 211 BMediaNode ** out_node, 212 int32 * out_internal_id, 213 bool * out_has_more) 214 { 215 CALLED(); 216 const flavor_info *fi; 217 status_t err; 218 219 // XXX: LEAK! 220 PRINT(("AutoStart: in_count=%d\n", in_count)); 221 // if (in_count < 1) 222 // return EINVAL; 223 *out_internal_id = 0; 224 *out_has_more = false; 225 err = GetFlavorAt(0, (const flavor_info **)&fi); 226 if (err < 0) 227 return err; 228 *out_node = InstantiateNodeFor((const flavor_info *)fi, NULL, &err); 229 delete fi; 230 if (err < 0) 231 return err; 232 return B_OK+1; 233 } 234 #endif 235 236 status_t 237 ESDSinkAddOn::SetupDefaultSinks() 238 { 239 CALLED(); 240 #if 0 241 BDirectory root; 242 if(rootEntry!=NULL) 243 root.SetTo(rootEntry); 244 else if(rootPath!=NULL) { 245 root.SetTo(rootPath); 246 } else { 247 PRINT(("Error in ESDSinkAddOn::RecursiveScan null params\n")); 248 return B_ERROR; 249 } 250 251 BEntry entry; 252 253 while(root.GetNextEntry(&entry) > B_ERROR) { 254 255 if(entry.IsDirectory()) { 256 RecursiveScan(rootPath, &entry); 257 } else { 258 BPath path; 259 entry.GetPath(&path); 260 ESDEndpoint *device = new ESDEndpoint(path.Path() + strlen(rootPath), path.Path()); 261 if (device) { 262 if (device->InitCheck() == B_OK) 263 fDevices.AddItem(device); 264 else 265 delete device; 266 } 267 } 268 } 269 270 #endif 271 return B_OK; 272 } 273 274 275 void 276 ESDSinkAddOn::SaveSettings(void) 277 { 278 CALLED(); 279 BPath path; 280 if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 281 path.Append(SETTINGS_FILE); 282 BFile file(path.Path(),B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE); 283 if(file.InitCheck()==B_OK) 284 fSettings.Flatten(&file); 285 } 286 } 287 288 289 void 290 ESDSinkAddOn::LoadSettings(void) 291 { 292 CALLED(); 293 fSettings.MakeEmpty(); 294 295 BPath path; 296 if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 297 path.Append(SETTINGS_FILE); 298 BFile file(path.Path(),B_READ_ONLY); 299 if((file.InitCheck()==B_OK)&&(fSettings.Unflatten(&file)==B_OK)) 300 { 301 //fSettings.PrintToStream(); 302 } else { 303 PRINT(("Error unflattening settings file %s\n",path.Path())); 304 } 305 } 306 } 307