xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioAddOn.cpp (revision cfc3fa87da824bdf593eb8b817a83b6376e77935)
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