Home | History | Annotate | Download | only in media
      1 /*
      2 **
      3 ** Copyright 2013, 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 
     18 package com.android.commands.media;
     19 
     20 import android.app.PendingIntent;
     21 import android.content.Context;
     22 import android.graphics.Bitmap;
     23 import android.media.IAudioService;
     24 import android.media.IRemoteControlDisplay;
     25 import android.os.Bundle;
     26 import android.os.RemoteException;
     27 import android.os.ServiceManager;
     28 import android.os.SystemClock;
     29 import android.util.AndroidException;
     30 import android.view.InputDevice;
     31 import android.view.KeyCharacterMap;
     32 import android.view.KeyEvent;
     33 import com.android.internal.os.BaseCommand;
     34 
     35 import java.io.BufferedReader;
     36 import java.io.IOException;
     37 import java.io.InputStreamReader;
     38 import java.io.PrintStream;
     39 
     40 public class Media extends BaseCommand {
     41 
     42     private IAudioService mAudioService;
     43 
     44     /**
     45      * Command-line entry point.
     46      *
     47      * @param args The command-line arguments
     48      */
     49     public static void main(String[] args) {
     50         (new Media()).run(args);
     51     }
     52 
     53     public void onShowUsage(PrintStream out) {
     54         out.println(
     55                 "usage: media [subcommand] [options]\n" +
     56                 "       media dispatch KEY\n" +
     57                 "       media remote-display\n" +
     58                 "\n" +
     59                 "media dispatch: dispatch a media key to the current media client.\n" +
     60                 "                KEY may be: play, pause, play-pause, mute, headsethook,\n" +
     61                 "                stop, next, previous, rewind, recordm fast-forword.\n" +
     62                 "media remote-display: monitor remote display updates.\n"
     63         );
     64     }
     65 
     66     public void onRun() throws Exception {
     67         mAudioService = IAudioService.Stub.asInterface(ServiceManager.checkService(
     68                 Context.AUDIO_SERVICE));
     69         if (mAudioService == null) {
     70             System.err.println(NO_SYSTEM_ERROR_CODE);
     71             throw new AndroidException("Can't connect to audio service; is the system running?");
     72         }
     73 
     74         String op = nextArgRequired();
     75 
     76         if (op.equals("dispatch")) {
     77             runDispatch();
     78         } else if (op.equals("remote-display")) {
     79             runRemoteDisplay();
     80         } else {
     81             showError("Error: unknown command '" + op + "'");
     82             return;
     83         }
     84     }
     85 
     86     private void sendMediaKey(KeyEvent event) {
     87         try {
     88             mAudioService.dispatchMediaKeyEvent(event);
     89         } catch (RemoteException e) {
     90         }
     91     }
     92 
     93     private void runDispatch() throws Exception {
     94         String cmd = nextArgRequired();
     95         int keycode;
     96         if ("play".equals(cmd)) {
     97             keycode = KeyEvent.KEYCODE_MEDIA_PLAY;
     98         } else if ("pause".equals(cmd)) {
     99             keycode = KeyEvent.KEYCODE_MEDIA_PAUSE;
    100         } else if ("play-pause".equals(cmd)) {
    101             keycode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
    102         } else if ("mute".equals(cmd)) {
    103             keycode = KeyEvent.KEYCODE_MUTE;
    104         } else if ("headsethook".equals(cmd)) {
    105             keycode = KeyEvent.KEYCODE_HEADSETHOOK;
    106         } else if ("stop".equals(cmd)) {
    107             keycode = KeyEvent.KEYCODE_MEDIA_STOP;
    108         } else if ("next".equals(cmd)) {
    109             keycode = KeyEvent.KEYCODE_MEDIA_NEXT;
    110         } else if ("previous".equals(cmd)) {
    111             keycode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
    112         } else if ("rewind".equals(cmd)) {
    113             keycode = KeyEvent.KEYCODE_MEDIA_REWIND;
    114         } else if ("record".equals(cmd)) {
    115             keycode = KeyEvent.KEYCODE_MEDIA_RECORD;
    116         } else if ("fast-forward".equals(cmd)) {
    117             keycode = KeyEvent.KEYCODE_MEDIA_FAST_FORWARD;
    118         } else {
    119             showError("Error: unknown dispatch code '" + cmd + "'");
    120             return;
    121         }
    122 
    123         final long now = SystemClock.uptimeMillis();
    124         sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0,
    125                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
    126         sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0, 0,
    127                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
    128     }
    129 
    130     class RemoteDisplayMonitor extends IRemoteControlDisplay.Stub {
    131         RemoteDisplayMonitor() {
    132         }
    133 
    134 
    135         @Override
    136         public void setCurrentClientId(int clientGeneration, PendingIntent clientMediaIntent,
    137                 boolean clearing) {
    138             System.out.println("New client: id=" + clientGeneration
    139                     + " intent=" + clientMediaIntent + " clearing=" + clearing);
    140         }
    141 
    142         @Override
    143         public void setEnabled(boolean enabled) {
    144             System.out.println("New enable state= " + (enabled ? "enabled" : "disabled"));
    145         }
    146 
    147         @Override
    148         public void setPlaybackState(int generationId, int state, long stateChangeTimeMs,
    149                 long currentPosMs, float speed) {
    150             System.out.println("New state: id=" + generationId + " state=" + state
    151                     + " time=" + stateChangeTimeMs + " pos=" + currentPosMs + " speed=" + speed);
    152         }
    153 
    154         @Override
    155         public void setTransportControlInfo(int generationId, int transportControlFlags,
    156                 int posCapabilities) {
    157             System.out.println("New control info: id=" + generationId
    158                     + " flags=0x" + Integer.toHexString(transportControlFlags)
    159                     + " cap=0x" + Integer.toHexString(posCapabilities));
    160         }
    161 
    162         @Override
    163         public void setMetadata(int generationId, Bundle metadata) {
    164             System.out.println("New metadata: id=" + generationId
    165                     + " data=" + metadata);
    166         }
    167 
    168         @Override
    169         public void setArtwork(int generationId, Bitmap artwork) {
    170             System.out.println("New artwork: id=" + generationId
    171                     + " art=" + artwork);
    172         }
    173 
    174         @Override
    175         public void setAllMetadata(int generationId, Bundle metadata, Bitmap artwork) {
    176             System.out.println("New metadata+artwork: id=" + generationId
    177                     + " data=" + metadata + " art=" + artwork);
    178         }
    179 
    180         void printUsageMessage() {
    181             System.out.println("Monitoring remote control displays...  available commands:");
    182             System.out.println("(q)uit: finish monitoring");
    183         }
    184 
    185         void run() throws RemoteException {
    186             printUsageMessage();
    187 
    188             mAudioService.registerRemoteControlDisplay(this, 0, 0);
    189 
    190             try {
    191                 InputStreamReader converter = new InputStreamReader(System.in);
    192                 BufferedReader in = new BufferedReader(converter);
    193                 String line;
    194 
    195                 while ((line = in.readLine()) != null) {
    196                     boolean addNewline = true;
    197                     if (line.length() <= 0) {
    198                         addNewline = false;
    199                     } else if ("q".equals(line) || "quit".equals(line)) {
    200                         break;
    201                     } else {
    202                         System.out.println("Invalid command: " + line);
    203                     }
    204 
    205                     synchronized (this) {
    206                         if (addNewline) {
    207                             System.out.println("");
    208                         }
    209                         printUsageMessage();
    210                     }
    211                 }
    212 
    213             } catch (IOException e) {
    214                 e.printStackTrace();
    215             } finally {
    216                 mAudioService.unregisterRemoteControlDisplay(this);
    217             }
    218         }
    219     }
    220 
    221     private void runRemoteDisplay() throws Exception {
    222         RemoteDisplayMonitor monitor = new RemoteDisplayMonitor();
    223         monitor.run();
    224     }
    225 }
    226