mpx/playbackframework/playbackserver/src/mpxplaybackserver.cpp
changeset 0 a2952bb97e68
child 15 d240f0a77280
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Playback server
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32std.h>
       
    20 #include <e32svr.h>
       
    21 #ifdef RD_TSP_CLIENT_MAPPER
       
    22 #include <tspclientmapper.h>
       
    23 #endif
       
    24 #include <mpxclientlist.h>
       
    25 #include <mpxpluginmonitor.h>
       
    26 #include <mpxlog.h>
       
    27 #include "mpxplaybackserverdefs.h"
       
    28 #include "mpxplaybackengine.h"
       
    29 #include "mpxplaybackserversession.h"
       
    30 #include "mpxplaybackserver.h"
       
    31 
       
    32 // CONSTANTS
       
    33 
       
    34 // Server Security Policy
       
    35 const TUint KMPXPlaybackServerRangeCount = 2;
       
    36 const TInt KMPXPlaybackServerRanges[KMPXPlaybackServerRangeCount] =
       
    37     {
       
    38     0,                  //range is [0-EPbsServerOpEnd)
       
    39     EPbsServerOpEnd,    //range is [EPbsServerOpEnd-KMaxTInt]
       
    40     };
       
    41 const TUint8 KMPXPlaybackSeverElementsIndex[KMPXPlaybackServerRangeCount] =
       
    42     {
       
    43     0,                            //applies to range [0-EPbsServerOpEnd)
       
    44     CPolicyServer::ENotSupported, //applies to range [EPbsServerOpEnd-KMaxTInt]
       
    45     };
       
    46 
       
    47 const CPolicyServer::TPolicyElement KMPXPlaybackServerPolicyElements[] =
       
    48     {
       
    49     {_INIT_SECURITY_POLICY_C1(ECapability_None),
       
    50                               CPolicyServer::EFailClient},
       
    51     };
       
    52 
       
    53 const CPolicyServer::TPolicy KMPXPlaybackServerPolicy =
       
    54     {
       
    55     CPolicyServer::EAlwaysPass, //specifies all connect attempts should pass
       
    56     KMPXPlaybackServerRangeCount,
       
    57     KMPXPlaybackServerRanges,
       
    58     KMPXPlaybackSeverElementsIndex,
       
    59     KMPXPlaybackServerPolicyElements,
       
    60     };
       
    61 
       
    62 // ----------------------------------------------------------------------------
       
    63 // Start playback server
       
    64 //
       
    65 LOCAL_C void StartServerL()
       
    66     {
       
    67     User::LeaveIfError(User::RenameThread(KMPXPlaybackServerName));
       
    68     CActiveScheduler* scheduler = new(ELeave)CActiveScheduler;
       
    69     CleanupStack::PushL(scheduler);
       
    70     CActiveScheduler::Install(scheduler);
       
    71     CMPXPlaybackServer* server = CMPXPlaybackServer::NewL();
       
    72     CleanupStack::PushL(server);
       
    73     RProcess::Rendezvous(KErrNone);
       
    74     CActiveScheduler::Start();
       
    75     CActiveScheduler::Install(NULL);
       
    76     CleanupStack::PopAndDestroy(server);
       
    77     CleanupStack::PopAndDestroy(scheduler);
       
    78     }
       
    79 
       
    80 // ============================ MEMBER FUNCTIONS ==============================
       
    81 
       
    82 // ----------------------------------------------------------------------------
       
    83 // Two-phased constructor.
       
    84 // ----------------------------------------------------------------------------
       
    85 //
       
    86 CMPXPlaybackServer* CMPXPlaybackServer::NewL()
       
    87     {
       
    88     CMPXPlaybackServer *pS = new(ELeave) CMPXPlaybackServer(
       
    89                                                 CActive::EPriorityStandard,
       
    90                                                 KMPXPlaybackServerPolicy);
       
    91     CleanupStack::PushL(pS);
       
    92     pS->ConstructL();
       
    93     CleanupStack::Pop(pS);
       
    94     return pS;
       
    95     }
       
    96 
       
    97 // ----------------------------------------------------------------------------
       
    98 // C++ constructor can NOT contain any code that might leave.
       
    99 // ----------------------------------------------------------------------------
       
   100 //
       
   101 CMPXPlaybackServer::CMPXPlaybackServer(TInt aPriority, const TPolicy &aPolicy)
       
   102     : CPolicyServer(aPriority, aPolicy)
       
   103     {}
       
   104 
       
   105 // ----------------------------------------------------------------------------
       
   106 // Destructor
       
   107 // ----------------------------------------------------------------------------
       
   108 //
       
   109 CMPXPlaybackServer::~CMPXPlaybackServer()
       
   110     {
       
   111     iPlayers.ResetAndDestroy();
       
   112     delete iPluginMonitor;
       
   113 #ifdef RD_TSP_CLIENT_MAPPER
       
   114     delete iClientMapper;
       
   115 #endif
       
   116     }
       
   117 
       
   118 // ----------------------------------------------------------------------------
       
   119 // Symbian 2nd phase constructor can leave.
       
   120 // ----------------------------------------------------------------------------
       
   121 //
       
   122 void CMPXPlaybackServer::ConstructL()
       
   123     {
       
   124     StartL(KMPXPlaybackServerName);
       
   125     iPluginMonitor = CMPXPluginMonitor::NewL(KMPXPlaybackInterfaceUid);
       
   126 #ifdef RD_TSP_CLIENT_MAPPER
       
   127     iClientMapper = CTspClientMapper::NewL();
       
   128 #endif
       
   129     }
       
   130 
       
   131 // ----------------------------------------------------------------------------
       
   132 // Increments number of sessions this server holds
       
   133 // ----------------------------------------------------------------------------
       
   134 //
       
   135 void CMPXPlaybackServer::AddClient()
       
   136     {
       
   137     iClients++;
       
   138     }
       
   139 
       
   140 
       
   141 // ----------------------------------------------------------------------------
       
   142 // Find the player that has client aName, and remove it from that player; if
       
   143 // that player has no clients, then delete that player. If the server has no
       
   144 //  more client sessions, then stop the server.
       
   145 // ----------------------------------------------------------------------------
       
   146 //
       
   147 void CMPXPlaybackServer::RemoveClient(const CMPXMessageQueue& aMsgQueue)
       
   148     {
       
   149     MPX_DEBUG2("CMPXPlaybackServer::RemoveClient from %d",
       
   150                 iPlayers.Count());
       
   151     for (TInt i=iPlayers.Count();--i>=0;)
       
   152         {
       
   153         CMPXPlaybackEngine* p=iPlayers[i];
       
   154         CMPXClientList* cl=p->ClientList();
       
   155         TInt index(cl->Find(aMsgQueue));
       
   156         if (KErrNotFound != index)
       
   157             {
       
   158             MPX_DEBUG1("CMPXPlaybackServer::RemoveClient found client");
       
   159             cl->RemoveClient(index);
       
   160             if (cl->ClientCount()==0)
       
   161                 {
       
   162                 MPX_DEBUG1("CMPXPlaybackServer::RemoveClient delete a player");
       
   163                 delete p;
       
   164                 iPlayers.Remove(i);
       
   165                 }
       
   166             break;
       
   167             }
       
   168         }
       
   169     iClients--;
       
   170     ASSERT(iClients>=0);
       
   171     if (iClients==0)
       
   172         {
       
   173         CActiveScheduler::Stop();
       
   174         }
       
   175     }
       
   176 
       
   177 // ----------------------------------------------------------------------------
       
   178 // Return last active process id
       
   179 // ----------------------------------------------------------------------------
       
   180 //
       
   181 TProcessId CMPXPlaybackServer::LastActiveProcessId()
       
   182     {
       
   183     TProcessId id(KNullProcessId);
       
   184     if (iPlayers.Count())
       
   185         {
       
   186         id = iPlayers[0]->LastActiveProcessId();
       
   187         }
       
   188     return id;
       
   189     }
       
   190 
       
   191 // ----------------------------------------------------------------------------
       
   192 // Creates a brand new player to the player list with this client name and TID,
       
   193 // and whether it's the music player.
       
   194 // ----------------------------------------------------------------------------
       
   195 //
       
   196 CMPXPlaybackEngine* CMPXPlaybackServer::AddNewPlayerL(
       
   197     TThreadId aClientId,
       
   198     const TUid& aModeId,
       
   199     CMPXMessageQueue* aMsgQueue,
       
   200     const TInt aCategory) 
       
   201     {
       
   202     CMPXPlaybackEngine* p =
       
   203                 CMPXPlaybackEngine::NewL(*iPluginMonitor,*this,this,aModeId, aCategory); 
       
   204     MPX_DEBUG2("CMPXPlaybackServer::AddNewPlayerL 0x%08x", p);
       
   205     CleanupStack::PushL(p);
       
   206     p->ClientList()->AddClientL(aClientId, aModeId.iUid, aMsgQueue, aCategory); 
       
   207     iPlayers.AppendL(p);
       
   208     CleanupStack::Pop(p);
       
   209     return p;
       
   210     }
       
   211 
       
   212 // ----------------------------------------------------------------------------
       
   213 // Create player according to the mode:
       
   214 // ----------------------------------------------------------------------------
       
   215 //
       
   216 CMPXPlaybackEngine* CMPXPlaybackServer::CreatePlayerL(
       
   217     const TUid& aModeId,
       
   218     const TInt aCategory, 
       
   219     TThreadId aClientId,
       
   220     CMPXMessageQueue* aMsgQueue)
       
   221     {
       
   222     CMPXPlaybackEngine* p=NULL;
       
   223     if (aModeId == KPbModeDefault)
       
   224         {
       
   225         // Add the new client to the player created by another client running
       
   226         // in the same thread. If there isn't one, then create the first player
       
   227         // for this thread
       
   228         //
       
   229         p=AddToDefaultPlayerL(aClientId,aMsgQueue,aCategory);
       
   230         if(!p)
       
   231             {
       
   232 
       
   233             p=AddNewPlayerL(aClientId, aModeId, aMsgQueue, aCategory);
       
   234             }
       
   235         }
       
   236         //
       
   237     else if (aModeId == KPbModeNewPlayer)
       
   238         {
       
   239         //
       
   240         // Create a brand new player for this client
       
   241         //
       
   242         p=AddNewPlayerL(aClientId, aModeId, aMsgQueue, aCategory);
       
   243         }
       
   244     else if (aModeId == KPbModeActivePlayer)
       
   245         { 
       
   246         TInt index = IndexOfRecentActivePlayer(aCategory);
       
   247         if (KErrNotFound != index)
       
   248             {
       
   249             p = iPlayers[index]; // active & matching category
       
   250             }
       
   251         if (!p && iPlayers.Count()>0)
       
   252             { //no recent activeplayer, attach to the first player with matching category
       
   253             TInt count = iPlayers.Count();
       
   254             for(TInt i = 0; i < count; i++)
       
   255                 {
       
   256                 if(iPlayers[i]->Category() == aCategory)
       
   257                     {
       
   258                     p = iPlayers[i]; // not active, first matching category 
       
   259                     break;
       
   260                     }
       
   261                 }
       
   262             }
       
   263         if (p)
       
   264             {
       
   265             p->ClientList()->AddClientL(aClientId,aModeId.iUid,aMsgQueue, aCategory);
       
   266             }
       
   267         else
       
   268             { // no player available (no active player with matching category)
       
   269             MPX_DEBUG1("CMPXPlaybackServer::CreatePlayerL create a new player");	
       
   270             p=AddNewPlayerL(aClientId, aModeId, aMsgQueue, aCategory);
       
   271             }
       
   272         }
       
   273     else
       
   274         {
       
   275         //
       
   276         // Add the new client to the player created by one application. If
       
   277         // there isn't one, then create the first player for the application
       
   278         //
       
   279         for (TInt i=iPlayers.Count();--i>=0;)
       
   280             {
       
   281             if (iPlayers[i]->ModeId() == aModeId)
       
   282                 {
       
   283                 p = iPlayers[i];
       
   284                 p->ClientList()->AddClientL(aClientId,
       
   285                                             aModeId.iUid, aMsgQueue, aCategory);
       
   286                 break;
       
   287                 }
       
   288             }
       
   289 
       
   290         if (!p)
       
   291             {		
       
   292             p=AddNewPlayerL(aClientId, aModeId, aMsgQueue, aCategory);		
       
   293             }
       
   294         }
       
   295     return p;
       
   296     }
       
   297 
       
   298 // ----------------------------------------------------------------------------
       
   299 // Add the new client (defined by it's TID) to the player
       
   300 // associated with the Tid aExistingClientId
       
   301 // ----------------------------------------------------------------------------
       
   302 //
       
   303 CMPXPlaybackEngine* CMPXPlaybackServer::AddToDefaultPlayerL(
       
   304     TThreadId aClientId,
       
   305     CMPXMessageQueue* aMsgQueue,
       
   306     const TInt aCategory)
       
   307     {
       
   308     CMPXPlaybackEngine* p=NULL;
       
   309     for (TInt i=0; i < iPlayers.Count(); ++i)
       
   310         {
       
   311         p=iPlayers[i];
       
   312         CMPXClientList* cl=p->ClientList();
       
   313         TInt index = cl->Find(aClientId);
       
   314         if (KErrNotFound != index)
       
   315             {
       
   316             // if the player is an active player, change mode from default
       
   317             // to activeplayer. Default mode always uses the mode of first client
       
   318             TInt mode = (cl->ClientMode(index) == KPbModeActivePlayer.iUid) ?
       
   319                          KPbModeActivePlayer.iUid : KPbModeDefault.iUid;
       
   320             MPX_DEBUG3("CMPXPlaybackServer::AddToDefaultPlayerL mode 0x%08x, engine 0x%08x",
       
   321                        mode, p);				   
       
   322             cl->AddClientL(aClientId,mode,aMsgQueue, aCategory);
       
   323             break;
       
   324             }
       
   325         }
       
   326     return p;
       
   327     }
       
   328 
       
   329 // ----------------------------------------------------------------------------
       
   330 // Return the index of an active player. If there is no active player, return
       
   331 // the index to the player in paused state which may be interrupted.
       
   332 // ----------------------------------------------------------------------------
       
   333 //
       
   334 TInt CMPXPlaybackServer::IndexOfRecentActivePlayer(TInt aCategory)
       
   335     {
       
   336     TInt ret(KErrNotFound);
       
   337     for (TInt i=0; i<iPlayers.Count(); ++i)
       
   338         {
       
   339         CMPXPlaybackEngine* p = iPlayers[i];
       
   340         if (p->IsPlayerActive() && aCategory == p->Category())
       
   341             { // Found active player
       
   342             ret = i;
       
   343             break;
       
   344             }
       
   345         else if (EPbStatePaused == p->State() && KErrNotFound == ret && aCategory == p->Category())
       
   346             { // first paused player
       
   347             ret = i;
       
   348             }
       
   349         }
       
   350     return ret;
       
   351     }
       
   352 
       
   353 TInt CMPXPlaybackServer::IndexOfRecentActivePlayer()
       
   354     {
       
   355     TInt ret(KErrNotFound);
       
   356     for (TInt i=0; i<iPlayers.Count(); ++i)
       
   357         {
       
   358         CMPXPlaybackEngine* p = iPlayers[i];
       
   359         if (p->IsPlayerActive())
       
   360             { // Found active player
       
   361             ret = i;
       
   362             break;
       
   363             }
       
   364         else if (EPbStatePaused == p->State() && KErrNotFound == ret)
       
   365             { // first paused player
       
   366             ret = i;
       
   367             }
       
   368         }
       
   369     return ret;
       
   370     }
       
   371 
       
   372 // ----------------------------------------------------------------------------
       
   373 // Handle active player changed evnet.
       
   374 // Notify all clients of EPbModeActivePlayer mode in inactive engines
       
   375 // ----------------------------------------------------------------------------
       
   376 //
       
   377 void CMPXPlaybackServer::HandleActiveEngineL(
       
   378     const CMPXPlaybackEngine* aEngine,
       
   379     TBool aActive)
       
   380     {
       
   381     MPX_DEBUG3("CMPXPlaybackServer::HandleActiveEngineL Engine: 0x%08x, Active %d",
       
   382                aEngine, aActive);
       
   383     TInt i(0);
       
   384     TInt indexOfActive = iPlayers.Find(aEngine);
       
   385     ASSERT(KErrNotFound!=indexOfActive);
       
   386     if (!aActive)
       
   387         {
       
   388 #ifdef RD_TSP_CLIENT_MAPPER
       
   389         iClientMapper->SetTspTargetClientToOtherType(
       
   390                 CTspClientMapper::EStoppedClients,
       
   391                 aEngine->LastActiveProcessId());
       
   392         MPX_DEBUG2("CMPXPlaybackServer::HandleActiveEngineL(): Adding to stopped client %d",
       
   393                    TUint( aEngine->LastActiveProcessId()));
       
   394 
       
   395 #endif
       
   396         if (EPbStatePaused != aEngine->State())
       
   397             {
       
   398             indexOfActive = IndexOfRecentActivePlayer();
       
   399             }
       
   400         else
       
   401             { // else no need to rebind. if the player is interruptted by other player
       
   402               // there must be another HandleActiveEngineL callback with aActive = ETrue
       
   403             indexOfActive = KErrNotFound;
       
   404             }
       
   405         }
       
   406     else
       
   407         {// else aEngine is active player
       
   408 #ifdef RD_TSP_CLIENT_MAPPER
       
   409         iClientMapper->SetTspTargetClientToOtherType(
       
   410                 CTspClientMapper::EPlayingClients,
       
   411                 aEngine->LastActiveProcessId());
       
   412         MPX_DEBUG2("CMPXPlaybackServer::HandleActiveEngineL(): Adding to playing client %d",
       
   413                    TUint( aEngine->LastActiveProcessId()));
       
   414 #endif
       
   415         }
       
   416 
       
   417     if (KErrNotFound != indexOfActive)
       
   418         {
       
   419         // Move the active player engine to the top of player list
       
   420         CMPXPlaybackEngine* player(NULL);
       
   421         if (indexOfActive)
       
   422             { // not 0
       
   423             player = iPlayers[indexOfActive];
       
   424             iPlayers.Remove(indexOfActive);
       
   425             iPlayers.Insert(player, 0);
       
   426             }
       
   427 
       
   428         // Active engine changed, notify all clients who are instrested.
       
   429         // e.g. KPbModeActivePlayer
       
   430         for (i=1; i < iPlayers.Count(); ++i)
       
   431             {
       
   432             player = iPlayers[i];
       
   433             if (player == aEngine && aActive)
       
   434                 {
       
   435                 continue;
       
   436                 }
       
   437             MPX_DEBUG2("CMPXPlaybackServer::HandleActiveEngineL Player: 0x%08x", player);
       
   438             CMPXClientList* cl = player->ClientList();
       
   439             for (TInt j = cl->ClientCount(); --j>=0;)
       
   440                 {
       
   441                 if ((KPbModeActivePlayer.iUid == cl->ClientMode(j)) && 
       
   442                         (aEngine->Category() == cl->ClientCategory(j))) 
       
   443                     {
       
   444                     MPX_DEBUG2(
       
   445                       "CMPXPlaybackServer notify %d client player changed", j);
       
   446                     player->ClientList()->SendMsgL(
       
   447                                 j,
       
   448                                 TMPXPlaybackMessage(
       
   449                                     TMPXPlaybackMessage::EActivePlayerChanged,
       
   450                                     1, aActive));
       
   451                     }
       
   452                 }
       
   453             }
       
   454         }
       
   455     }
       
   456 
       
   457 // ----------------------------------------------------------------------------
       
   458 // Observe client change event
       
   459 // ----------------------------------------------------------------------------
       
   460 //
       
   461 void CMPXPlaybackServer::HandleClientChange(
       
   462     const TProcessId& aPid,
       
   463     MMPXClientlistObserver::TChangeType aChangeType)
       
   464     {
       
   465 #ifdef RD_TSP_CLIENT_MAPPER
       
   466     if (MMPXClientlistObserver::EAdd == aChangeType)
       
   467         {
       
   468         iClientMapper->SetTspTargetClient(
       
   469                 CTspClientMapper::EPlayingClients,
       
   470                 aPid);
       
   471         MPX_DEBUG2("CMPXPlaybackServer::HandleClientChange(): Adding to registered client %d",
       
   472                    TUint( aPid ));
       
   473         }
       
   474     else
       
   475         {
       
   476         iClientMapper->RemoveTspTargetClient(
       
   477                 CTspClientMapper::EPlayingClients,
       
   478                 aPid);
       
   479         MPX_DEBUG2("CMPXPlaybackServer::HandleClientChange(): Adding to EPlayingClients client %d",
       
   480                    TUint( aPid ));
       
   481         }
       
   482 #else
       
   483     (void)aPid;
       
   484     (void)aChangeType;
       
   485 #endif
       
   486     }
       
   487 
       
   488 // ----------------------------------------------------------------------------
       
   489 // Create a new session
       
   490 // ----------------------------------------------------------------------------
       
   491 //
       
   492 CSession2* CMPXPlaybackServer::NewSessionL(const TVersion& aVersion,
       
   493                                            const RMessage2& /*aMessage*/) const
       
   494     {
       
   495     TVersion v(KMPXPlaybackServerMajorVersionNumber,
       
   496                KMPXPlaybackServerMinorVersionNumber,
       
   497                KMPXPlaybackServerBuildVersionNumber);
       
   498     if (!User::QueryVersionSupported(v,aVersion))
       
   499         User::Leave(KErrNotSupported);
       
   500     CMPXPlaybackSession* session = CMPXPlaybackSession::NewL();
       
   501     const_cast<CMPXPlaybackServer*>(this)->AddClient();
       
   502     return session;
       
   503     }
       
   504 
       
   505 // ----------------------------------------------------------------------------
       
   506 // Server exe entry
       
   507 // ----------------------------------------------------------------------------
       
   508 //
       
   509 TInt E32Main()
       
   510     {
       
   511     __UHEAP_MARK;
       
   512     //
       
   513     CTrapCleanup* cleanup=CTrapCleanup::New();
       
   514     TInt r=KErrNoMemory;
       
   515     if (cleanup)
       
   516         {
       
   517         TRAP(r,StartServerL());
       
   518         }
       
   519 
       
   520     delete cleanup;
       
   521     __UHEAP_MARKEND;
       
   522     return r;
       
   523     }
       
   524 
       
   525 // End of file