javauis/mmapi_qt/baseline/javasrc/com/nokia/microedition/media/PlayerImpl.java
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 14 May 2010 15:47:24 +0300
changeset 23 98ccebc37403
child 26 dc7c549001d5
permissions -rw-r--r--
Revision: v2.1.24 Kit: 201019

/*
* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  This class is native player implementation of Player interface
*
*/


package com.nokia.microedition.media;

import javax.microedition.media.PlayerListener;
import javax.microedition.media.MediaException;
import com.nokia.microedition.media.NativeError;
import com.nokia.mj.impl.rt.support.Finalizer;
import com.nokia.mj.impl.utils.Logger;

public class PlayerImpl extends PlayerBase
{
    // CMMAPlayer handle
    protected int iPlayerHandle;

    // Controls container
    protected ControlContainer iControls;

    // object for waiting native asynchronous method calls
    protected Object iLockObject = new Object();
     protected Object iPrefetchLockObject = new Object();

    // native error code
    protected int iError;

    protected PlayerListenerImpl iPlayerListenerImpl;

    private Finalizer mFinalizer;
    
    private boolean iWaitFlag = true;
    
    private boolean iStartWaitFlag = true;

    /**
     * Constructor
     * @param aPlayerHandle handle to player (CMMAPlayer)
     */
    public PlayerImpl(int aPlayerHandle)
    {
        iPlayerHandle = aPlayerHandle;

        iPlayerListenerImpl = new PlayerListenerImpl(this);

        // Initialize player
        int err = _initPlayer(iPlayerListenerImpl,
                              ManagerImpl.getEventSource(),
                              iPlayerHandle);
        if (err < NativeError.KErrNone)
        {
            throw new OutOfMemoryError(NativeError.errorMessage(err));
        }

        mFinalizer = new Finalizer()
        {
            public void finalizeImpl()
            {
                doFinalize();
            }
        };

        iControls = ControlContainer.populateControls(this,
                    ManagerImpl.getEventSource(),
                    iPlayerHandle);
    }

    private void doFinalize()
    {
        if (mFinalizer != null)
        {
            registeredFinalize();
            mFinalizer = null;
        }
    }

    /**
     * This method is called when garbage collection occurs
     * to delete native object
     */
    protected void registeredFinalize()
    {
        close();
    }

    /**
     * Returns native player handle.
     * @return Native player handle.
     */
    public int getPlayerHandle()
    {
        return iPlayerHandle;
    }

    /**
     * @return Player's PlayerListenerImpl
     */
    public PlayerListenerImpl getPlayerListenerImpl()
    {
        return iPlayerListenerImpl;
    }

    /**
     * Adds control to the player.
     * @param aControl Player's control
     * @param aControlName Identifies the control. Name must contain
     * full package information
     */
    public void addControl(javax.microedition.media.Control aControl,
                           String aControlName)
    {
        iControls.addControl(aControl, aControlName);
    }

    /**
     * interface Controllable
     * Return controls
     * @return list of controls
     * @see Controllable
     */
    public javax.microedition.media.Control[] getControls()
    {
        closeCheck();
        unrealizedCheck();
        return iControls.getControls();
    }

    /**
     * interface Controllable
     * get control by content type
     * @param aControlType content type of wanted control
     * @return control
     * @see Controllable
     * @see Control
     */
    public javax.microedition.media.Control getControl(String aControlType)
    {
        closeCheck();
        unrealizedCheck();
        return iControls.getControl(aControlType);
    }

    /**
     * interface Player
     * @see Player
     */
    public void addPlayerListener(PlayerListener aPlayerListener)
    {
        closeCheck();
        iPlayerListenerImpl.addPlayerListener(aPlayerListener);
    }

    /**
     * From Player
     * @see Player
     */
    public void removePlayerListener(PlayerListener aPlayerListener)
    {
        closeCheck();
        iPlayerListenerImpl.removePlayerListener(aPlayerListener);
    }

