static void flac_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
    MediaScannerClient *client = (MediaScannerClient *)client_data;

    if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
        FLAC__uint64 duration = 1000 * metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate;
        if (duration > 0) {
            char buffer[20];
            sprintf(buffer, "%lld", duration);
            if (!client->addStringTag("duration", buffer))
                return;
        }
    } else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
        for (uint32_t i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
            char *ptr = (char *)metadata->data.vorbis_comment.comments[i].entry;

            char *val = strchr(ptr, '=');
            if (val) {
                int keylen = val++ - ptr;
                char key[keylen + 1];
                strncpy(key, ptr, keylen);
                key[keylen] = 0;
                if (!client->addStringTag(key, val)) return;
            }
        }
    }
}
MediaScanResult StagefrightMediaScanner::processFile(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
    ALOGV("processFile '%s'.", path);

    client.setLocale(locale());
    client.beginFile();
    MediaScanResult result = processFileInternal(path, mimeType, client);
    client.endFile();
    return result;
}
MediaScanResult StagefrightMediaScanner::processFile(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
#ifndef ANDROID_DEFAULT_CODE
    LOGD("processFile '%s'.", path);
#else
    LOGV("processFile '%s'.", path);
#endif // #ifndef ANDROID_DEFAULT_CODE

    client.setLocale(locale());
    client.beginFile();
    MediaScanResult result = processFileInternal(path, mimeType, client);
    client.endFile();
    return result;
}
MediaScanResult StagefrightMediaScanner::processFile(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
#ifdef MTK_AOSP_ENHANCEMENT
    ALOGI("processFile '%s'.", path);
#else
    ALOGV("processFile '%s'.", path);
#endif // #ifdef MTK_AOSP_ENHANCEMENT

    client.setLocale(locale());
    client.beginFile();
    MediaScanResult result = processFileInternal(path, mimeType, client);
    client.endFile();
    return result;
}
示例#5
0
MediaScanResult MediaScanner::processDirectory(
        const char *path, MediaScannerClient &client) {
#ifndef ANDROID_DEFAULT_CODE
    ALOGI("processDirectory: %s \n", path);
#endif  
    int pathLength = strlen(path);
    if (pathLength >= PATH_MAX) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }
    char* pathBuffer = (char *)malloc(PATH_MAX + 1);
    if (!pathBuffer) {
        return MEDIA_SCAN_RESULT_ERROR;
    }

    int pathRemaining = PATH_MAX - pathLength;
    strcpy(pathBuffer, path);
    if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') {
        pathBuffer[pathLength] = '/';
        pathBuffer[pathLength + 1] = 0;
        --pathRemaining;
    }

    client.setLocale(locale());

    MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, false);

    free(pathBuffer);

    return result;
}
示例#6
0
status_t MediaScanner::processDirectory(
        const char *path, const char *extensions,
        MediaScannerClient &client,
        ExceptionCheck exceptionCheck, void *exceptionEnv) {
    int pathLength = strlen(path);
    if (pathLength >= PATH_MAX) {
        return UNKNOWN_ERROR;
    }
    char* pathBuffer = (char *)malloc(PATH_MAX + 1);
    if (!pathBuffer) {
        return UNKNOWN_ERROR;
    }

    int pathRemaining = PATH_MAX - pathLength;
    strcpy(pathBuffer, path);
    if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') {
        pathBuffer[pathLength] = '/';
        pathBuffer[pathLength + 1] = 0;
        --pathRemaining;
    }

    client.setLocale(locale());

    status_t result =
        doProcessDirectory(
                pathBuffer, pathRemaining, extensions, client,
                exceptionCheck, exceptionEnv);

    free(pathBuffer);

    return result;
}
示例#7
0
MediaScanResult MediaScanner::processDirectory(
        const char *path, MediaScannerClient &client) {
#ifdef MTK_AOSP_ENHANCEMENT
    ALOGI("processDirectory: %s \n", path);
#endif  
    int pathLength = strlen(path);
    if (pathLength >= PATH_MAX) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }
    char* pathBuffer = (char *)malloc(PATH_MAX + 1);
    if (!pathBuffer) {
        return MEDIA_SCAN_RESULT_ERROR;
    }

    int pathRemaining = PATH_MAX - pathLength;
    strcpy(pathBuffer, path);
    if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') {
        pathBuffer[pathLength] = '/';
        pathBuffer[pathLength + 1] = 0;
        --pathRemaining;
    }

    client.setLocale(locale());

	/// M: add for the new feature about the new thread pool on JB9.MP/KK/KK.AOSP branch
	bool flag = false;
    for (int i = pathLength - 1; i >= 1; i--) {
        if ((pathBuffer[i] == '.') && (pathBuffer[i - 1] == '/')) {
			ALOGW("Include nomeida folder.");
			flag = true;
        } 
    }

    MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, flag);
	/// @}

    free(pathBuffer);

    return result;
}
MediaScanResult StagefrightMediaScanner::processFileInternal(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
    const char *extension = strrchr(path, '.');

    if (!extension) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

    if (!FileHasAcceptableExtension(extension)) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

    if (!strcasecmp(extension, ".mid")
            || !strcasecmp(extension, ".smf")
            || !strcasecmp(extension, ".imy")
            || !strcasecmp(extension, ".midi")
            || !strcasecmp(extension, ".xmf")
            || !strcasecmp(extension, ".rtttl")
            || !strcasecmp(extension, ".rtx")
            || !strcasecmp(extension, ".ota")
            || !strcasecmp(extension, ".mxmf")) {
        return HandleMIDI(path, &client);
    }

    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);

    int fd = open(path, O_RDONLY | O_LARGEFILE);
    status_t status;
    if (fd < 0) {
        // couldn't open it locally, maybe the media server can?
        status = mRetriever->setDataSource(path);
    } else {
        status = mRetriever->setDataSource(fd, 0, 0x7ffffffffffffffL);
        close(fd);
    }

    if (status) {
        return MEDIA_SCAN_RESULT_ERROR;
    }

    const char *value;
    if ((value = mRetriever->extractMetadata(
                    METADATA_KEY_MIMETYPE)) != NULL) {
        status = client.setMimeType(value);
        if (status) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }

    struct KeyMap {
        const char *tag;
        int key;
    };
    static const KeyMap kKeyMap[] = {
        { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
        { "discnumber", METADATA_KEY_DISC_NUMBER },
        { "album", METADATA_KEY_ALBUM },
        { "artist", METADATA_KEY_ARTIST },
        { "albumartist", METADATA_KEY_ALBUMARTIST },
        { "composer", METADATA_KEY_COMPOSER },
        { "genre", METADATA_KEY_GENRE },
        { "title", METADATA_KEY_TITLE },
        { "year", METADATA_KEY_YEAR },
        { "duration", METADATA_KEY_DURATION },
        { "writer", METADATA_KEY_WRITER },
        { "compilation", METADATA_KEY_COMPILATION },
        { "isdrm", METADATA_KEY_IS_DRM },
        { "width", METADATA_KEY_VIDEO_WIDTH },
        { "height", METADATA_KEY_VIDEO_HEIGHT },
    };
    static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);

    for (size_t i = 0; i < kNumEntries; ++i) {
        const char *value;
        if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
            status = client.addStringTag(kKeyMap[i].tag, value);
            if (status != OK) {
                return MEDIA_SCAN_RESULT_ERROR;
            }
        }
    }

    return MEDIA_SCAN_RESULT_OK;
}
示例#9
0
MediaScanResult MediaScanner::doProcessDirectoryEntry(
        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
        struct dirent* entry, char* fileSpot) {
    struct stat statbuf;
    const char* name = entry->d_name;
#ifndef ANDROID_DEFAULT_CODE
    ALOGV("doProcessDirectoryEntry: %s \n", path);
#endif 
    // ignore "." and ".."
    if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

    int nameLength = strlen(name);
    if (nameLength + 1 > pathRemaining) {
        // path too long!
        return MEDIA_SCAN_RESULT_SKIPPED;
    }
    strcpy(fileSpot, name);

    int type = entry->d_type;
    if (type == DT_UNKNOWN) {
        // If the type is unknown, stat() the file instead.
        // This is sometimes necessary when accessing NFS mounted filesystems, but
        // could be needed in other cases well.
        if (stat(path, &statbuf) == 0) {
            if (S_ISREG(statbuf.st_mode)) {
                type = DT_REG;
            } else if (S_ISDIR(statbuf.st_mode)) {
                type = DT_DIR;
            }
        } else {
            ALOGD("stat() failed for %s: %s", path, strerror(errno) );
        }
    }
    if (type == DT_DIR) {
        bool childNoMedia = noMedia;
        // set noMedia flag on directories with a name that starts with '.'
        // for example, the Mac ".Trashes" directory
        if (name[0] == '.')
            childNoMedia = true;

        // report the directory to the client
        if (stat(path, &statbuf) == 0) {
            status_t status = client.scanFile(path, statbuf.st_mtime, 0,
                    true /*isDirectory*/, childNoMedia);
            if (status) {
                return MEDIA_SCAN_RESULT_ERROR;
            }
        }

        // and now process its contents
        strcat(fileSpot, "/");
        MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1,
                client, childNoMedia);
        if (result == MEDIA_SCAN_RESULT_ERROR) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    } else if (type == DT_REG) {
        stat(path, &statbuf);
        status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size,
                false /*isDirectory*/, noMedia);
        if (status) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }

    return MEDIA_SCAN_RESULT_OK;
}
status_t StagefrightMediaScanner::processFile(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
    LOGV("processFile '%s'.", path);

    client.setLocale(locale());
    client.beginFile();

    const char *extension = strrchr(path, '.');

    if (!extension) {
        return UNKNOWN_ERROR;
    }

    if (!FileHasAcceptableExtension(extension)) {
        client.endFile();

        return UNKNOWN_ERROR;
    }

    if (!strcasecmp(extension, ".mid")
            || !strcasecmp(extension, ".smf")
            || !strcasecmp(extension, ".imy")
            || !strcasecmp(extension, ".midi")
            || !strcasecmp(extension, ".xmf")
            || !strcasecmp(extension, ".rtttl")
            || !strcasecmp(extension, ".rtx")
            || !strcasecmp(extension, ".ota")) {
        return HandleMIDI(path, &client);
    }

    if (!strcasecmp(extension, ".flac")) {
        return HandleFLAC(path, &client);
    }

    if (mRetriever->setDataSource(path) == OK
            && mRetriever->setMode(
                METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) {
        const char *value;
        if ((value = mRetriever->extractMetadata(
                        METADATA_KEY_MIMETYPE)) != NULL) {
            client.setMimeType(value);
        }

        struct KeyMap {
            const char *tag;
            int key;
        };
        static const KeyMap kKeyMap[] = {
            { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
            { "discnumber", METADATA_KEY_DISC_NUMBER },
            { "album", METADATA_KEY_ALBUM },
            { "artist", METADATA_KEY_ARTIST },
            { "albumartist", METADATA_KEY_ALBUMARTIST },
            { "composer", METADATA_KEY_COMPOSER },
            { "genre", METADATA_KEY_GENRE },
            { "title", METADATA_KEY_TITLE },
            { "year", METADATA_KEY_YEAR },
            { "duration", METADATA_KEY_DURATION },
            { "writer", METADATA_KEY_WRITER },
        };
        static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);

        for (size_t i = 0; i < kNumEntries; ++i) {
            const char *value;
            if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
                client.addStringTag(kKeyMap[i].tag, value);
            }
        }
    }

    client.endFile();

    return OK;
}
MediaScanResult StagefrightMediaScanner::processFileInternal(
        const char *path, const char *mimeType,
        MediaScannerClient &client) {
    const char *extension = strrchr(path, '.');

    if (!extension) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

    if (!FileHasAcceptableExtension(extension)) {
        return MEDIA_SCAN_RESULT_SKIPPED;
    }

#ifndef ANDROID_DEFAULT_CODE
#ifdef MTK_DRM_APP
    // add dcf meta data for dcf file
    // check extension first
    LOGV("processFileInternal() : the extension: %s", extension);
    bool isOMADrmDcf = false;
    if (0 == strcasecmp(extension, ".dcf")) {
        String8 tmp(path);
        DrmManagerClient* drmManagerClient = new DrmManagerClient();
        DrmMetadata* dcfMetadata = drmManagerClient->getMetadata(&tmp);

        if (dcfMetadata == NULL) {
            LOGW("scan: OMA DRM v1: failed to get drm metadata, not scanned into db.");
            delete drmManagerClient;
            client.setMimeType("bad mime type");
            return MEDIA_SCAN_RESULT_SKIPPED;
        }

        struct Map {
            const char* from;
            int to;
        };
        static const Map kMap[] = {
            {DrmMetaKey::META_KEY_IS_DRM,
                METADATA_KEY_IS_DRM}, // "is_drm"
            {DrmMetaKey::META_KEY_CONTENT_URI, 
                METADATA_KEY_DRM_CONTENT_URI},
            {DrmMetaKey::META_KEY_OFFSET,
                METADATA_KEY_DRM_OFFSET},
            {DrmMetaKey::META_KEY_DATALEN,
                METADATA_KEY_DRM_DATALEN},
            {DrmMetaKey::META_KEY_RIGHTS_ISSUER,
                METADATA_KEY_DRM_RIGHTS_ISSUER},
            {DrmMetaKey::META_KEY_CONTENT_NAME,
                METADATA_KEY_DRM_CONTENT_NAME},
            {DrmMetaKey::META_KEY_CONTENT_DESCRIPTION,
                METADATA_KEY_DRM_CONTENT_DES},
            {DrmMetaKey::META_KEY_CONTENT_VENDOR,
                METADATA_KEY_DRM_CONTENT_VENDOR},
            {DrmMetaKey::META_KEY_ICON_URI,
                METADATA_KEY_DRM_ICON_URI} ,
            {DrmMetaKey::META_KEY_METHOD,
                METADATA_KEY_DRM_METHOD},
            {DrmMetaKey::META_KEY_MIME,
                METADATA_KEY_DRM_MIME}
        };
        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);

        int action = Action::PLAY;
        String8 type;
        for (size_t i = 0; i < kNumMapEntries; ++i) {
            String8 value = dcfMetadata->get(String8(kMap[i].from));
            if (value.length() != 0)
            {
                if (kMap[i].to == METADATA_KEY_DRM_MIME) {
                    value = DrmMtkUtil::toCommonMime(value.string());
                    // not audio/video/image -> not scan into db
                    type.setTo(value.string(), 6);
                    if (0 != strcasecmp(type.string(), "audio/")
                        && 0 != strcasecmp(type.string(), "video/")
                        && 0 != strcasecmp(type.string(), "image/")) {
                        LOGW("scan: OMA DRM v1: invalid drm media file mime type[%s], not added into db.",
                                value.string());
                        delete dcfMetadata;
                        delete drmManagerClient;
                        client.setMimeType("bad mime type");
                        return MEDIA_SCAN_RESULT_SKIPPED;
                    }

                    client.setMimeType(value.string());
                    LOGD("scan: OMA DRM v1: drm original mime type[%s].",
                            value.string());

                    // determine the Action it shall used.
                    if ((0 == strcasecmp(type.string(), "audio/"))
                        || (0 == strcasecmp(type.string(), "video/"))) {
                        action = Action::PLAY;
                    } else if ((0 == strcasecmp(type.string(), "image/"))) {
                        action = Action::DISPLAY;
                    }
                }

                if (kMap[i].to == METADATA_KEY_IS_DRM) {
                    isOMADrmDcf = (value == String8("1"));
                }

                client.addStringTag(kMap[i].from, value.string());
                LOGD("scan: OMA DRM v1: client.addString tag[%s] value[%s].",
                        kMap[i].from, value.string());
            }
        }

        // if there's no valid rights for this file currently, just return OK
        // to make sure it can be scanned into db.
        if (isOMADrmDcf
            && RightsStatus::RIGHTS_VALID != drmManagerClient->checkRightsStatus(tmp, action)) {
            LOGD("scan: OMA DRM v1: current no valid rights, return OK so that it can be added into db.");
            delete dcfMetadata;
            delete drmManagerClient;
            return MEDIA_SCAN_RESULT_OK;
        }

        // when there's valid rights, should contine to add extra metadata
        LOGD("scan: OMA DRM v1: current valid rights, continue to add extra info.");
        delete dcfMetadata; dcfMetadata = NULL;
        delete drmManagerClient; drmManagerClient = NULL;

        // if picture then we need not to scan with extractors.
        if (isOMADrmDcf && 0 == strcasecmp(type.string(), "image/")) {
            LOGD("scan: OMA DRM v1: for DRM image we do not sniff with extractors.");
            return MEDIA_SCAN_RESULT_OK;
        }
    }
