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