/* * FireWire DV media addon for Haiku * * Copyright (c) 2008, JiSheng Zhang (jszhang3@mail.ustc.edu.cn) * Distributed under the terms of the MIT License. * * Based on DVB media addon * Copyright (c) 2004-2007 Marcus Overhagen */ #include "FireWireDVAddOn.h" #include "FireWireCard.h" #include "FireWireDVNode.h" #include #include #include #include #include #include #include #include "debug.h" struct device_info { FireWireCard* card; char name[16]; media_format in_formats[1]; media_format out_formats[1]; flavor_info flavor; }; extern "C" BMediaAddOn* make_media_addon(image_id id) { CALLED(); return new FireWireDVAddOn(id); } FireWireDVAddOn::FireWireDVAddOn(image_id id) : BMediaAddOn(id) { CALLED(); ScanFolder("/dev/bus/fw"); } FireWireDVAddOn::~FireWireDVAddOn() { CALLED(); FreeDeviceList(); } status_t FireWireDVAddOn::InitCheck(const char** out_failure_text) { CALLED(); if (!fDeviceList.CountItems()) { *out_failure_text = "No supported device found"; return B_ERROR; } return B_OK; } int32 FireWireDVAddOn::CountFlavors() { CALLED(); return fDeviceList.CountItems(); } status_t FireWireDVAddOn::GetFlavorAt(int32 n, const flavor_info** out_info) { CALLED(); device_info* dev = fDeviceList.ItemAt(n); if (!dev) return B_ERROR; *out_info = &dev->flavor; return B_OK; } BMediaNode * FireWireDVAddOn::InstantiateNodeFor(const flavor_info* info, BMessage* config, status_t* out_error) { CALLED(); device_info* dev = fDeviceList.ItemAt(info->internal_id); if (!dev || dev->flavor.internal_id != info->internal_id) { *out_error = B_ERROR; return NULL; } *out_error = B_OK; return new FireWireDVNode(this, dev->name, dev->flavor.internal_id, dev->card); } bool FireWireDVAddOn::WantsAutoStart() { CALLED(); return false; } status_t FireWireDVAddOn::AutoStart(int index, BMediaNode** outNode, int32* outInternalID, bool* outHasMore) { CALLED(); return B_ERROR; } void FireWireDVAddOn::ScanFolder(const char* path) { CALLED(); BDirectory dir(path); if (dir.InitCheck() != B_OK) return; BEntry ent; while (dir.GetNextEntry(&ent) == B_OK) { BPath path(&ent); if (!ent.IsDirectory() && !ent.IsSymLink()) { FireWireCard *card = new FireWireCard(path.Path()); if (card->InitCheck() == B_OK) AddDevice(card, path.Path()); else delete card; } } } void FireWireDVAddOn::AddDevice(FireWireCard* card, const char* path) { const char* fwnumber; // get card name, info and type // get interface number const char *p = strrchr(path, '/'); fwnumber = p ? p + 1 : ""; // create device_info device_info *dev = new device_info; fDeviceList.AddItem(dev); dev->card = card; sprintf(dev->name, "FireWire-%s", fwnumber); // setup supported formats (the lazy way) memset(dev->in_formats, 0, sizeof(dev->in_formats)); memset(dev->out_formats, 0, sizeof(dev->out_formats)); dev->in_formats[0].type = B_MEDIA_ENCODED_VIDEO; dev->out_formats[0].type = B_MEDIA_ENCODED_VIDEO; // setup flavor info dev->flavor.name = dev->name; dev->flavor.info = (char *)"The FireWireDVNode outputs to fw_raw drivers."; dev->flavor.kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_OUTPUT | B_PHYSICAL_INPUT; dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL; dev->flavor.internal_id = fDeviceList.CountItems() - 1; dev->flavor.possible_count = 1; dev->flavor.in_format_count = 1; dev->flavor.in_format_flags = 0; dev->flavor.in_formats = dev->in_formats; dev->flavor.out_format_count = 1; dev->flavor.out_format_flags = 0; dev->flavor.out_formats = dev->out_formats; } void FireWireDVAddOn::FreeDeviceList() { device_info* dev; while ((dev = fDeviceList.RemoveItemAt(0L))) { delete dev->card; delete dev; } }