#endif
#endif

    if (!strcasecmp(extension, ".mid")
            || !strcasecmp(extension, ".smf")
            || !strcasecmp(extension, ".imy")
            || !strcasecmp(extension, ".midi")
            || !strcasecmp(extension, ".xmf")
            || !strcasecmp(extension, ".rtttl")
            || !strcasecmp(extension, ".rtx")
            || !strcasecmp(extension, ".ota")
            || !strcasecmp(extension, ".mxmf")) {
        return HandleMIDI(path, &client);
    }

    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);

    status_t status = mRetriever->setDataSource(path);
    if (status) {
#ifndef ANDROID_DEFAULT_CODE
         //if this still need on ICS
        // set mime type to "bad mime type" for unsupported format, otherwise the file will be included in Gallery/Music
        LOGE("processFile '%s' - not supported", path);
        client.setMimeType("bad mime type");
        return MEDIA_SCAN_RESULT_SKIPPED;
#else
        return MEDIA_SCAN_RESULT_ERROR;
#endif
    }

    const char *value;
    if ((value = mRetriever->extractMetadata(
                    METADATA_KEY_MIMETYPE)) != NULL) {
        status = client.setMimeType(value);
        if (status) {
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }

    struct KeyMap {
        const char *tag;
        int key;
    };
    static const KeyMap kKeyMap[] = {
        { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
        { "discnumber", METADATA_KEY_DISC_NUMBER },
        { "album", METADATA_KEY_ALBUM },
        { "artist", METADATA_KEY_ARTIST },
        { "albumartist", METADATA_KEY_ALBUMARTIST },
        { "composer", METADATA_KEY_COMPOSER },
        { "genre", METADATA_KEY_GENRE },
        { "title", METADATA_KEY_TITLE },
        { "year", METADATA_KEY_YEAR },
        { "duration", METADATA_KEY_DURATION },
        { "writer", METADATA_KEY_WRITER },
        { "compilation", METADATA_KEY_COMPILATION },
        { "isdrm", METADATA_KEY_IS_DRM }, // "isdrm"
#ifdef MTK_S3D_SUPPORT
        {"stereotype",METADATA_KEY_STEREO_3D}, //stereo 3d info
#endif
    };
    static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);

    for (size_t i = 0; i < kNumEntries; ++i) {
        const char *value;
        if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
#ifndef ANDROID_DEFAULT_CODE
#ifdef MTK_DRM_APP
            if (kKeyMap[i].key == METADATA_KEY_IS_DRM) {
                if (isOMADrmDcf) {
                    LOGD("set METADATA_KEY_IS_DRM to 1 for OMA DRM v1.");
                    value = "1";
                }
            }
#endif
#endif
            status = client.addStringTag(kKeyMap[i].tag, value);
            LOGD("processFileInternal() : client.addString tag[%s] value[%s]",
                        kKeyMap[i].tag, value);
            if (status != OK) {
                return MEDIA_SCAN_RESULT_ERROR;
            }
#ifndef ANDROID_DEFAULT_CODE
            if (kKeyMap[i].key == METADATA_KEY_DURATION) {
                if (!strcasecmp(extension, ".mp3")
                        || !strcasecmp(extension, ".aac")
                        || !strcasecmp(extension, ".amr")
                        || !strcasecmp(extension, ".awb")) {
                    client.addStringTag("isAccurateDuration", "0");
                } else if (!strcasecmp(extension, ".wav")
                        || !strcasecmp(extension, ".ogg")
                        || !strcasecmp(extension, ".oga")) {
                    client.addStringTag("isAccurateDuration", "1");
                }
            }
#endif // ANDROID_DEFAULT_CODE
        }
    }
