1 /*
2 * FireWire DV media addon for Haiku
3 *
4 * Copyright (c) 2008, JiSheng Zhang (jszhang3@mail.ustc.edu.cn)
5 * Distributed under the terms of the MIT License.
6 *
7 * Based on DVB media addon
8 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
9 */
10
11 #include "FireWireDVAddOn.h"
12 #include "FireWireCard.h"
13 #include "FireWireDVNode.h"
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <time.h>
18
19 #include <Alert.h>
20 #include <Directory.h>
21 #include <Entry.h>
22 #include <Path.h>
23
24 #include "debug.h"
25
26 struct device_info
27 {
28 FireWireCard* card;
29 char name[16];
30 media_format in_formats[1];
31 media_format out_formats[1];
32 flavor_info flavor;
33 };
34
35 extern "C" BMediaAddOn*
make_media_addon(image_id id)36 make_media_addon(image_id id)
37 {
38 CALLED();
39 return new FireWireDVAddOn(id);
40 }
41
42
FireWireDVAddOn(image_id id)43 FireWireDVAddOn::FireWireDVAddOn(image_id id)
44 : BMediaAddOn(id)
45 {
46 CALLED();
47 ScanFolder("/dev/bus/fw");
48 }
49
50
~FireWireDVAddOn()51 FireWireDVAddOn::~FireWireDVAddOn()
52 {
53 CALLED();
54 FreeDeviceList();
55 }
56
57
58 status_t
InitCheck(const char ** out_failure_text)59 FireWireDVAddOn::InitCheck(const char** out_failure_text)
60 {
61 CALLED();
62 if (!fDeviceList.CountItems()) {
63 *out_failure_text = "No supported device found";
64 return B_ERROR;
65 }
66 return B_OK;
67 }
68
69
70 int32
CountFlavors()71 FireWireDVAddOn::CountFlavors()
72 {
73 CALLED();
74 return fDeviceList.CountItems();
75 }
76
77
78 status_t
GetFlavorAt(int32 n,const flavor_info ** out_info)79 FireWireDVAddOn::GetFlavorAt(int32 n, const flavor_info** out_info)
80 {
81 CALLED();
82 device_info* dev = fDeviceList.ItemAt(n);
83 if (!dev)
84 return B_ERROR;
85 *out_info = &dev->flavor;
86 return B_OK;
87 }
88
89
90 BMediaNode *
InstantiateNodeFor(const flavor_info * info,BMessage * config,status_t * out_error)91 FireWireDVAddOn::InstantiateNodeFor(const flavor_info* info, BMessage* config,
92 status_t* out_error)
93 {
94 CALLED();
95 device_info* dev = fDeviceList.ItemAt(info->internal_id);
96 if (!dev || dev->flavor.internal_id != info->internal_id) {
97 *out_error = B_ERROR;
98 return NULL;
99 }
100 *out_error = B_OK;
101
102 return new FireWireDVNode(this, dev->name, dev->flavor.internal_id,
103 dev->card);
104 }
105
106
107 bool
WantsAutoStart()108 FireWireDVAddOn::WantsAutoStart()
109 {
110 CALLED();
111 return false;
112 }
113
114
115 status_t
AutoStart(int index,BMediaNode ** outNode,int32 * outInternalID,bool * outHasMore)116 FireWireDVAddOn::AutoStart(int index, BMediaNode** outNode,
117 int32* outInternalID, bool* outHasMore)
118 {
119 CALLED();
120 return B_ERROR;
121 }
122
123
124 void
ScanFolder(const char * path)125 FireWireDVAddOn::ScanFolder(const char* path)
126 {
127 CALLED();
128 BDirectory dir(path);
129 if (dir.InitCheck() != B_OK)
130 return;
131
132 BEntry ent;
133
134 while (dir.GetNextEntry(&ent) == B_OK) {
135 BPath path(&ent);
136 if (!ent.IsDirectory() && !ent.IsSymLink()) {
137 FireWireCard *card = new FireWireCard(path.Path());
138 if (card->InitCheck() == B_OK)
139 AddDevice(card, path.Path());
140 else
141 delete card;
142 }
143 }
144 }
145
146
147 void
AddDevice(FireWireCard * card,const char * path)148 FireWireDVAddOn::AddDevice(FireWireCard* card, const char* path)
149 {
150 const char* fwnumber;
151
152 // get card name, info and type
153
154 // get interface number
155 const char *p = strrchr(path, '/');
156 fwnumber = p ? p + 1 : "";
157
158 // create device_info
159 device_info *dev = new device_info;
160 fDeviceList.AddItem(dev);
161
162 dev->card = card;
163
164 sprintf(dev->name, "FireWire-%s", fwnumber);
165
166 // setup supported formats (the lazy way)
167 memset(dev->in_formats, 0, sizeof(dev->in_formats));
168 memset(dev->out_formats, 0, sizeof(dev->out_formats));
169 dev->in_formats[0].type = B_MEDIA_ENCODED_VIDEO;
170 dev->out_formats[0].type = B_MEDIA_ENCODED_VIDEO;
171
172 // setup flavor info
173 dev->flavor.name = dev->name;
174 dev->flavor.info = (char *)"The FireWireDVNode outputs to fw_raw drivers.";
175 dev->flavor.kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER
176 | B_CONTROLLABLE | B_PHYSICAL_OUTPUT | B_PHYSICAL_INPUT;
177 dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
178 dev->flavor.internal_id = fDeviceList.CountItems() - 1;
179 dev->flavor.possible_count = 1;
180 dev->flavor.in_format_count = 1;
181 dev->flavor.in_format_flags = 0;
182 dev->flavor.in_formats = dev->in_formats;
183 dev->flavor.out_format_count = 1;
184 dev->flavor.out_format_flags = 0;
185 dev->flavor.out_formats = dev->out_formats;
186 }
187
188
189 void
FreeDeviceList()190 FireWireDVAddOn::FreeDeviceList()
191 {
192 device_info* dev;
193 while ((dev = fDeviceList.RemoveItemAt(0L))) {
194 delete dev->card;
195 delete dev;
196 }
197 }
198
199