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