#ifndef ANDROID_DEFAULT_CODE
	LOGD("processFileInternal '%s' - return OK", path);
#endif
    return MEDIA_SCAN_RESULT_OK;
}
MediaScanResult MediaScanner::doProcessDirectory(
        char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
#ifndef ANDROID_DEFAULT_CODE
    LOGV("doProcessDirectory %s extensions: %s\n", path, extensions);
#endif   

    // place to copy file or directory name
    char* fileSpot = path + strlen(path);
    struct dirent* entry;

    if (shouldSkipDirectory(path)) {
      LOGD("Skipping: %s", path);
      return MEDIA_SCAN_RESULT_OK;
    }

    // Treat all files as non-media in directories that contain a  ".nomedia" file
    if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
        strcpy(fileSpot, ".nomedia");
        if (access(path, F_OK) == 0) {
            LOGV("found .nomedia, setting noMedia flag\n");
            noMedia = true;
        }

        // restore path
        fileSpot[0] = 0;
    }

    DIR* dir = opendir(path);
    if (!dir) {
        LOGW("Error opening directory '%s', skipping: %s.", path, strerror(errno));
        return MEDIA_SCAN_RESULT_SKIPPED;
    }
#ifndef ANDROID_DEFAULT_CODE
    //--start--find the best file to set default ringtone.
    static bool isSetRingtone = false;
    static bool isSetNotification = false;
    static bool isSetAlarm = false;
    bool needFindFile = false;
    if (isSetRingtone == false) {
        if (strcmp(path, "/system/media/audio/ringtones/") == 0) {
            needFindFile = true;
            isSetRingtone = true;
        }
    }
    if (isSetNotification == false) {
        if (strcmp(path, "/system/media/audio/notifications/") == 0) {
            needFindFile = true;
            isSetNotification = true;
        }
    }
    if (isSetAlarm == false) {
            if (strcmp(path, "/system/media/audio/alarms/") == 0) {
                needFindFile = true;
                isSetAlarm = true;
            }
        }
    if (needFindFile) {
        char* findFile = 0;
        while ((entry = readdir(dir))) {
            const char* name = entry->d_name;
            // ignore "." and ".."
            if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
                continue;
            }
            int type = entry->d_type;
            if (type == DT_UNKNOWN) {
                // If the type is unknown, stat() the file instead.
                // This is sometimes necessary when accessing NFS mounted filesystems, but
                // could be needed in other cases well.
                struct stat statbuf;
                if (stat(path, &statbuf) == 0) {
                    if (S_ISREG(statbuf.st_mode)) {
                        type = DT_REG;
                    } else if (S_ISDIR(statbuf.st_mode)) {
                        type = DT_DIR;
                    }
                } else {
                    LOGD("stat() failed for %s: %s", path, strerror(errno) );
                }
            }
            if (type == DT_REG) {
                int nameLength = strlen(name);
                if (nameLength > pathRemaining) {
                    // path too long!
                    continue;
                }
                int pathLength = strlen(path);
                strcpy(fileSpot, name);
                //if (fileMatchesExtension(path, extensions)) {
                    if (findFile == 0) {
                        findFile = new char[pathLength + pathRemaining];
                        strcpy(findFile, path);
                    } else {
                        if (strcmp(path, findFile) < 0) {
                            strcpy(findFile, path);
                        }
                    }
               // }
            }
        }
        if (findFile != 0) {
            struct stat statbuf;
            stat(findFile, &statbuf);
            if (statbuf.st_size > 0) {
                LOGD("find the default audio file = %s", findFile);
               // client.scanFile(findFile, statbuf.st_mtime, statbuf.st_size);
               //need audio owner check
               client.scanFile(findFile, statbuf.st_mtime, statbuf.st_size,false,false);
            }
            delete findFile;
            findFile = 0;
           // if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
        } else {
            LOGD("Can not get the best file for ringtone");
        }
        closedir(dir);
        //restore the path
        fileSpot[0] = 0;
        //reopen the dir for android's default deal.
        dir = opendir(path);
        if (!dir) {
            LOGD("opendir %s failed, errno: %d", path, errno);
            return MEDIA_SCAN_RESULT_ERROR;
        }
    }
    //--end--find the best file to set default ringtone.
