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 88 MultiAudioDevice* device = (MultiAudioDevice*)fDevices.ItemAt(index); 89 if (device == NULL) 90 return B_BAD_INDEX; 91 92 flavor_info* info = new (std::nothrow) flavor_info; 93 if (info == NULL) 94 return B_NO_MEMORY; 95 96 MultiAudioNode::GetFlavor(info, index); 97 info->name = (char*)device->Description().friendly_name; 98 99 *_info = info; 100 return B_OK; 101 } 102 103 104 BMediaNode* 105 MultiAudioAddOn::InstantiateNodeFor(const flavor_info* info, BMessage* config, 106 status_t* _error) 107 { 108 CALLED(); 109 110 MultiAudioDevice* device = (MultiAudioDevice*)fDevices.ItemAt( 111 info->internal_id); 112 if (device == NULL) { 113 *_error = B_ERROR; 114 return NULL; 115 } 116 117 #ifdef MULTI_SAVE 118 if (fSettings.FindMessage(device->Description().friendly_name, config) 119 == B_OK) { 120 fSettings.RemoveData(device->Description().friendly_name); 121 } 122 #endif 123 124 MultiAudioNode* node = new (std::nothrow) MultiAudioNode(this, 125 device->Description().friendly_name, device, info->internal_id, config); 126 if (node == NULL) 127 *_error = B_NO_MEMORY; 128 else 129 *_error = node->InitCheck(); 130 131 return node; 132 } 133 134 135 status_t 136 MultiAudioAddOn::GetConfigurationFor(BMediaNode* _node, BMessage* message) 137 { 138 CALLED(); 139 MultiAudioNode* node = dynamic_cast<MultiAudioNode*>(_node); 140 if (node == NULL) 141 return B_BAD_TYPE; 142 143 #ifdef MULTI_SAVE 144 if (message == NULL) { 145 BMessage settings; 146 if (node->GetConfigurationFor(&settings) == B_OK) { 147 fSettings.AddMessage(node->Name(), &settings); 148 } 149 return B_OK; 150 } 151 #endif 152 153 // currently never called by the media kit. Seems it is not implemented. 154 155 return node->GetConfigurationFor(message); 156 } 157 158 159 bool 160 MultiAudioAddOn::WantsAutoStart() 161 { 162 CALLED(); 163 return false; 164 } 165 166 167 status_t 168 MultiAudioAddOn::AutoStart(int count, BMediaNode** _node, int32* _internalID, 169 bool* _hasMore) 170 { 171 CALLED(); 172 return B_OK; 173 } 174 175 176 status_t 177 MultiAudioAddOn::_RecursiveScan(const char* rootPath, BEntry* rootEntry, uint32 depth) 178 { 179 CALLED(); 180 if (depth > 16) 181 return B_ERROR; 182 183 BDirectory root; 184 if (rootEntry != NULL) 185 root.SetTo(rootEntry); 186 else if (rootPath != NULL) 187 root.SetTo(rootPath); 188 else { 189 PRINT(("Error in MultiAudioAddOn::RecursiveScan() null params\n")); 190 return B_ERROR; 191 } 192 193 BEntry entry; 194 while (root.GetNextEntry(&entry) == B_OK) { 195 if (entry.IsDirectory()) { 196 _RecursiveScan(rootPath, &entry, depth + 1); 197 } else { 198 BPath path; 199 entry.GetPath(&path); 200 MultiAudioDevice *device = 201 new(std::nothrow) MultiAudioDevice(path.Path() 202 + strlen(rootPath), path.Path()); 203 if (device) { 204 if (device->InitCheck() == B_OK) 205 fDevices.AddItem(device); 206 else 207 delete device; 208 } 209 } 210 } 211 212 return B_OK; 213 } 214 215 216 void 217 MultiAudioAddOn::_SaveSettings() 218 { 219 CALLED(); 220 BPath path; 221 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 222 return; 223 224 path.Append(kSettingsName); 225 226 BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 227 if (file.InitCheck() == B_OK) 228 fSettings.Flatten(&file); 229 } 230 231 232 void 233 MultiAudioAddOn::_LoadSettings() 234 { 235 CALLED(); 236 fSettings.MakeEmpty(); 237 238 BPath path; 239 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 240 return; 241 242 path.Append(kSettingsName); 243 244 BFile file(path.Path(), B_READ_ONLY); 245 if (file.InitCheck() == B_OK && fSettings.Unflatten(&file) == B_OK) { 246 PRINT_OBJECT(fSettings); 247 } else { 248 PRINT(("Error unflattening settings file %s\n", path.Path())); 249 } 250 } 251