1 /* 2 * multiaudio replacement media addon for BeOS 3 * 4 * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr) 5 * 6 * All rights reserved. 7 * Redistribution and use in source and binary forms, with or without modification, 8 * are permitted provided that the following conditions are met: 9 * 10 * - Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 #include <MediaDefs.h> 29 #include <MediaAddOn.h> 30 #include <Errors.h> 31 #include <Node.h> 32 #include <Mime.h> 33 #include <StorageDefs.h> 34 #include <Path.h> 35 #include <Directory.h> 36 #include <Entry.h> 37 #include <FindDirectory.h> 38 39 #include "MultiAudioNode.h" 40 #include "MultiAudioAddOn.h" 41 #include "MultiAudioDevice.h" 42 43 #include <limits.h> 44 #include <stdio.h> 45 #include <string.h> 46 47 #include "debug.h" 48 49 #define MULTI_SAVE 50 51 // instantiation function 52 extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) { 53 CALLED(); 54 return new MultiAudioAddOn(image); 55 } 56 57 // -------------------------------------------------------- // 58 // ctor/dtor 59 // -------------------------------------------------------- // 60 61 MultiAudioAddOn::~MultiAudioAddOn() 62 { 63 CALLED(); 64 65 void *device = NULL; 66 for ( int32 i = 0; (device = fDevices.ItemAt(i)); i++ ) 67 delete device; 68 69 SaveSettings(); 70 } 71 72 MultiAudioAddOn::MultiAudioAddOn(image_id image) : 73 BMediaAddOn(image), 74 fDevices() 75 { 76 CALLED(); 77 fInitCheckStatus = B_NO_INIT; 78 79 if(RecursiveScan("/dev/audio/multi/")!=B_OK) 80 return; 81 82 LoadSettings(); 83 84 fInitCheckStatus = B_OK; 85 } 86 87 // -------------------------------------------------------- // 88 // BMediaAddOn impl 89 // -------------------------------------------------------- // 90 91 status_t MultiAudioAddOn::InitCheck( 92 const char ** out_failure_text) 93 { 94 CALLED(); 95 return B_OK; 96 } 97 98 int32 MultiAudioAddOn::CountFlavors() 99 { 100 CALLED(); 101 return fDevices.CountItems(); 102 } 103 104 status_t MultiAudioAddOn::GetFlavorAt( 105 int32 n, 106 const flavor_info ** out_info) 107 { 108 CALLED(); 109 if (out_info == 0) { 110 fprintf(stderr,"<- B_BAD_VALUE\n"); 111 return B_BAD_VALUE; // we refuse to crash because you were stupid 112 } 113 if (n < 0 || n > fDevices.CountItems() - 1) { 114 fprintf(stderr,"<- B_BAD_INDEX\n"); 115 return B_BAD_INDEX; 116 } 117 118 MultiAudioDevice *device = (MultiAudioDevice *) fDevices.ItemAt(n); 119 120 flavor_info * infos = new flavor_info[1]; 121 MultiAudioNode::GetFlavor(&infos[0], n); 122 infos[0].name = device->MD.friendly_name; 123 (*out_info) = infos; 124 return B_OK; 125 } 126 127 BMediaNode * MultiAudioAddOn::InstantiateNodeFor( 128 const flavor_info * info, 129 BMessage * config, 130 status_t * out_error) 131 { 132 CALLED(); 133 if (out_error == 0) { 134 fprintf(stderr,"<- NULL\n"); 135 return 0; // we refuse to crash because you were stupid 136 } 137 138 MultiAudioDevice *device = (MultiAudioDevice*)fDevices.ItemAt(info->internal_id); 139 if(device == NULL) { 140 *out_error = B_ERROR; 141 return NULL; 142 } 143 144 #ifdef MULTI_SAVE 145 if(fSettings.FindMessage(device->MD.friendly_name, config)==B_OK) { 146 fSettings.RemoveData(device->MD.friendly_name); 147 } 148 #endif 149 150 MultiAudioNode * node 151 = new MultiAudioNode(this, 152 device->MD.friendly_name, 153 device, 154 info->internal_id, 155 config); 156 if (node == 0) { 157 *out_error = B_NO_MEMORY; 158 fprintf(stderr,"<- B_NO_MEMORY\n"); 159 } else { 160 *out_error = node->InitCheck(); 161 } 162 return node; 163 } 164 165 status_t 166 MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message) 167 { 168 CALLED(); 169 #ifdef MULTI_SAVE 170 if (into_message == 0) { 171 into_message = new BMessage(); 172 MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node); 173 if (node == 0) { 174 fprintf(stderr,"<- B_BAD_TYPE\n"); 175 return B_BAD_TYPE; 176 } 177 if(node->GetConfigurationFor(into_message)==B_OK) { 178 fSettings.AddMessage(your_node->Name(), into_message); 179 } 180 return B_OK; 181 } 182 #endif 183 // currently never called by the media kit. Seems it is not implemented. 184 if (into_message == 0) { 185 fprintf(stderr,"<- B_BAD_VALUE\n"); 186 return B_BAD_VALUE; // we refuse to crash because you were stupid 187 } 188 MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node); 189 if (node == 0) { 190 fprintf(stderr,"<- B_BAD_TYPE\n"); 191 return B_BAD_TYPE; 192 } 193 return node->GetConfigurationFor(into_message); 194 } 195 196 197 bool MultiAudioAddOn::WantsAutoStart() 198 { 199 CALLED(); 200 return false; 201 } 202 203 status_t MultiAudioAddOn::AutoStart( 204 int in_count, 205 BMediaNode ** out_node, 206 int32 * out_internal_id, 207 bool * out_has_more) 208 { 209 CALLED(); 210 return B_OK; 211 } 212 213 status_t 214 MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry = NULL) 215 { 216 CALLED(); 217 218 BDirectory root; 219 if(rootEntry!=NULL) 220 root.SetTo(rootEntry); 221 else if(rootPath!=NULL) { 222 root.SetTo(rootPath); 223 } else { 224 PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n")); 225 return B_ERROR; 226 } 227 228 BEntry entry; 229 230 while(root.GetNextEntry(&entry) > B_ERROR) { 231 232 if(entry.IsDirectory()) { 233 RecursiveScan(rootPath, &entry); 234 } else { 235 BPath path; 236 entry.GetPath(&path); 237 MultiAudioDevice *device = new MultiAudioDevice(path.Path() + strlen(rootPath), path.Path()); 238 if(device && device->InitCheck() == B_OK) 239 fDevices.AddItem(device); 240 } 241 } 242 243 return B_OK; 244 } 245 246 247 void 248 MultiAudioAddOn::SaveSettings(void) 249 { 250 CALLED(); 251 BPath path; 252 if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 253 path.Append(SETTINGS_FILE); 254 BFile file(path.Path(),B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE); 255 if(file.InitCheck()==B_OK) 256 fSettings.Flatten(&file); 257 } 258 } 259 260 261 void 262 MultiAudioAddOn::LoadSettings(void) 263 { 264 CALLED(); 265 fSettings.MakeEmpty(); 266 267 BPath path; 268 if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 269 path.Append(SETTINGS_FILE); 270 BFile file(path.Path(),B_READ_ONLY); 271 if((file.InitCheck()==B_OK)&&(fSettings.Unflatten(&file)==B_OK)) 272 { 273 PRINT_OBJECT(fSettings); 274 } else { 275 PRINT(("Error unflattening settings file %s\n",path.Path())); 276 } 277 } 278 }