#endif


    MediaScanResult result = MEDIA_SCAN_RESULT_OK;
    while ((entry = readdir(dir))) {
        if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot)
                == MEDIA_SCAN_RESULT_ERROR) {
            result = MEDIA_SCAN_RESULT_ERROR;
            break;
        }
    }
    closedir(dir);
    return result;
}
示例#13
0
status_t MediaScanner::doProcessDirectory(
        char *path, int pathRemaining, const char *extensions,
        MediaScannerClient &client, ExceptionCheck exceptionCheck,
        void *exceptionEnv) {
    // place to copy file or directory name
    char* fileSpot = path + strlen(path);
    struct dirent* entry;
    char* tempPathBuffer = NULL;
    char* pathBuffer = NULL;
    DIR* dir = NULL;
    int pathLength = strlen(path);
    if (pathLength >= PATH_MAX) {
        goto failure;
    }
    pathBuffer = (char *)malloc(PATH_MAX + 1);
    tempPathBuffer = (char *)malloc(PATH_MAX + 1);
    if (!pathBuffer || !tempPathBuffer) {
        goto failure;
    }

    strcpy(pathBuffer, path);
    // ignore directories that contain a  ".nomedia" file
    if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
        strcpy(fileSpot, ".nomedia");
        if (access(path, F_OK) == 0) {
            LOGD("found .nomedia, skipping directory\n");
            fileSpot[0] = 0;
            client.addNoMediaFolder(path);
            goto success;
        }
        // restore path
        fileSpot[0] = 0;
    }

    dir = opendir(path);
    if (!dir) {
        LOGD("opendir %s failed, errno: %d", path, errno);
        goto failure;
    }

    while ((entry = readdir(dir))) {
        const char* name = entry->d_name;

        // ignore "." and ".."
        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
            continue;
        }

        int type = entry->d_type;
        if (type == DT_UNKNOWN) {
            // If the type is unknown, stat() the file instead.
            // This is sometimes necessary when accessing NFS mounted filesystems, but
            // could be needed in other cases well.
            struct stat statbuf;
            int tempPathLength = strlen(pathBuffer) + strlen(name);
            if (tempPathLength >= PATH_MAX) {
                goto failure;
            }

            strcpy(tempPathBuffer, pathBuffer);
            strcat(tempPathBuffer, name);
            if (stat(tempPathBuffer, &statbuf) == 0) {
                if (S_ISREG(statbuf.st_mode)) {
                    type = DT_REG;
                } else if (S_ISDIR(statbuf.st_mode)) {
                    type = DT_DIR;
                }
            } else {
                LOGD("stat() failed for %s %s: %s", path, name, strerror(errno) );
            }

        }
        if (type == DT_REG || type == DT_DIR) {
            int nameLength = strlen(name);
            bool isDirectory = (type == DT_DIR);

            if (nameLength > pathRemaining || (isDirectory && nameLength + 1 > pathRemaining)) {
                // path too long!
                continue;
            }

            strcpy(fileSpot, name);
            if (isDirectory) {
                // ignore directories with a name that starts with '.'
                // for example, the Mac ".Trashes" directory
                if (name[0] == '.') continue;

                strcat(fileSpot, "/");
                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, extensions, client, exceptionCheck, exceptionEnv);
                if (err) {
                    // pass exceptions up - ignore other errors
                    if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
                    LOGE("Error processing '%s' - skipping\n", path);
                    continue;
                }
            } else if (fileMatchesExtension(path, extensions)) {
                struct stat statbuf;
                stat(path, &statbuf);
                if (statbuf.st_size > 0) {
                    client.scanFile(path, statbuf.st_mtime, statbuf.st_size);
                }
                if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
            }
        }
    }
    closedir(dir);