    /**
     * From Player
     * @see Player
     */
    public int getState()
    {
        int state = CLOSED;
        if (iState != CLOSED)
        {
            state = _getState(ManagerImpl.getEventSource(), iPlayerHandle);
        }
        return state;
    }


    /**
     * From PlayerBase
     * @see PlayerBase
     */
    public void doRealize() throws MediaException
    {
        int err = _realize(ManagerImpl.getEventSource(), iPlayerHandle);

        if (err < NativeError.KErrNone)
        {
            throw new MediaException(
                "Realize failed, Symbian OS error: " + err);
        }
    }

    /**
     * From PlayerBase
     * @see PlayerBase
     */
    public void doPrefetch() throws MediaException
    {
    	Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doPrefetch");
        synchronized(iPrefetchLockObject)
        { 
        	if (PREFETCHED == getState())
        	return;
         synchronized (iLockObject)
         {
        	Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doPrefetch inside try"+Thread.currentThread().getName());
          //int retval[] = new int[1];
      		 int err = _prefetch(ManagerImpl.getEventSource(), iPlayerHandle);
          Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doPrefetch err = " + err);
          if (err < NativeError.KErrNone)
          {
              throw new MediaException(
              "Prefetch failed, Symbian OS error: " + err);
          }
          if(iWaitFlag)
          {
           try
            {
                // wait until actionCompleted( int aError ) is called
                iLockObject.wait();
            }
            catch (InterruptedException ie)
            {
                // cannot occur
            }
          }
         Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doPrefetch Sync end");
	        } // end   synchronized (iLockObject)
   	   }
        if (iError < NativeError.KErrNone)
        {
            throw new MediaException(
                "Prefetch failed, Symbian OS error: " + iError);
        }
    }

    /**
     * Notify that action is completed. Called from native side.
     * @param aError error code
     */
    private void actionCompleted(int aError)
    {
    	  Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"actionCompleted callback11 aError ="+ aError + "    "+Thread.currentThread().getName());
        iError = aError;

