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 26const char* kSettingsName = "Media/multi_audio_settings"; 27 28 29//! instantiation function 30extern "C" BMediaAddOn* 31make_media_addon(image_id image) 32{ 33 CALLED(); 34 return new MultiAudioAddOn(image); 35} 36 37 38// #pragma mark - 39 40 41MultiAudioAddOn::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 55MultiAudioAddOn::~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 67status_t 68MultiAudioAddOn::InitCheck(const char** _failureText) 69{ 70 CALLED(); 71 return fInitStatus; 72} 73 74 75int32 76MultiAudioAddOn::CountFlavors() 77{ 78 CALLED(); 79 return fDevices.CountItems(); 80} 81 82 83status_t 84MultiAudioAddOn::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 = device->Description().friendly_name; 98 99 *_info = info; 100 return B_OK; 101} 102 103 104BMediaNode* 105MultiAudioAddOn::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 135status_t 136MultiAudioAddOn::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 159bool 160MultiAudioAddOn::WantsAutoStart() 161{ 162 CALLED(); 163 return false; 164} 165 166 167status_t 168MultiAudioAddOn::AutoStart(int count, BMediaNode** _node, int32* _internalID, 169 bool* _hasMore) 170{ 171 CALLED(); 172 return B_OK; 173} 174 175 176status_t 177MultiAudioAddOn::_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 216void 217MultiAudioAddOn::_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 232void 233MultiAudioAddOn::_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