1 /* 2 * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr) 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <MediaDefs.h> 7 #include <MediaAddOn.h> 8 #include <Errors.h> 9 #include <Node.h> 10 #include <Mime.h> 11 #include <StorageDefs.h> 12 #include <Path.h> 13 #include <Directory.h> 14 #include <Entry.h> 15 #include <FindDirectory.h> 16 17 #include "MultiAudioNode.h" 18 #include "MultiAudioAddOn.h" 19 #include "MultiAudioDevice.h" 20 21 #include <limits.h> 22 #include <stdio.h> 23 #include <string.h> 24 25 #include "debug.h" 26 27 #define MULTI_SAVE 28 29 // instantiation function 30 extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) { 31 CALLED(); 32 return new MultiAudioAddOn(image); 33 } 34 35 // -------------------------------------------------------- // 36 // ctor/dtor 37 // -------------------------------------------------------- // 38 39 MultiAudioAddOn::~MultiAudioAddOn() 40 { 41 CALLED(); 42 43 void *device = NULL; 44 for (int32 i = 0; (device = fDevices.ItemAt(i)); i++) 45 delete (MultiAudioDevice *)device; 46 47 SaveSettings(); 48 } 49 50 MultiAudioAddOn::MultiAudioAddOn(image_id image) : 51 BMediaAddOn(image), 52 fDevices() 53 { 54 CALLED(); 55 fInitCheckStatus = B_NO_INIT; 56 57 if (RecursiveScan("/dev/audio/hmulti/") != B_OK) 58 return; 59 60 LoadSettings(); 61 62 fInitCheckStatus = B_OK; 63 } 64 65 // -------------------------------------------------------- // 66 // BMediaAddOn impl 67 // -------------------------------------------------------- // 68 69 status_t MultiAudioAddOn::InitCheck( 70 const char ** out_failure_text) 71 { 72 CALLED(); 73 return B_OK; 74 } 75 76 int32 MultiAudioAddOn::CountFlavors() 77 { 78 CALLED(); 79 return fDevices.CountItems(); 80 } 81 82 status_t MultiAudioAddOn::GetFlavorAt( 83 int32 n, 84 const flavor_info ** out_info) 85 { 86 CALLED(); 87 if (out_info == 0) { 88 fprintf(stderr, "<- B_BAD_VALUE\n"); 89 return B_BAD_VALUE; // we refuse to crash because you were stupid 90 } 91 if (n < 0 || n > fDevices.CountItems() - 1) { 92 fprintf(stderr, "<- B_BAD_INDEX\n"); 93 return B_BAD_INDEX; 94 } 95 96 MultiAudioDevice *device = (MultiAudioDevice *) fDevices.ItemAt(n); 97 98 flavor_info * infos = new flavor_info[1]; 99 MultiAudioNode::GetFlavor(&infos[0], n); 100 infos[0].name = device->MD.friendly_name; 101 (*out_info) = infos; 102 return B_OK; 103 } 104 105 BMediaNode * MultiAudioAddOn::InstantiateNodeFor( 106 const flavor_info * info, 107 BMessage * config, 108 status_t * out_error) 109 { 110 CALLED(); 111 if (out_error == 0) { 112 fprintf(stderr, "<- NULL\n"); 113 return 0; // we refuse to crash because you were stupid 114 } 115 116 MultiAudioDevice *device = (MultiAudioDevice*)fDevices.ItemAt(info->internal_id); 117 if (device == NULL) { 118 *out_error = B_ERROR; 119 return NULL; 120 } 121 122 #ifdef MULTI_SAVE 123 if (fSettings.FindMessage(device->MD.friendly_name, config) == B_OK) { 124 fSettings.RemoveData(device->MD.friendly_name); 125 } 126 #endif 127 128 MultiAudioNode * node = 129 new MultiAudioNode(this, 130 device->MD.friendly_name, 131 device, 132 info->internal_id, 133 config); 134 if (node == 0) { 135 *out_error = B_NO_MEMORY; 136 fprintf(stderr, "<- B_NO_MEMORY\n"); 137 } else { 138 *out_error = node->InitCheck(); 139 } 140 return node; 141 } 142 143 status_t 144 MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message) 145 { 146 CALLED(); 147 #ifdef MULTI_SAVE 148 if (into_message == 0) { 149 into_message = new BMessage(); 150 MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node); 151 if (node == 0) { 152 fprintf(stderr, "<- B_BAD_TYPE\n"); 153 return B_BAD_TYPE; 154 } 155 if (node->GetConfigurationFor(into_message) == B_OK) { 156 fSettings.AddMessage(your_node->Name(), into_message); 157 } 158 return B_OK; 159 } 160 #endif 161 // currently never called by the media kit. Seems it is not implemented. 162 if (into_message == 0) { 163 fprintf(stderr, "<- B_BAD_VALUE\n"); 164 return B_BAD_VALUE; // we refuse to crash because you were stupid 165 } 166 MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node); 167 if (node == 0) { 168 fprintf(stderr, "<- B_BAD_TYPE\n"); 169 return B_BAD_TYPE; 170 } 171 return node->GetConfigurationFor(into_message); 172 } 173 174 175 bool MultiAudioAddOn::WantsAutoStart() 176 { 177 CALLED(); 178 return false; 179 } 180 181 status_t MultiAudioAddOn::AutoStart( 182 int in_count, 183 BMediaNode ** out_node, 184 int32 * out_internal_id, 185 bool * out_has_more) 186 { 187 CALLED(); 188 return B_OK; 189 } 190 191 status_t 192 MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry) 193 { 194 CALLED(); 195 196 BDirectory root; 197 if (rootEntry != NULL) 198 root.SetTo(rootEntry); 199 else if (rootPath != NULL) { 200 root.SetTo(rootPath); 201 } else { 202 PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n")); 203 return B_ERROR; 204 } 205 206 BEntry entry; 207 208 while (root.GetNextEntry(&entry) > B_ERROR) { 209 210 if (entry.IsDirectory()) { 211 RecursiveScan(rootPath, &entry); 212 } else { 213 BPath path; 214 entry.GetPath(&path); 215 MultiAudioDevice *device = new MultiAudioDevice(path.Path() + strlen(rootPath), path.Path()); 216 if (device) { 217 if (device->InitCheck() == B_OK) 218 fDevices.AddItem(device); 219 else 220 delete device; 221 } 222 } 223 } 224 225 return B_OK; 226 } 227 228 229 void 230 MultiAudioAddOn::SaveSettings(void) 231 { 232 CALLED(); 233 BPath path; 234 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 235 path.Append(SETTINGS_FILE); 236 BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 237 if (file.InitCheck() == B_OK) 238 fSettings.Flatten(&file); 239 } 240 } 241 242 243 void 244 MultiAudioAddOn::LoadSettings(void) 245 { 246 CALLED(); 247 fSettings.MakeEmpty(); 248 249 BPath path; 250 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 251 path.Append(SETTINGS_FILE); 252 BFile file(path.Path(), B_READ_ONLY); 253 if ((file.InitCheck() == B_OK) && (fSettings.Unflatten(&file) == B_OK)) 254 { 255 PRINT_OBJECT(fSettings); 256 } else { 257 PRINT(("Error unflattening settings file %s\n", path.Path())); 258 } 259 } 260 } 261