xref: /haiku/src/add-ons/media/media-add-ons/multi_audio/MultiAudioAddOn.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * multiaudio replacement media addon for BeOS
3  *
4  * Copyright (c) 2002, Jerome Duval (jerome.duval@free.fr)
5  *
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  *   this list of conditions and the following disclaimer in the documentation
14  *   and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 #include <MediaDefs.h>
29 #include <MediaAddOn.h>
30 #include <Errors.h>
31 #include <Node.h>
32 #include <Mime.h>
33 #include <StorageDefs.h>
34 #include <Path.h>
35 #include <Directory.h>
36 #include <Entry.h>
37 #include <FindDirectory.h>
38 
39 #include "MultiAudioNode.h"
40 #include "MultiAudioAddOn.h"
41 #include "MultiAudioDevice.h"
42 
43 #include <limits.h>
44 #include <stdio.h>
45 #include <string.h>
46 
47 #include "debug.h"
48 
49 #define MULTI_SAVE
50 
51 // instantiation function
52 extern "C" _EXPORT BMediaAddOn * make_media_addon(image_id image) {
53 	CALLED();
54 	return new MultiAudioAddOn(image);
55 }
56 
57 // -------------------------------------------------------- //
58 // ctor/dtor
59 // -------------------------------------------------------- //
60 
61 MultiAudioAddOn::~MultiAudioAddOn()
62 {
63 	CALLED();
64 
65 	void *device = NULL;
66 	for ( int32 i = 0; (device = fDevices.ItemAt(i)); i++ )
67 		delete (MultiAudioDevice *)device;
68 
69 	SaveSettings();
70 }
71 
72 MultiAudioAddOn::MultiAudioAddOn(image_id image) :
73 	BMediaAddOn(image),
74 	fDevices()
75 {
76 	CALLED();
77 	fInitCheckStatus = B_NO_INIT;
78 
79 	if(RecursiveScan("/dev/audio/hmulti/")!=B_OK)
80 		return;
81 
82 	LoadSettings();
83 
84 	fInitCheckStatus = B_OK;
85 }
86 
87 // -------------------------------------------------------- //
88 // BMediaAddOn impl
89 // -------------------------------------------------------- //
90 
91 status_t MultiAudioAddOn::InitCheck(
92 	const char ** out_failure_text)
93 {
94 	CALLED();
95 	return B_OK;
96 }
97 
98 int32 MultiAudioAddOn::CountFlavors()
99 {
100 	CALLED();
101 	return fDevices.CountItems();
102 }
103 
104 status_t MultiAudioAddOn::GetFlavorAt(
105 	int32 n,
106 	const flavor_info ** out_info)
107 {
108 	CALLED();
109 	if (out_info == 0) {
110 		fprintf(stderr,"<- B_BAD_VALUE\n");
111 		return B_BAD_VALUE; // we refuse to crash because you were stupid
112 	}
113 	if (n < 0 || n > fDevices.CountItems() - 1) {
114 		fprintf(stderr,"<- B_BAD_INDEX\n");
115 		return B_BAD_INDEX;
116 	}
117 
118 	MultiAudioDevice *device = (MultiAudioDevice *) fDevices.ItemAt(n);
119 
120 	flavor_info * infos = new flavor_info[1];
121 	MultiAudioNode::GetFlavor(&infos[0], n);
122 	infos[0].name = device->MD.friendly_name;
123 	(*out_info) = infos;
124 	return B_OK;
125 }
126 
127 BMediaNode * MultiAudioAddOn::InstantiateNodeFor(
128 				const flavor_info * info,
129 				BMessage * config,
130 				status_t * out_error)
131 {
132 	CALLED();
133 	if (out_error == 0) {
134 		fprintf(stderr,"<- NULL\n");
135 		return 0; // we refuse to crash because you were stupid
136 	}
137 
138 	MultiAudioDevice *device = (MultiAudioDevice*)fDevices.ItemAt(info->internal_id);
139 	if(device == NULL) {
140 		*out_error = B_ERROR;
141 		return NULL;
142 	}
143 
144 #ifdef MULTI_SAVE
145 	if(fSettings.FindMessage(device->MD.friendly_name, config)==B_OK) {
146 		fSettings.RemoveData(device->MD.friendly_name);
147 	}
148 #endif
149 
150 	MultiAudioNode * node
151 		= new MultiAudioNode(this,
152 						  device->MD.friendly_name,
153 						  device,
154 						  info->internal_id,
155 						  config);
156 	if (node == 0) {
157 		*out_error = B_NO_MEMORY;
158 		fprintf(stderr,"<- B_NO_MEMORY\n");
159 	} else {
160 		*out_error = node->InitCheck();
161 	}
162 	return node;
163 }
164 
165 status_t
166 MultiAudioAddOn::GetConfigurationFor(BMediaNode * your_node, BMessage * into_message)
167 {
168 	CALLED();
169 #ifdef MULTI_SAVE
170 	if (into_message == 0) {
171 		into_message = new BMessage();
172 		MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node);
173 		if (node == 0) {
174 			fprintf(stderr,"<- B_BAD_TYPE\n");
175 			return B_BAD_TYPE;
176 		}
177 		if(node->GetConfigurationFor(into_message)==B_OK) {
178 			fSettings.AddMessage(your_node->Name(), into_message);
179 		}
180 		return B_OK;
181 	}
182 #endif
183 	// currently never called by the media kit. Seems it is not implemented.
184 	if (into_message == 0) {
185 		fprintf(stderr,"<- B_BAD_VALUE\n");
186 		return B_BAD_VALUE; // we refuse to crash because you were stupid
187 	}
188 	MultiAudioNode * node = dynamic_cast<MultiAudioNode*>(your_node);
189 	if (node == 0) {
190 		fprintf(stderr,"<- B_BAD_TYPE\n");
191 		return B_BAD_TYPE;
192 	}
193 	return node->GetConfigurationFor(into_message);
194 }
195 
196 
197 bool MultiAudioAddOn::WantsAutoStart()
198 {
199 	CALLED();
200 	return false;
201 }
202 
203 status_t MultiAudioAddOn::AutoStart(
204 				int in_count,
205 				BMediaNode ** out_node,
206 				int32 * out_internal_id,
207 				bool * out_has_more)
208 {
209 	CALLED();
210 	return B_OK;
211 }
212 
213 status_t
214 MultiAudioAddOn::RecursiveScan(char* rootPath, BEntry *rootEntry)
215 {
216 	CALLED();
217 
218 	BDirectory root;
219 	if(rootEntry!=NULL)
220 		root.SetTo(rootEntry);
221 	else if(rootPath!=NULL) {
222 		root.SetTo(rootPath);
223 	} else {
224 		PRINT(("Error in MultiAudioAddOn::RecursiveScan null params\n"));
225 		return B_ERROR;
226 	}
227 
228 	BEntry entry;
229 
230 	while(root.GetNextEntry(&entry) > B_ERROR) {
231 
232 		if(entry.IsDirectory()) {
233 			RecursiveScan(rootPath, &entry);
234 		} else {
235 			BPath path;
236 			entry.GetPath(&path);
237 			MultiAudioDevice *device = new MultiAudioDevice(path.Path() + strlen(rootPath), path.Path());
238 			if (device) {
239 				if (device->InitCheck() == B_OK)
240 					fDevices.AddItem(device);
241 				else
242 					delete device;
243 			}
244 		}
245 	}
246 
247 	return B_OK;
248 }
249 
250 
251 void
252 MultiAudioAddOn::SaveSettings(void)
253 {
254 	CALLED();
255 	BPath path;
256 	if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
257 		path.Append(SETTINGS_FILE);
258 		BFile file(path.Path(),B_READ_WRITE|B_CREATE_FILE|B_ERASE_FILE);
259 		if(file.InitCheck()==B_OK)
260 			fSettings.Flatten(&file);
261 	}
262 }
263 
264 
265 void
266 MultiAudioAddOn::LoadSettings(void)
267 {
268 	CALLED();
269 	fSettings.MakeEmpty();
270 
271 	BPath path;
272 	if(find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
273 		path.Append(SETTINGS_FILE);
274 		BFile file(path.Path(),B_READ_ONLY);
275 		if((file.InitCheck()==B_OK)&&(fSettings.Unflatten(&file)==B_OK))
276 		{
277 			PRINT_OBJECT(fSettings);
278 		} else {
279 			PRINT(("Error unflattening settings file %s\n",path.Path()));
280 		}
281 	}
282 }
283