172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.model;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.HashMap;
21d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport java.util.Map;
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport org.w3c.dom.events.Event;
2472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
28d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.database.sqlite.SqliteWrapper;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.MediaStore.Audio;
31f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms.Part;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
35d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.ContentRestrictionException;
36d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.dom.events.EventImpl;
37d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.dom.smil.SmilMediaElementImpl;
38d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.MmsException;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class AudioModel extends MediaModel {
417fa61cafe50deb74beb0819bdf52128239d50201Wei Huang    private static final String TAG = MediaModel.TAG;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean DEBUG = false;
43150c4179995cc0a75f934ef194372f9295957ca2Joe Onorato    private static final boolean LOCAL_LOGV = false;
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final HashMap<String, String> mExtras;
4672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public AudioModel(Context context, Uri uri) throws MmsException {
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        this(context, null, null, uri);
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        initModelFromUri(uri);
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        checkContentRestriction();
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public AudioModel(Context context, String contentType, String src, Uri uri) throws MmsException {
5472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super(context, SmilHelper.ELEMENT_TAG_AUDIO, contentType, src, uri);
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mExtras = new HashMap<String, String>();
5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void initModelFromUri(Uri uri) throws MmsException {
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentResolver cr = mContext.getContentResolver();
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Cursor c = SqliteWrapper.query(mContext, cr, uri, null, null, null, null);
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (c != null) {
6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            try {
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (c.moveToFirst()) {
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    String path;
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    boolean isFromMms = isMmsUri(uri);
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // FIXME We suppose that there should be only two sources
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // of the audio, one is the media store, the other is
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // our MMS database.
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (isFromMms) {
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        path = c.getString(c.getColumnIndexOrThrow(Part._DATA));
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        mContentType = c.getString(c.getColumnIndexOrThrow(Part.CONTENT_TYPE));
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    } else {
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        path = c.getString(c.getColumnIndexOrThrow(Audio.Media.DATA));
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        mContentType = c.getString(c.getColumnIndexOrThrow(
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                Audio.Media.MIME_TYPE));
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        // Get more extras information which would be useful
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        // to the user.
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        String album = c.getString(c.getColumnIndexOrThrow("album"));
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (!TextUtils.isEmpty(album)) {
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            mExtras.put("album", album);
8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        String artist = c.getString(c.getColumnIndexOrThrow("artist"));
8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (!TextUtils.isEmpty(artist)) {
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            mExtras.put("artist", artist);
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mSrc = path.substring(path.lastIndexOf('/') + 1);
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (TextUtils.isEmpty(mContentType)) {
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        throw new MmsException("Type of media is unknown.");
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    if (LOCAL_LOGV) {
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.v(TAG, "New AudioModel created:"
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                + " mSrc=" + mSrc
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                + " mContentType=" + mContentType
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                + " mUri=" + uri
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                + " mExtras=" + mExtras);
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                } else {
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    throw new MmsException("Nothing found: " + uri);
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } finally {
10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                c.close();
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            throw new MmsException("Bad URI: " + uri);
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        initMediaDuration();
11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void stop() {
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        appendAction(MediaAction.STOP);
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        notifyModelChanged(false);
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void handleEvent(Event evt) {
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String evtType = evt.getType();
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (LOCAL_LOGV) {
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "Handling event: " + evtType + " on " + this);
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        MediaAction action = MediaAction.NO_ACTIVE_ACTION;
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_START_EVENT)) {
12972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            action = MediaAction.START;
1307fa61cafe50deb74beb0819bdf52128239d50201Wei Huang            // if the Music player app is playing audio, we should pause that so it won't
1317fa61cafe50deb74beb0819bdf52128239d50201Wei Huang            // interfere with us playing audio here.
1327fa61cafe50deb74beb0819bdf52128239d50201Wei Huang            pauseMusicPlayer();
13372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_END_EVENT)) {
13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            action = MediaAction.STOP;
13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_PAUSE_EVENT)) {
13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            action = MediaAction.PAUSE;
13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_SEEK_EVENT)) {
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            action = MediaAction.SEEK;
1391931fe06a209e2ed3497db0248eec31dbe95d352Jesse Wilson            mSeekTo = ((EventImpl) evt).getSeekTo();
14072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
14172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
14272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        appendAction(action);
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        notifyModelChanged(false);
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
14572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
14672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public Map<String, ?> getExtras() {
14772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return mExtras;
14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
14972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void checkContentRestriction() throws ContentRestrictionException {
15172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContentRestriction cr = ContentRestrictionFactory.getContentRestriction();
15272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        cr.checkAudioContentType(mContentType);
15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected boolean isPlayable() {
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return true;
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
160