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 (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 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 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 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 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 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