success:
    free(pathBuffer);
    free(tempPathBuffer);
    return OK;
failure:
    free(pathBuffer);
    free(tempPathBuffer);
    closedir(dir);
    return -1;
}
示例#14
0
    static PVMFStatus parseMP3(const char *filename,MediaScannerClient& client) {
        PVID3ParCom pvId3Param;
        PVFile fileHandle;
        Oscl_FileServer iFs;
        uint32 duration;
        //LOGD("c---> filename 好的 = %s", filename);
        if (iFs.Connect() != 0) {
            LOGD("=======iFs.Connect failed========>\n");
            return PVMFFailure;
        }

        oscl_wchar output[MAX_BUFF_SIZE];
        oscl_UTF8ToUnicode((const char *) filename, oscl_strlen((const char *) filename),
                           (oscl_wchar *) output, MAX_BUFF_SIZE);
        if (0 !=
            fileHandle.Open((oscl_wchar *) output, Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
                            iFs)) {
            //LOGE("Could not open the input file for reading(Test: parse id3).\n");
            return PVMFFailure;
        }

        fileHandle.Seek(0, Oscl_File::SEEKSET);
        pvId3Param.ParseID3Tag(&fileHandle);
        fileHandle.Close();
        iFs.Close();

        //Get the frames information from ID3 library
        PvmiKvpSharedPtrVector framevector;
        pvId3Param.GetID3Frames(framevector);

        uint32 num_frames = framevector.size();

        for (uint32 i = 0; i < num_frames; i++) {
            const char *key = framevector[i]->key;
            bool isUtf8 = false;
            bool isIso88591 = false;

            // type should follow first semicolon
            const char *type = strchr(key, ';');
            if (type == NULL) continue;
            type++;

            char tracknumkeybuf[100];
            if (strncmp(key, "track-info/track-number;", 24) == 0) {
                // Java expects the track number key to be called "tracknumber", so
                // construct a temporary one here.
                snprintf(tracknumkeybuf, sizeof(tracknumkeybuf), "tracknumber;%s", type);
                key = tracknumkeybuf;
            }

            const char *value = framevector[i]->value.pChar_value;

            // KVP_VALTYPE_UTF8_CHAR check must be first, since KVP_VALTYPE_ISO88591_CHAR
            // is a substring of KVP_VALTYPE_UTF8_CHAR.
            // Similarly, KVP_VALTYPE_UTF16BE_WCHAR must be checked before KVP_VALTYPE_UTF16_WCHAR
            if (oscl_strncmp(type, KVP_VALTYPE_UTF8_CHAR, KVP_VALTYPE_UTF8_CHAR_LEN) == 0) {
                isUtf8 = true;
            } else if (
                    oscl_strncmp(type, KVP_VALTYPE_ISO88591_CHAR, KVP_VALTYPE_ISO88591_CHAR_LEN) ==
                    0) {
                isIso88591 = true;
            }

            if (isUtf8) {
                // validate to make sure it is legal utf8
                uint32 valid_chars;
                if (oscl_str_is_valid_utf8((const uint8 *) value, valid_chars)) {
                    // utf8 can be passed through directly
                    //LOGD("c---> key(utf8) = %s  ; value = %s", key, value);
                    if (!client.handleStringTag(key, value)) goto failure;
                } else {
                    // treat as ISO-8859-1 if UTF-8 fails
                    isIso88591 = true;
                }
            }

            if (isIso88591) {
                size_t iInLen = strlen(value);
                char sOutBuf[100];
                size_t iOutLen = 100;
                memset(sOutBuf, 0x00, 100);
                ChangeCode("GBK", "UTF-8", value, &iInLen, sOutBuf, &iOutLen);
                //LOGD("c---> key(gbk) = %s  ; value = %s", key, sOutBuf);
                if (!client.handleStringTag(key, sOutBuf)) goto failure;
            }

            // treat it as iso-8859-1 and our native encoding detection will try to
            // figure out what it is
/*            if (isIso88591) {
                // convert ISO-8859-1 to utf8, worse case is 2x inflation
                const unsigned char *src = (const unsigned char *) value;
                char *temp = (char *) alloca(strlen(value) * 2 + 1);
                if (temp) {
                    char *dest = temp;
                    unsigned int uch;
                    while ((uch = *src++) != 0) {
                        if (uch & 0x80) {
                            *dest++ = (uch >> 6) | 0xc0;
                            *dest++ = (uch & 0x3f) | 0x80;
                        } else *dest++ = uch;
                    }
                    *dest = 0;
                    LOGD("c---> key(iso) = %s  ; value = %s", key, temp);
                    //if (!client.addStringTag(key, temp)) goto failure;
                }
            }*/

            // not UTF-8 or ISO-8859-1, try wide char formats
            if (!isUtf8 && !isIso88591 &&
                (oscl_strncmp(type, KVP_VALTYPE_UTF16BE_WCHAR, KVP_VALTYPE_UTF16BE_WCHAR_LEN) ==
                 0 ||
                 oscl_strncmp(type, KVP_VALTYPE_UTF16_WCHAR, KVP_VALTYPE_UTF16_WCHAR_LEN) == 0)) {
                // convert wchar to utf8
                // the id3parcom library has already taken care of byteswapping
                const oscl_wchar *src = framevector[i]->value.pWChar_value;
                int srcLen = oscl_strlen(src);
                // worse case is 3 bytes per character, plus zero termination
                int destLen = srcLen * 3 + 1;
                char *dest = (char *) alloca(destLen);

                if (oscl_UnicodeToUTF8(src, oscl_strlen(src), dest, destLen) > 0) {
                    //LOGD("c---> key(!utf8 && !iso) = %s  ; value = %s", key, dest);
                    if (!client.handleStringTag(key, dest)) goto failure;
                }
            } else if (oscl_strncmp(type, KVP_VALTYPE_UINT32, KVP_VALTYPE_UINT32_LEN) == 0) {
                char temp[20];
                snprintf(temp, sizeof(temp), "%d", (int) framevector[i]->value.uint32_value);
                //LOGD("c---> key() = %s  ; value = %s", key, temp);
                if (!client.handleStringTag(key, temp)) goto failure;
            } else {
                //LOGE("unknown tag type %s for key %s\n", type, key);
            }
        }

        // extract non-ID3 properties below
        {
            OSCL_wHeapString<OsclMemAllocator> mp3filename(output);
            MP3ErrorType err;
            IMpeg3File mp3File(mp3filename, err);
            if (err != MP3_SUCCESS) {
                //LOGE("IMpeg3File constructor returned %d for %s\n", err, filename);
                return err;
            }
            err = mp3File.ParseMp3File();
            if (err != MP3_SUCCESS) {
                //LOGE("IMpeg3File::ParseMp3File returned %d for %s\n", err, filename);
                return err;
            }

            char buffer[20];
            duration = mp3File.GetDuration();
            sprintf(buffer, "%d", duration);
            LOGD("c---> duration = %s", "duration");
            //if (!client.addStringTag("duration", buffer)) goto failure;
        }

        return PVMFSuccess;

        failure:
        return PVMFFailure;
    }
