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