/* * 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 "debug.h" #include "DataExchange.h" /* * some little helper function */ static inline char *_newstrdup(const char *str); 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; } #define MAX_FLAVOR_IN_FORMAT_COUNT 300 #define MAX_FLAVOR_OUT_FORMAT_COUNT 300 #define FLATTEN_MAGIC 'CODE' #define FLATTEN_TYPECODE 'DFIT' /************************************************************* * public dormant_node_info *************************************************************/ // final & verified dormant_node_info::dormant_node_info() : addon(-1), flavor_id(-1) { name[0] = '\0'; } // final dormant_node_info::~dormant_node_info() { } /************************************************************* * private flavor_info *************************************************************/ /* DO NOT IMPLEMENT */ /* flavor_info &flavor_info::operator=(const flavor_info &other) */ /************************************************************* * public dormant_flavor_info *************************************************************/ // final & verified dormant_flavor_info::dormant_flavor_info() { name = 0; info = 0; kinds = 0; flavor_flags = 0; internal_id = 0; possible_count = 0; in_format_count = 0; in_format_flags = 0; in_formats = 0; out_format_count = 0; out_format_flags = 0; out_formats = 0; } /* virtual */ 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) { *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 = 0; in_format_count = 0; in_format_flags = clone.in_format_flags; if (kinds & B_BUFFER_CONSUMER) { 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 = 0; 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 from dormant_node_info constructor dormant_node_info defaultValues; node_info = defaultValues; return *this; } void dormant_flavor_info::set_name(const char *in_name) { delete [] name; name = _newstrdup(in_name); } void dormant_flavor_info::set_info(const char *in_info) { delete [] info; info = _newstrdup(in_info); } 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; } } /* virtual */ bool dormant_flavor_info::IsFixedSize() const { return false; } /* virtual */ type_code dormant_flavor_info::TypeCode() const { return FLATTEN_TYPECODE; } /* virtual */ 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; } /* virtual */ 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) && 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) && 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; } /* virtual */ 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 name = new(std::nothrow) char [nameLength + 1]; if (name) { memcpy(name, buf, nameLength); name[nameLength] = 0; buf += nameLength; // XXX not save } } infoLength = *(int32*)buf; buf += sizeof(int32); if (infoLength >= 0) { // if infoLength is -1, we leave info = 0 info = new(std::nothrow) char [infoLength + 1]; if (info) { memcpy(info, buf, infoLength); info[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; // XXX FIXME! we should not!!! make flat copies of media_format memcpy(const_cast(in_formats), buf, count * sizeof(media_format)); in_format_count = count; } buf += count * sizeof(media_format); // XXX not save } 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; // XXX FIXME! we should not!!! make flat copies of media_format memcpy(const_cast(out_formats), buf, count * sizeof(media_format)); out_format_count = count; } buf += count * sizeof(media_format); // XXX not save } node_info = *(dormant_node_info*)buf; buf += sizeof(dormant_node_info); return B_OK; } /************************************************************* * public BMediaAddOn *************************************************************/ /* explicit */ BMediaAddOn::BMediaAddOn(image_id image) : fImage(image), fAddon(0) { CALLED(); } /* virtual */ BMediaAddOn::~BMediaAddOn() { CALLED(); } /* virtual */ status_t BMediaAddOn::InitCheck(const char **out_failure_text) { CALLED(); // only to be implemented by derived classes *out_failure_text = "no error"; return B_OK; } /* virtual */ int32 BMediaAddOn::CountFlavors() { CALLED(); // only to be implemented by derived classes return 0; } /* virtual */ status_t BMediaAddOn::GetFlavorAt(int32 n, const flavor_info **out_info) { CALLED(); // only to be implemented by derived classes return B_ERROR; } /* virtual */ BMediaNode * BMediaAddOn::InstantiateNodeFor(const flavor_info *info, BMessage *config, status_t *out_error) { CALLED(); // only to be implemented by derived classes return NULL; } /* virtual */ status_t BMediaAddOn::GetConfigurationFor(BMediaNode *your_node, BMessage *into_message) { CALLED(); // only to be implemented by derived classes return B_ERROR; } /* virtual */ bool BMediaAddOn::WantsAutoStart() { CALLED(); // only to be implemented by derived classes return false; } /* virtual */ status_t BMediaAddOn::AutoStart(int in_count, BMediaNode **out_node, int32 *out_internal_id, bool *out_has_more) { CALLED(); // only to be implemented by derived classes return B_ERROR; } /* virtual */ status_t BMediaAddOn::SniffRef(const entry_ref &file, BMimeType *io_mime_type, float *out_quality, int32 *out_internal_id) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } /* virtual */ status_t BMediaAddOn::SniffType(const BMimeType &type, float *out_quality, int32 *out_internal_id) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } /* virtual */ status_t BMediaAddOn::GetFileFormatList(int32 flavor_id, media_file_format *out_writable_formats, int32 in_write_items, int32 *out_write_items, media_file_format *out_readable_formats, int32 in_read_items, int32 *out_read_items, void *_reserved) { CALLED(); // only to be implemented by BFileInterface derived classes return B_ERROR; } /* virtual */ status_t BMediaAddOn::SniffTypeKind(const BMimeType &type, uint64 in_kinds, float *out_quality, int32 *out_internal_id, 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; } /************************************************************* * protected BMediaAddOn *************************************************************/ status_t BMediaAddOn::NotifyFlavorChange() { CALLED(); if (fAddon == 0) return B_ERROR; addonserver_rescan_mediaaddon_flavors_command command; command.addonid = fAddon; return SendToAddonServer(ADDONSERVER_RESCAN_MEDIAADDON_FLAVORS, &command, sizeof(command)); } /************************************************************* * private BMediaAddOn *************************************************************/ /* unimplemented: BMediaAddOn::BMediaAddOn() BMediaAddOn::BMediaAddOn(const BMediaAddOn &clone) BMediaAddOn & BMediaAddOn::operator=(const BMediaAddOn &clone) */ /************************************************************* * private BMediaAddOn *************************************************************/ 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; }