1 /*
2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "DVBMediaAddon.h"
26 #include "DVBCard.h"
27 #include "DVBMediaNode.h"
28 #include "config.h"
29
30 #include <string.h>
31 #include <stdio.h>
32 #include <time.h>
33 #include <Alert.h>
34 #include <Directory.h>
35 #include <Entry.h>
36 #include <Path.h>
37
38 struct device_info
39 {
40 DVBCard * card;
41 char name[200];
42 char info[200];
43 media_format formats[5];
44 flavor_info flavor;
45 };
46
47
48 extern "C" BMediaAddOn *
make_media_addon(image_id id)49 make_media_addon(image_id id)
50 {
51 return new DVBMediaAddon(id);
52 }
53
54
DVBMediaAddon(image_id id)55 DVBMediaAddon::DVBMediaAddon(image_id id)
56 : BMediaAddOn(id)
57 {
58 ScanFolder("/dev/dvb");
59 }
60
61
~DVBMediaAddon()62 DVBMediaAddon::~DVBMediaAddon()
63 {
64 FreeDeviceList();
65 }
66
67
68 status_t
InitCheck(const char ** out_failure_text)69 DVBMediaAddon::InitCheck(const char ** out_failure_text)
70 {
71 debugger("");
72 if (!fDeviceList.CountItems()) {
73 *out_failure_text = "No supported device found";
74 return B_ERROR;
75 }
76
77 return B_OK;
78 }
79
80
81 int32
CountFlavors()82 DVBMediaAddon::CountFlavors()
83 {
84 return fDeviceList.CountItems();
85 }
86
87
88 status_t
GetFlavorAt(int32 n,const flavor_info ** out_info)89 DVBMediaAddon::GetFlavorAt(int32 n, const flavor_info ** out_info)
90 {
91 device_info *dev = (device_info *)fDeviceList.ItemAt(n);
92 if (!dev)
93 return B_ERROR;
94 *out_info = &dev->flavor;
95 return B_OK;
96 }
97
98
99 BMediaNode *
InstantiateNodeFor(const flavor_info * info,BMessage * config,status_t * out_error)100 DVBMediaAddon::InstantiateNodeFor(const flavor_info * info, BMessage * config, status_t * out_error)
101 {
102 printf("DVB: DVBMediaAddon::InstantiateNodeFor\n");
103
104 device_info *dev = (device_info *)fDeviceList.ItemAt(info->internal_id);
105 if (!dev || dev->flavor.internal_id != info->internal_id) {
106 *out_error = B_ERROR;
107 return NULL;
108 }
109 *out_error = B_OK;
110
111 return new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card);
112 }
113
114
115 bool
WantsAutoStart()116 DVBMediaAddon::WantsAutoStart()
117 {
118 #if BUILD_FOR_HAIKU
119 // printf("DVB: DVBMediaAddon::WantsAutoStart - NO\n");
120 return false;
121 #else
122 // printf("DVB: DVBMediaAddon::WantsAutoStart - YES\n");
123 return true;
124 #endif
125 }
126
127
128 status_t
AutoStart(int index,BMediaNode ** outNode,int32 * outInternalID,bool * outHasMore)129 DVBMediaAddon::AutoStart(int index, BMediaNode **outNode, int32 *outInternalID, bool *outHasMore)
130 {
131 printf("DVB: DVBMediaAddon::AutoStart, index %d\n", index);
132
133 #if BUILD_FOR_HAIKU
134 return B_ERROR;
135 #else
136
137 device_info *dev = (device_info *)fDeviceList.ItemAt(index);
138 if (!dev) {
139 printf("DVB: DVBMediaAddon::AutoStart, bad index\n");
140 return B_BAD_INDEX;
141 }
142
143 *outHasMore = fDeviceList.ItemAt(index + 1) ? true : false;
144 *outInternalID = dev->flavor.internal_id;
145 *outNode = new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card);
146
147 printf("DVB: DVBMediaAddon::AutoStart, success\n");
148
149 return B_OK;
150 #endif
151 }
152
153
154 void
ScanFolder(const char * path)155 DVBMediaAddon::ScanFolder(const char *path)
156 {
157 BDirectory dir(path);
158 if (dir.InitCheck() != B_OK)
159 return;
160
161 BEntry ent;
162
163 while (dir.GetNextEntry(&ent) == B_OK) {
164 BPath path(&ent);
165 if (ent.IsDirectory()) {
166 ScanFolder(path.Path());
167 } else {
168 DVBCard *card = new DVBCard(path.Path());
169 if (card->InitCheck() == B_OK)
170 AddDevice(card, path.Path());
171 else
172 delete card;
173 }
174 }
175 }
176
177
178 void
AddDevice(DVBCard * card,const char * path)179 DVBMediaAddon::AddDevice(DVBCard *card, const char *path)
180 {
181 dvb_type_t type;
182 char name[250];
183 char info[1000];
184 const char *dvbtype;
185 const char *dvbnumber;
186
187 // get card name, info and type
188 if (B_OK != card->GetCardType(&type)) {
189 printf("DVBMediaAddon::AddDevice: getting DVB card type failed\n");
190 return;
191 }
192 if (B_OK != card->GetCardInfo(name, sizeof(name), info, sizeof(info))) {
193 printf("DVBMediaAddon::AddDevice: getting DVB card info failed\n");
194 return;
195 }
196
197 // get type
198 switch (type) {
199 case DVB_TYPE_DVB_C: dvbtype = "C"; break;
200 case DVB_TYPE_DVB_H: dvbtype = "H"; break;
201 case DVB_TYPE_DVB_S: dvbtype = "S"; break;
202 case DVB_TYPE_DVB_T: dvbtype = "T"; break;
203 default:
204 printf("DVBMediaAddon::AddDevice: unsupported DVB type %d\n", type);
205 return;
206 }
207
208 // get interface number
209 const char *p = strrchr(path, '/');
210 dvbnumber = p ? p + 1 : "";
211
212 // create device_info
213 device_info *dev = new device_info;
214 fDeviceList.AddItem(dev);
215
216 dev->card = card;
217
218 // setup name and info, it's important that name starts with "DVB"
219 // snprintf(dev->name, sizeof(dev->name), "DVB-%s %s (%s)", dvbtype, dvbnumber, name);
220 // strlcpy(dev->info, info, sizeof(dev->info));
221 sprintf(dev->name, "DVB-%s %s %s", dvbtype, name, dvbnumber);
222 strcpy(dev->info, info);
223
224 // setup supported formats (the lazy way)
225 memset(dev->formats, 0, sizeof(dev->formats));
226 dev->formats[0].type = B_MEDIA_RAW_VIDEO;
227 dev->formats[1].type = B_MEDIA_RAW_AUDIO;
228 dev->formats[2].type = B_MEDIA_ENCODED_VIDEO;
229 dev->formats[3].type = B_MEDIA_ENCODED_AUDIO;
230 dev->formats[4].type = B_MEDIA_MULTISTREAM;
231
232 // setup flavor info
233 dev->flavor.name = dev->name;
234 dev->flavor.info = dev->info;
235 dev->flavor.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
236 dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
237 dev->flavor.internal_id = fDeviceList.CountItems() - 1;
238 dev->flavor.possible_count = 1;
239 dev->flavor.in_format_count = 0;
240 dev->flavor.in_format_flags = 0;
241 dev->flavor.in_formats = 0;
242 dev->flavor.out_format_count = 5;
243 dev->flavor.out_format_flags = 0;
244 dev->flavor.out_formats = dev->formats;
245 }
246
247
248 void
FreeDeviceList()249 DVBMediaAddon::FreeDeviceList()
250 {
251 device_info *dev;
252 while ((dev = (device_info *)fDeviceList.RemoveItem((int32)0))) {
253 delete dev->card;
254 delete dev;
255 }
256 }
257