/* * Copyright (c) 2002, 2003, 2008 Marcus Overhagen * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files or portions * thereof (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject * to the following conditions: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice * in the binary, as well as this list of conditions and the following * disclaimer in the documentation and/or other materials provided with * the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #include #include #include #include #include "MediaDebug.h" #include "DataExchange.h" #define MAX_FLAVOR_IN_FORMAT_COUNT 300 #define MAX_FLAVOR_OUT_FORMAT_COUNT 300 #define FLATTEN_MAGIC 'CODE' #define FLATTEN_TYPECODE 'DFIT' static char * _newstrdup(const char *str) { if (str == NULL) return NULL; int len = strlen(str) + 1; char *p = new(std::nothrow) char[len]; if (p) memcpy(p, str, len); return p; } // #pragma mark - dormant_node_info dormant_node_info::dormant_node_info() : addon(-1), flavor_id(-1) { name[0] = '\0'; } dormant_node_info::~dormant_node_info() { } // #pragma mark - flavor_info /* DO NOT IMPLEMENT */ /* flavor_info &flavor_info::operator=(const flavor_info &other) */ // #pragma mark - dormant_flavor_info dormant_flavor_info::dormant_flavor_info() { name = NULL; info = NULL; kinds = 0; flavor_flags = 0; internal_id = 0; possible_count = 0; in_format_count = 0; in_format_flags = 0; in_formats = NULL; out_format_count = 0; out_format_flags = 0; out_formats = NULL; } dormant_flavor_info::~dormant_flavor_info() { delete[] name; delete[] info; delete[] in_formats; delete[] out_formats; } dormant_flavor_info::dormant_flavor_info(const dormant_flavor_info &clone) { name = NULL; info = NULL; in_formats = NULL; out_formats = NULL; *this = clone; } dormant_flavor_info & dormant_flavor_info::operator=(const dormant_flavor_info &clone) { // call operator=(const flavor_info &clone) to copy the flavor_info base class *this = static_cast(clone); // copy the dormant_node_info member variable node_info = clone.node_info; return *this; } dormant_flavor_info & dormant_flavor_info::operator=(const flavor_info &clone) { kinds = clone.kinds; flavor_flags = clone.flavor_flags; internal_id = clone.internal_id; possible_count = clone.possible_count; delete [] info; info = _newstrdup(clone.info); delete [] name; name = _newstrdup(clone.name); delete [] in_formats; in_formats = NULL; in_format_count = 0; in_format_flags = clone.in_format_flags; if ((kinds & B_BUFFER_CONSUMER) != 0) { if (clone.in_format_count >= 0 && clone.in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT) { in_formats = new(std::nothrow) media_format[clone.in_format_count]; if (in_formats != NULL && clone.in_formats != NULL) { in_format_count = clone.in_format_count; for (int i = 0; i < in_format_count; i++) { const_cast(in_formats[i]) = clone.in_formats[i]; } } } else { fprintf(stderr, "error: dormant_flavor_info::operator= clone.in_" "format_count is invalid\n"); } } else if (clone.in_format_count) { fprintf(stderr, "warning: dormant_flavor_info::operator= not " "B_BUFFER_CONSUMER and clone.in_format_count is != 0\n"); } delete [] out_formats; out_formats = NULL; out_format_count = 0; out_format_flags = clone.out_format_flags; if (kinds & B_BUFFER_PRODUCER) { if (clone.out_format_count >= 0 && clone.out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { out_formats = new(std::nothrow) media_format[clone.out_format_count]; if (out_formats != NULL && clone.out_formats != NULL) { out_format_count = clone.out_format_count; for (int i = 0; i < out_format_count; i++) { const_cast(out_formats[i]) = clone.out_formats[i]; } } } else { fprintf(stderr, "error dormant_flavor_info::operator= clone.out_" "format_count is invalid\n"); } } else if (clone.out_format_count) { fprintf(stderr, "warning: dormant_flavor_info::operator= not " "B_BUFFER_PRODUCER and clone.out_format_count is != 0\n"); } // initialize node_info with default values dormant_node_info defaultValues; node_info = defaultValues; return *this; } void dormant_flavor_info::set_name(const char *newName) { delete[] name; name = _newstrdup(newName); } void dormant_flavor_info::set_info(const char *newInfo) { delete[] info; info = _newstrdup(newInfo); } void dormant_flavor_info::add_in_format(const media_format &in_format) { media_format *p = new(std::nothrow) media_format[in_format_count + 1]; if (p) { for (int i = 0; i < in_format_count; i++) p[i] = in_formats[i]; p[in_format_count] = in_format; delete [] in_formats; in_formats = p; in_format_count += 1; } } void dormant_flavor_info::add_out_format(const media_format &out_format) { media_format *p = new(std::nothrow) media_format[out_format_count + 1]; if (p) { for (int i = 0; i < out_format_count; i++) p[i] = out_formats[i]; p[out_format_count] = out_format; delete [] out_formats; out_formats = p; out_format_count += 1; } } bool dormant_flavor_info::IsFixedSize() const { return false; } type_code dormant_flavor_info::TypeCode() const { return FLATTEN_TYPECODE; } ssize_t dormant_flavor_info::FlattenedSize() const { ssize_t size = 0; // magic size += sizeof(int32); // size size += sizeof(int32); // struct flavor_info size += sizeof(int32) + strlen(name); size += sizeof(int32) + strlen(info); size += sizeof(kinds); size += sizeof(flavor_flags); size += sizeof(internal_id); size += sizeof(possible_count); size += sizeof(in_format_count); size += sizeof(in_format_flags); if (in_format_count > 0 && in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT && in_formats != NULL) size += in_format_count * sizeof(media_format); size += sizeof(out_format_count); size += sizeof(out_format_flags); if (out_format_count > 0 && out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT && out_formats != NULL) size += out_format_count * sizeof(media_format); // struct dormant_node_info node_info size += sizeof(node_info); return size; } status_t dormant_flavor_info::Flatten(void *buffer, ssize_t size) const { if (size < FlattenedSize()) return B_ERROR; char *buf = (char *)buffer; int32 nameLength = name ? (int32)strlen(name) : -1; int32 infoLength = info ? (int32)strlen(info) : -1; int32 inFormatCount = 0; size_t inFormatSize = 0; int32 outFormatCount = 0; size_t outFormatSize = 0; if ((kinds & B_BUFFER_CONSUMER) != 0 && in_format_count > 0 && in_formats != NULL) { if (in_format_count <= MAX_FLAVOR_IN_FORMAT_COUNT) { inFormatCount = in_format_count; inFormatSize = in_format_count * sizeof(media_format); } else { fprintf(stderr, "error dormant_flavor_info::Flatten: " "in_format_count is too large\n"); return B_ERROR; } } if ((kinds & B_BUFFER_PRODUCER) != 0 && out_format_count > 0 && out_formats != NULL) { if (out_format_count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { outFormatCount = out_format_count; outFormatSize = out_format_count * sizeof(media_format); } else { fprintf(stderr, "error dormant_flavor_info::Flatten: " "out_format_count is too large\n"); return B_ERROR; } } // magic *(int32*)buf = FLATTEN_MAGIC; buf += sizeof(int32); // size *(int32*)buf = FlattenedSize(); buf += sizeof(int32); // struct flavor_info *(int32*)buf = nameLength; buf += sizeof(int32); if (nameLength > 0) { memcpy(buf, name, nameLength); buf += nameLength; } *(int32*)buf = infoLength; buf += sizeof(int32); if (infoLength > 0) { memcpy(buf, info, infoLength); buf += infoLength; } *(uint64*)buf = kinds; buf += sizeof(uint64); *(uint32*)buf = flavor_flags; buf += sizeof(uint32); *(int32*)buf = internal_id; buf += sizeof(int32); *(int32*)buf = possible_count; buf += sizeof(int32); *(int32*)buf = inFormatCount; buf += sizeof(int32); *(uint32*)buf = in_format_flags; buf += sizeof(uint32); // XXX FIXME! we should not!!! make flat copies of media_format memcpy(buf, in_formats, inFormatSize); buf += inFormatSize; *(int32*)buf = outFormatCount; buf += sizeof(int32); *(uint32*)buf = out_format_flags; buf += sizeof(uint32); // XXX FIXME! we should not!!! make flat copies of media_format memcpy(buf, out_formats, outFormatSize); buf += outFormatSize; *(dormant_node_info*)buf = node_info; buf += sizeof(dormant_node_info); return B_OK; } status_t dormant_flavor_info::Unflatten(type_code c, const void *buffer, ssize_t size) { if (c != FLATTEN_TYPECODE) return B_ERROR; if (size < 8) return B_ERROR; const char *buf = (const char *)buffer; int32 nameLength; int32 infoLength; // check magic if (*(int32*)buf != FLATTEN_MAGIC) return B_ERROR; buf += sizeof(int32); // check size if (*(uint32*)buf > (uint32)size) return B_ERROR; buf += sizeof(int32); delete[] name; name = NULL; delete[] info; info = NULL; delete[] in_formats; in_formats = NULL; in_format_count = 0; delete[] out_formats; out_formats = NULL; out_format_count = 0; // struct flavor_info nameLength = *(int32*)buf; buf += sizeof(int32); if (nameLength >= 0) { // if nameLength is -1, we leave name = 0 char* nameStorage = new(std::nothrow) char [nameLength + 1]; name = nameStorage; if (nameStorage) { memcpy(nameStorage, buf, nameLength); nameStorage[nameLength] = 0; buf += nameLength; // XXX not save } } infoLength = *(int32*)buf; buf += sizeof(int32); if (infoLength >= 0) { // if infoLength is -1, we leave info = 0 char* infoStorage = new(std::nothrow) char [infoLength + 1]; info = infoStorage; if (infoStorage) { memcpy(infoStorage, buf, infoLength); infoStorage[infoLength] = 0; buf += infoLength; // XXX not save } } int32 count; kinds = *(uint64*)buf; buf += sizeof(uint64); flavor_flags = *(uint32*)buf; buf += sizeof(uint32); internal_id = *(int32*)buf; buf += sizeof(int32); possible_count = *(int32*)buf; buf += sizeof(int32); count = *(int32*)buf; buf += sizeof(int32); in_format_flags = *(uint32*)buf; buf += sizeof(uint32); if (count > 0) { if (count <= MAX_FLAVOR_IN_FORMAT_COUNT) { in_formats = new(std::nothrow) media_format[count]; if (!in_formats) return B_NO_MEMORY; // TODO: we should not!!! make flat copies of media_format for (int32 i = 0; i < count; i++) { const_cast (&in_formats[i])->Unflatten(buf); buf += sizeof(media_format); // TODO: not save } in_format_count = count; } } count = *(int32*)buf; buf += sizeof(int32); out_format_flags = *(uint32*)buf; buf += sizeof(uint32); if (count > 0) { if (count <= MAX_FLAVOR_OUT_FORMAT_COUNT) { out_formats = new(std::nothrow) media_format[count]; if (!out_formats) return B_NO_MEMORY; // TODO: we should not!!! make flat copies of media_format for (int32 i = 0; i < count; i++) { const_cast (&out_formats[i])->Unflatten(buf); buf += sizeof(media_format); // TODO: not save } out_format_count = count; } } node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info); return B_OK; } // #pragma mark - BMediaAddOn BMediaAddOn::BMediaAddOn(image_id image) : fImage(image), fAddon(0) { CALLED(); } BMediaAddOn::~BMediaAddOn() { CALLED(); } status_t BMediaAddOn::InitCheck(const char **_failureText) { CALLED(); // only to be implemented by derived classes *_failureText = "no error"; return B_OK; } int32 BMediaAddOn::CountFlavors() { CALLED(); // only to be implemented by derived classes return 0; } status_t BMediaAddOn::GetFlavorAt(int32 n, const flavor_info **_info) { CALLED(); // only to be implemented by derived classes return B_ERROR; } BMediaNode* BMediaAddOn::InstantiateNodeFor(const flavor_info *info, BMessage *config, status_t *_error) { CALLED(); // only to be implemented by derived classes return NULL; } status_t BMediaAddOn::GetConfigurationFor(BMediaNode *node, BMessage *toMessage) { CALLED(); // only to be implemented by derived classes return B_ERROR; } bool BMediaAddOn::WantsAutoStart() { CALLED(); // only to be implemented by derived classes return false; } status_t BMediaAddOn::AutoStart(int count, BMediaNode **_node, int32 *_internalID, bool *_hasMore) { CALLED(); // only to be implemented by derived classes return B_ERROR; } status_t BMediaAddOn::SniffRef(const entry_ref &file, BMimeType *mimeType, float *_quality, int32 *_internalID) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } status_t BMediaAddOn::SniffType(const BMimeType &type, float *_quality, int32 *_internalID) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } status_t BMediaAddOn::GetFileFormatList(int32 flavorID, media_file_format *writableFormats, int32 maxWriteItems, int32 *_writeItems, media_file_format *readableFormats, int32 maxReadItems, int32 *_readItems, void *_reserved) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } status_t BMediaAddOn::SniffTypeKind(const BMimeType &type, uint64 kinds, float *_quality, int32 *_internalID, void *_reserved) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } image_id BMediaAddOn::ImageID() { return fImage; } media_addon_id BMediaAddOn::AddonID() { return fAddon; } // #pragma mark - protected BMediaAddOn status_t BMediaAddOn::NotifyFlavorChange() { CALLED(); if (fAddon == 0) return B_ERROR; add_on_server_rescan_flavors_command command; command.add_on_id = fAddon; return SendToAddOnServer(ADD_ON_SERVER_RESCAN_ADD_ON_FLAVORS, &command, sizeof(command)); } // #pragma mark - private BMediaAddOn /* unimplemented: BMediaAddOn::BMediaAddOn() BMediaAddOn::BMediaAddOn(const BMediaAddOn &clone) BMediaAddOn & BMediaAddOn::operator=(const BMediaAddOn &clone) */ extern "C" { // declared here to remove them from the class header file status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::GetFileFormatList */ status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *); /* now used for BMediaAddOn::SniffTypeKind */ status_t _Reserved_MediaAddOn_0__11BMediaAddOnPv(void *, void *) { return B_ERROR; } status_t _Reserved_MediaAddOn_1__11BMediaAddOnPv(void *, void *) { return B_ERROR; } }; status_t BMediaAddOn::_Reserved_MediaAddOn_2(void *) { return B_ERROR; } status_t BMediaAddOn::_Reserved_MediaAddOn_3(void *) { return B_ERROR; } status_t BMediaAddOn::_Reserved_MediaAddOn_4(void *) { return B_ERROR; } status_t BMediaAddOn::_Reserved_MediaAddOn_5(void *) { return B_ERROR; } status_t BMediaAddOn::_Reserved_MediaAddOn_6(void *) { return B_ERROR; } status_t BMediaAddOn::_Reserved_MediaAddOn_7(void *) { return B_ERROR; }