        synchronized (iLockObject)
       {
        	Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"actionCompleted callback inside synchronized (iLockObject)");
            iLockObject.notify();
        }
    }
    
    private void actionCompletedFile()
    {
        Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : actionCompletedFile");
        iWaitFlag = false;       
        
   }
    
    private void actionCompletedStart()
    {
        Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : actionCompletedStart");
        iStartWaitFlag = false;       
        
    }

    /**
     * From PlayerBase
     * @see PlayerBase
     */
    public void doDeallocate()
    {
        int ret = _deallocate(ManagerImpl.getEventSource(), iPlayerHandle);
        if (ret < NativeError.KErrNone)
        {
            Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,
                       "_deallocate() failed: err=" + ret);
        }
    }

    /**
     * From Player.
     * @see Player
     */
    public void start() throws MediaException
    {
    Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : start()");
    prefetch();
			 Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl, start, state = "+getState());
    // Only preteched player may be started. If player is already started
    // this method returns silently.
    if (getState() == PREFETCHED)
    {
         synchronized (iLockObject)
         {        
             Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl, before calling native _start() thread is =" +Thread.currentThread().getName());
            	Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl, before calling native _start()");
             int err = _start(ManagerImpl.getEventSource(), iPlayerHandle);
             Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl, before calling native _start( ) returned : err = "+err);
             if (err < NativeError.KErrNone)
             {
                throw new MediaException(
                "Start failed, Symbian OS error: " + err);
             }
             if (iError < NativeError.KErrNone)
             {
                    throw new MediaException(
                    "Start failed, Symbian OS error: " + iError);
             }
             if(iStartWaitFlag)
             {
                try
                {
                      // wait until actionCompleted( int aError ) is called
                       iLockObject.wait();   // only for tck run
                 }
                 catch (InterruptedException ie)
                 {
                    // cannot occur
                 }
                
             }
          }
    }
    }

    /**
     * From PlayerBase
     * @see PlayerBase
     */
    public void doStop() throws MediaException
    {
        /*
        Stops the Player. It will pause the playback at the current media time.
        Calling start will resume the playback from where it is stopped.
        If stop is called on a stopped Player, the request is ignored.
        */
        Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doStop()");
        int err = _stop(ManagerImpl.getEventSource(), iPlayerHandle);
        if (err < NativeError.KErrNone)
        {
            throw new MediaException(
                "Stop failed, Symbian OS error: " + err);
        }
        // After this request is completed,
        // the Player is in the PREFETCHED state.
    }

    /**
     * From PlayerBase
     * @see PlayerBase
     */
    public void doClose()
    {
    	Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doclose() 1");
        _close(ManagerImpl.getEventSource(), iPlayerHandle);

        if (iPlayerHandle > NativeError.KErrNone)  // construction has succeed
        {
            Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doclose() 2");
            // notify the controls
            iControls.dispose();
            Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doclose() 3");

            // delete the native object
            _dispose(ManagerImpl.getEventSource(), iPlayerHandle);
            Logger.LOG(Logger.EJavaMMAPI, Logger.EInfo,"PlayerImpl.java : doclose() 4");
            iPlayerHandle = 0; // Do not use native object anymore
        }
    }
    /**
     * interface Player
     * @see Player
     */
    public void setLoopCount(int aCount)
    {
        super.setLoopCount(aCount);
        _setLoopCount(ManagerImpl.getEventSource(), iPlayerHandle, aCount);
    }

    /**
     * interface Player
     * @see Player
     */
    public long getDuration()
    {
        closeCheck();
        long duration = _duration(ManagerImpl.getEventSource(), iPlayerHandle);
        if (duration < NativeError.KErrNone)
        {
            duration = TIME_UNKNOWN;
        }
        return duration;
    }

    /**
     * From PlayerBase
     * @see PlayerBase
     */
    public long setMediaTime(long aNow) throws MediaException
    {
        long time = _setMediaTime(ManagerImpl.getEventSource(),
                                  iPlayerHandle,
                                  super.setMediaTime(aNow));
        if (time < NativeError.KErrNone)
        {
            throw new MediaException(
                "Could not set media time, Symbian OS error: " + time);
        }
        return time;
    }

    /**
     * interface Player
     * @see Player
     */
    public long getMediaTime()
    {
        closeCheck();
        long time = _getMediaTime(ManagerImpl.getEventSource(), iPlayerHandle);
        if (time < NativeError.KErrNone)
        {
            time = TIME_UNKNOWN;
        }
        return time;
    }


    /**
     * interface Player
     * @see Player
     */
    public String getContentType()
    {
        closeCheck();
        unrealizedCheck();

        return _getContentType(iPlayerHandle);
    }

    // JNI
    private native int _initPlayer(Object aPlayerListenerObject,
                                   int aEventSource,
                                   int aPlayerHandle);

    private static native int _start(int aEventPoster, int aPlayer);
    private static native int _stop(int aEventPoster, int aPlayer);
    private static native int _close(int aEventPoster, int aPlayer);
    private static native int _prefetch(int aEventPoster, int aPlayer);

    private static native int _setLoopCount(int aEventPoster, int aPlayer,
                                            int aLoopCount);

    private static native int _realize(int aEventPoster, int aPlayer);
    private static native long _duration(int aEventPoster, int aPlayer);
    private static native long _setMediaTime(int aEventPoster, int aPlayer,
            long aNow);

    private static native int _deallocate(int aEventPoster, int aPlayer);
    private static native long _getMediaTime(int aEventPoster, int aPlayer);
    private static native int _getState(int aEventPoster, int aPlayer);

    protected static native int _addSourceStream(int aEventPoster,
            int aPlayerHandle,
            Object aSourceStreamReader);

    private static native String _getContentType(int aPlayerHandle);

    private static native void _dispose(int aEventSourceHandle,
                                        int aObjectHandle);
}

// End of File