static PVMFStatus parseMP3(const char *filename, MediaScannerClient& client)
{
    PVID3ParCom pvId3Param;
    PVFile fileHandle;
    Oscl_FileServer iFs;
    uint32 duration;

    if (iFs.Connect() != 0)
    {
        LOGE("iFs.Connect failed\n");
        return PVMFFailure;
    }

    oscl_wchar output[MAX_BUFF_SIZE];
    oscl_UTF8ToUnicode((const char *)filename, oscl_strlen((const char *)filename), (oscl_wchar *)output, MAX_BUFF_SIZE);
    if (0 != fileHandle.Open((oscl_wchar *)output, Oscl_File::MODE_READ | Oscl_File::MODE_BINARY, iFs) )
    {
        LOGE("Could not open the input file for reading(Test: parse id3).\n");
        return PVMFFailure;
    }

    fileHandle.Seek(0, Oscl_File::SEEKSET);
    pvId3Param.ParseID3Tag(&fileHandle);
    fileHandle.Close();
    iFs.Close();

    //Get the frames information from ID3 library
    PvmiKvpSharedPtrVector framevector;
    pvId3Param.GetID3Frames(framevector);

    uint32 num_frames = framevector.size();

    for (uint32 i = 0; i < num_frames;i++)
    {
        const char* key = framevector[i]->key;
        bool validUtf8 = true;

        // type should follow first semicolon
        const char* type = strchr(key, ';') + 1;
        if (type == 0) continue;
        
        const char* value = framevector[i]->value.pChar_value;

        // KVP_VALTYPE_UTF8_CHAR check must be first, since KVP_VALTYPE_ISO88591_CHAR 
        // is a substring of KVP_VALTYPE_UTF8_CHAR.
        // Similarly, KVP_VALTYPE_UTF16BE_WCHAR must be checked before KVP_VALTYPE_UTF16_WCHAR
        if (oscl_strncmp(type, KVP_VALTYPE_UTF8_CHAR, KVP_VALTYPE_UTF8_CHAR_LEN) == 0) {
            // utf8 can be passed through directly
            // but first validate to make sure it is legal utf8
            uint32 valid_chars;
            validUtf8 = oscl_str_is_valid_utf8((const uint8 *)value, valid_chars);
            if (validUtf8 && !client.handleStringTag(key, value)) goto failure;
        } 

        // if the value is not valid utf8, then we will treat it as iso-8859-1 
        // and our native encoding detection will try to figure out what it is
        if (oscl_strncmp(type, KVP_VALTYPE_ISO88591_CHAR, KVP_VALTYPE_ISO88591_CHAR_LEN) == 0 
                || !validUtf8) {
            // iso-8859-1
            // convert to utf8
            // worse case is 2x inflation
            const unsigned char* src = (const unsigned char *)value;
            char* temp = (char *)alloca(strlen(value) * 2 + 1);
            if (temp) {
                char* dest = temp;
                unsigned int uch;
                while ((uch = *src++) != 0) {
                    if (uch & 0x80) {
                        *dest++ = (uch >> 6) | 0xc0;
                        *dest++ = (uch & 0x3f) | 0x80;
                    } else *dest++ = uch;
                }
                *dest = 0;
                if (!client.addStringTag(key, temp)) goto failure;           
            }
        } else if (oscl_strncmp(type, KVP_VALTYPE_UTF16BE_WCHAR, KVP_VALTYPE_UTF16BE_WCHAR_LEN) == 0 ||