Show/hide notification area icon when starting/stopping playback.
[maemo-rb.git] / android / src / org / rockbox / RockboxPCM.java
blobf2568d840611d696ee0fe986632db047f9d6e250
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Thomas Martitz
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 package org.rockbox;
24 import android.media.AudioFormat;
25 import android.media.AudioManager;
26 import android.media.AudioTrack;
27 import android.util.Log;
29 public class RockboxPCM extends AudioTrack
31 byte[] raw_data;
33 private void LOG(CharSequence text)
35 Log.d("RockboxBootloader", (String) text);
38 public RockboxPCM()
40 super(AudioManager.STREAM_MUSIC,
41 44100,
42 /* should be CHANNEL_OUT_STEREO in 2.0 and above */
43 AudioFormat.CHANNEL_CONFIGURATION_STEREO,
44 AudioFormat.ENCODING_PCM_16BIT,
45 24<<10,
46 AudioTrack.MODE_STREAM);
47 int buf_len = 24<<10;
49 raw_data = new byte[buf_len*2];
50 for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00;
51 /* fill with silence */
52 write(raw_data, 0, raw_data.length);
53 if (getState() == AudioTrack.STATE_INITIALIZED)
55 if (setNotificationMarkerPosition(bytes2frames(buf_len*2)/4) != AudioTrack.SUCCESS)
56 LOG("setNotificationMarkerPosition Error");
57 setPlaybackPositionUpdateListener(new PCMListener(buf_len*2));
61 int bytes2frames(int bytes) {
62 /* 1 sample is 2 bytes, 2 samples are 1 frame */
63 return (bytes/4);
66 int frames2bytes(int frames) {
67 /* 1 frame is 2 samples, 1 sample is 2 bytes */
68 return (frames*4);
71 @SuppressWarnings("unused")
72 private void play_pause(boolean pause) {
73 LOG("play_pause()");
74 if (pause)
75 pause();
76 else
78 if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
80 for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00;
81 LOG("Writing silence");
82 /* fill with silence */
83 write(raw_data, 0, raw_data.length);
84 RockboxService.startForeground();
86 play();
88 LOG("play_pause() return");
91 @Override
92 public void stop() throws IllegalStateException
94 super.stop();
95 RockboxService.stopForeground();
98 @SuppressWarnings("unused")
99 private void set_volume(int volume)
101 /* volume comes from 0..-990 from Rockbox */
102 /* TODO volume is in dB, but this code acts as if it were in %, convert? */
103 float fvolume;
104 /* special case min and max volume to not suffer from floating point accuracy */
105 if (volume == 0)
106 fvolume = 1.0f;
107 else if (volume == -990)
108 fvolume = 0.0f;
109 else
110 fvolume = (volume + 990)/990.0f;
111 setStereoVolume(fvolume, fvolume);
114 public native void pcmSamplesToByteArray(byte[] dest);
116 private class PCMListener implements OnPlaybackPositionUpdateListener {
117 int max_len;
118 byte[] buf;
119 public PCMListener(int len) {
120 max_len = len;
121 buf = new byte[len/2];
123 @Override
124 public void onMarkerReached(AudioTrack track) {
125 // push new data to the hardware
126 int result = 1;
127 pcmSamplesToByteArray(buf);
128 //LOG("Trying to write " + buf.length + " bytes");
129 result = track.write(buf, 0, buf.length);
130 if (result > 0)
132 //LOG(result + " bytes written");
133 track.setPlaybackPositionUpdateListener(this);
134 track.setNotificationMarkerPosition(bytes2frames(max_len)/4);
135 switch(track.getPlayState())
137 case AudioTrack.PLAYSTATE_PLAYING:
138 //LOG("State PLAYING");
139 break;
140 case AudioTrack.PLAYSTATE_PAUSED:
141 LOG("State PAUSED");
142 break;
143 case AudioTrack.PLAYSTATE_STOPPED:
144 LOG("State STOPPED");
145 break;
148 else
150 LOG("Error in onMarkerReached");
151 track.stop();
155 @Override
156 public void onPeriodicNotification(AudioTrack track) {
157 // TODO Auto-generated method stub