1/*
2 * Copyright (C) 2008 Esmertec AG.
3 * Copyright (C) 2008 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mms.model;
19
20import java.util.HashMap;
21import java.util.Map;
22
23import org.w3c.dom.events.Event;
24
25import android.content.ContentResolver;
26import android.content.Context;
27import android.database.Cursor;
28import android.database.sqlite.SqliteWrapper;
29import android.net.Uri;
30import android.provider.MediaStore.Audio;
31import android.provider.Telephony.Mms.Part;
32import android.text.TextUtils;
33import android.util.Log;
34
35import com.android.mms.ContentRestrictionException;
36import com.android.mms.dom.events.EventImpl;
37import com.android.mms.dom.smil.SmilMediaElementImpl;
38import com.google.android.mms.MmsException;
39
40public class AudioModel extends MediaModel {
41    private static final String TAG = MediaModel.TAG;
42    private static final boolean DEBUG = false;
43    private static final boolean LOCAL_LOGV = false;
44
45    private final HashMap<String, String> mExtras;
46
47    public AudioModel(Context context, Uri uri) throws MmsException {
48        this(context, null, null, uri);
49        initModelFromUri(uri);
50        checkContentRestriction();
51    }
52
53    public AudioModel(Context context, String contentType, String src, Uri uri) throws MmsException {
54        super(context, SmilHelper.ELEMENT_TAG_AUDIO, contentType, src, uri);
55        mExtras = new HashMap<String, String>();
56    }
57
58    private void initModelFromUri(Uri uri) throws MmsException {
59        ContentResolver cr = mContext.getContentResolver();
60        Cursor c = SqliteWrapper.query(mContext, cr, uri, null, null, null, null);
61
62        if (c != null) {
63            try {
64                if (c.moveToFirst()) {
65                    String path;
66                    boolean isFromMms = isMmsUri(uri);
67
68                    // FIXME We suppose that there should be only two sources
69                    // of the audio, one is the media store, the other is
70                    // our MMS database.
71                    if (isFromMms) {
72                        path = c.getString(c.getColumnIndexOrThrow(Part._DATA));
73                        mContentType = c.getString(c.getColumnIndexOrThrow(Part.CONTENT_TYPE));
74                    } else {
75                        path = c.getString(c.getColumnIndexOrThrow(Audio.Media.DATA));
76                        mContentType = c.getString(c.getColumnIndexOrThrow(
77                                Audio.Media.MIME_TYPE));
78                        // Get more extras information which would be useful
79                        // to the user.
80                        String album = c.getString(c.getColumnIndexOrThrow("album"));
81                        if (!TextUtils.isEmpty(album)) {
82                            mExtras.put("album", album);
83                        }
84
85                        String artist = c.getString(c.getColumnIndexOrThrow("artist"));
86                        if (!TextUtils.isEmpty(artist)) {
87                            mExtras.put("artist", artist);
88                        }
89                    }
90                    mSrc = path.substring(path.lastIndexOf('/') + 1);
91
92                    if (TextUtils.isEmpty(mContentType)) {
93                        throw new MmsException("Type of media is unknown.");
94                    }
95
96                    if (LOCAL_LOGV) {
97                        Log.v(TAG, "New AudioModel created:"
98                                + " mSrc=" + mSrc
99                                + " mContentType=" + mContentType
100                                + " mUri=" + uri
101                                + " mExtras=" + mExtras);
102                    }
103                } else {
104                    throw new MmsException("Nothing found: " + uri);
105                }
106            } finally {
107                c.close();
108            }
109        } else {
110            throw new MmsException("Bad URI: " + uri);
111        }
112
113        initMediaDuration();
114    }
115
116    public void stop() {
117        appendAction(MediaAction.STOP);
118        notifyModelChanged(false);
119    }
120
121    public void handleEvent(Event evt) {
122        String evtType = evt.getType();
123        if (LOCAL_LOGV) {
124            Log.v(TAG, "Handling event: " + evtType + " on " + this);
125        }
126
127        MediaAction action = MediaAction.NO_ACTIVE_ACTION;
128        if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_START_EVENT)) {
129            action = MediaAction.START;
130            // if the Music player app is playing audio, we should pause that so it won't
131            // interfere with us playing audio here.
132            pauseMusicPlayer();
133        } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_END_EVENT)) {
134            action = MediaAction.STOP;
135        } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_PAUSE_EVENT)) {
136            action = MediaAction.PAUSE;
137        } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_SEEK_EVENT)) {
138            action = MediaAction.SEEK;
139            mSeekTo = ((EventImpl) evt).getSeekTo();
140        }
141
142        appendAction(action);
143        notifyModelChanged(false);
144    }
145
146    public Map<String, ?> getExtras() {
147        return mExtras;
148    }
149
150    protected void checkContentRestriction() throws ContentRestrictionException {
151        ContentRestriction cr = ContentRestrictionFactory.getContentRestriction();
152        cr.checkAudioContentType(mContentType);
153    }
154
155    @Override
156    protected boolean isPlayable() {
157        return true;
158    }
159}
160