Logo Search packages:      
Sourcecode: zinf version File versions  Download package

corbaUI.cpp

/*____________________________________________________________________________
        
        Zinf - Zinf Is Not FreeA*p (The Free MP3 Player)

        Portions Copyright (C) 1998-1999 EMusic.com
        Portions Copyright (C) 1999      Henrik Johnson 
        Portions Copyright (C) 2000      Martin Enlund
        Portions Copyright (C) 2000      Ralf Engels

        This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation; either version 2 of the License, or
        (at your option) any later version.

        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.

        You should have received a copy of the GNU General Public License
        along with this program; if not, write to the Free Software
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        
        $Id: corbaUI.cpp,v 1.12 2004/01/08 19:33:44 kgk Exp $
____________________________________________________________________________*/

#include <stdio.h>
#include <unistd.h>
#include <iostream>

#include <sys/time.h>
#include <termios.h>
#include <signal.h>
#include <string>
#include <vector>

using namespace std;
#include "config.h"
#include "corbaUI.h"
#include "event.h"
#include "player.h"
#include "playlist.h"
#include "thread.h"
#include "eventdata.h"

#include "MusicPlayer.h"
#include <orb/orbit.h>


/** The server name */
#define CORBA_SERVER_NAME "MusicPlayer-ORBit"

/** Saves "the context"
 *  Often forgotten: a java static class variable is just a normal C++ variable!
 */
FAContext*     context = NULL;

/** Saves the last received song time.
 *  The time is the (virtual) start time of the song so that every time
 *  the updated current song time can be calculated.
 */
timeval        startTime;

/** Saves the last received media info event.
 */
MediaInfoEvent mediaInfoEvent;

/** Saves the last received mpeg info event.
 */
MpegInfoEvent mpegInfoEvent;

/** Thread used for corba server
 */
Thread* corbaServerThread = NULL;

/** This is so we can get out a valid IOR later... 
 */
MusicPlayer zinf_client = CORBA_OBJECT_NIL;


#define stdinfd 0
// #define CORBADEBUG 
extern "C"
{

  /** Initialize must be defined as extern C */
  UserInterface *Initialize(FAContext * context)
  {
    return new corbaUI(context);
  }


/*** App-specific servant structures ***/

typedef struct
{
   POA_MusicPlayer servant;
   PortableServer_POA poa;

} impl_POA_MusicPlayer;

/*** Implementation stub prototypes ***/

/*
static void impl_MusicPlayer__destroy(impl_POA_MusicPlayer * servant,
                         CORBA_Environment * ev);
*/

static void
impl_MusicPlayer_Previous(PortableServer_Servant servant, CORBA_Environment * ev);

static void impl_MusicPlayer_Next(PortableServer_Servant servant, CORBA_Environment * ev);

static void impl_MusicPlayer_Quit(PortableServer_Servant servant, CORBA_Environment * ev);

static void impl_MusicPlayer_Play(PortableServer_Servant servant, CORBA_Environment * ev);

static void impl_MusicPlayer_Pause(PortableServer_Servant servant, CORBA_Environment * ev);

static void impl_MusicPlayer_Stop(PortableServer_Servant servant, CORBA_Environment * ev);

static CORBA_long
impl_MusicPlayer_GetState(PortableServer_Servant servant, CORBA_Environment * ev);

static CORBA_boolean
impl_MusicPlayer_GetShuffle(PortableServer_Servant servant, CORBA_Environment * ev);

static void
impl_MusicPlayer_SetShuffle(PortableServer_Servant servant,
                 const CORBA_boolean value, CORBA_Environment * ev);

static CORBA_long
impl_MusicPlayer_GetRepeat(PortableServer_Servant servant, CORBA_Environment * ev);

static void
impl_MusicPlayer_SetRepeat(PortableServer_Servant servant,
                const CORBA_long value, CORBA_Environment * ev);

static void
impl_MusicPlayer_GetVolume(PortableServer_Servant servant,
                MusicPlayer_Volume * volume, CORBA_Environment * ev);

static void
impl_MusicPlayer_SetVolume(PortableServer_Servant servant,
                const MusicPlayer_Volume * volume, CORBA_Environment * ev);


static CORBA_char *impl_MusicPlayer_GetCurrentSong(PortableServer_Servant servant,
                                            CORBA_Environment * ev);

static CORBA_long
impl_MusicPlayer_GetTotalTime(PortableServer_Servant servant, CORBA_Environment * ev);

static CORBA_long
impl_MusicPlayer_GetCurrentTime(PortableServer_Servant servant, CORBA_Environment * ev);

static void
impl_MusicPlayer_SetCurrentTime(PortableServer_Servant servant,
                   const CORBA_unsigned_long time,
                   CORBA_Environment * ev);

static void
impl_MusicPlayer_GetPlaylist(PortableServer_Servant servant,
                  MusicPlayer_StringList ** list, CORBA_Environment * ev);

static void
impl_MusicPlayer_SetPlaylist(PortableServer_Servant servant,
                  const MusicPlayer_StringList * list, CORBA_Environment * ev);

static CORBA_unsigned_long
impl_MusicPlayer_GetPlaylistPos(PortableServer_Servant servant, CORBA_Environment * ev);

static void
impl_MusicPlayer_SetPlaylistPos(PortableServer_Servant servant,
                   const CORBA_unsigned_long number,
                   CORBA_Environment * ev);

static void
impl_MusicPlayer_AddSong(PortableServer_Servant servant,
              const CORBA_char * url, CORBA_Environment * ev);

static void
impl_MusicPlayer_DeleteNumber(PortableServer_Servant servant,
                   const CORBA_unsigned_long number,
                   CORBA_Environment * ev);

/*** epv structures ***/

static PortableServer_ServantBase__epv impl_MusicPlayer_base_epv = {
   NULL,                /* _private data */
   NULL,                /* finalize routine */
   NULL,                /* default_POA routine */
};


static POA_MusicPlayer__epv impl_MusicPlayer_epv = {
   NULL,                /* _private */
   impl_MusicPlayer_Previous,

   impl_MusicPlayer_Next,

   impl_MusicPlayer_Quit,

   impl_MusicPlayer_Play,

   impl_MusicPlayer_Pause,

   impl_MusicPlayer_Stop,

   impl_MusicPlayer_GetState,
   
   impl_MusicPlayer_GetShuffle,

   impl_MusicPlayer_SetShuffle,

   impl_MusicPlayer_GetRepeat,

   impl_MusicPlayer_SetRepeat,

   impl_MusicPlayer_GetVolume,

   impl_MusicPlayer_SetVolume,

   impl_MusicPlayer_GetCurrentSong,

   impl_MusicPlayer_GetTotalTime,

   impl_MusicPlayer_GetCurrentTime,

   impl_MusicPlayer_SetCurrentTime,

   impl_MusicPlayer_GetPlaylist,

   impl_MusicPlayer_SetPlaylist,

   impl_MusicPlayer_GetPlaylistPos,

   impl_MusicPlayer_SetPlaylistPos,

   impl_MusicPlayer_AddSong,

   impl_MusicPlayer_DeleteNumber,

};

/*** vepv structures ***/

static POA_MusicPlayer__vepv impl_MusicPlayer_vepv = {
   &impl_MusicPlayer_base_epv,
   &impl_MusicPlayer_epv,
};



/*** Stub implementations ***/


static MusicPlayer
impl_MusicPlayer__create(PortableServer_POA poa, CORBA_Environment * ev)
{
   MusicPlayer retval;
   impl_POA_MusicPlayer *newservant;
   PortableServer_ObjectId *objid;

   newservant = g_new0(impl_POA_MusicPlayer, 1);
   newservant->servant.vepv = &impl_MusicPlayer_vepv;
   newservant->poa = poa;
   POA_MusicPlayer__init((PortableServer_Servant) newservant, ev);
   objid = PortableServer_POA_activate_object(poa, newservant, ev);
   CORBA_free(objid);
   retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);

   return retval;
}

/*
static void
impl_MusicPlayer__destroy(impl_POA_MusicPlayer* servant, CORBA_Environment * ev)
{
   PortableServer_ObjectId *objid;

   objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
   PortableServer_POA_deactivate_object(servant->poa, objid, ev);
   CORBA_free(objid);

   POA_MusicPlayer__fini((PortableServer_Servant) servant, ev);
   g_free(servant);
}
*/

static void
impl_MusicPlayer_Previous(PortableServer_Servant servant, CORBA_Environment * ev)
{             
  Event *e = new Event(CMD_PrevMediaPiece);
  context->target->AcceptEvent(e);
}

static void
impl_MusicPlayer_Next(PortableServer_Servant servant, CORBA_Environment * ev)
{             
  Event *e = new Event(CMD_NextMediaPiece);
  context->target->AcceptEvent(e);
}

static void
impl_MusicPlayer_Quit(PortableServer_Servant servant, CORBA_Environment * ev)
{      
  Event *e = new Event(CMD_QuitPlayer);
  context->target->AcceptEvent(e);
}

static void
impl_MusicPlayer_Play(PortableServer_Servant servant, CORBA_Environment * ev)
{
  Event *e = new Event(CMD_Play);
  context->target->AcceptEvent(e);
}

static void
impl_MusicPlayer_Pause(PortableServer_Servant servant, CORBA_Environment * ev)
{               
  if( context->player->State() == PlayerState_Playing ) 
    {
      Event *e = new Event(CMD_TogglePause);
      context->target->AcceptEvent(e);
    }
}

static void
impl_MusicPlayer_Stop(PortableServer_Servant servant, CORBA_Environment * ev)
{
  Event *e = new Event(CMD_Stop);
  context->target->AcceptEvent(e);
}

static CORBA_long
impl_MusicPlayer_GetState(PortableServer_Servant servant, CORBA_Environment * ev)
{
   CORBA_long retval = 0;

   switch( context->player->State() ) 
     {
     case PlayerState_Paused:
       retval = 2; break;
     case PlayerState_Playing:
       retval = 3; break;
     case PlayerState_Stopped:
       retval = 1; break;
     }

   return retval;
}

static CORBA_boolean
impl_MusicPlayer_GetShuffle(PortableServer_Servant servant, CORBA_Environment * ev)
{
   CORBA_boolean retval;

   if( context->plm ) {
     retval = context->plm->GetShuffleMode();
   } else {
     retval = false;
   }

   return retval;
}

static void
impl_MusicPlayer_SetShuffle(PortableServer_Servant servant,
                 const CORBA_boolean value, CORBA_Environment * ev)
{
  if( context->plm ) {
    context->plm->SetShuffleMode(value);
  }
}

static CORBA_long
impl_MusicPlayer_GetRepeat(PortableServer_Servant servant, CORBA_Environment * ev)
{
   CORBA_long retval = 1;

   if( context->plm ) {
     switch( context->plm->GetRepeatMode() )
       {
       case kPlaylistMode_RepeatNone:
         retval = 1; break;
       case kPlaylistMode_RepeatOne:
         retval = 2; break;
       case kPlaylistMode_RepeatAll:
         retval = 3; break;
       }
   }
   
   return retval;
}

static void
impl_MusicPlayer_SetRepeat(PortableServer_Servant servant,
                const CORBA_long value, CORBA_Environment * ev)
{
  if( context->plm ) {

    RepeatMode repeat = kPlaylistMode_RepeatNone;
    switch( value ) 
      {
      case 2:
        repeat = kPlaylistMode_RepeatOne; break;
      case 3:
        repeat = kPlaylistMode_RepeatAll; break;
      default:
        repeat = kPlaylistMode_RepeatNone; break;
      }

    context->plm->SetRepeatMode( repeat );
  }
}

static void
impl_MusicPlayer_GetVolume(PortableServer_Servant servant,
                MusicPlayer_Volume * volume, CORBA_Environment * ev)
{
  // there is no good way to get the volume without blocking.
  volume->left = 50;
  volume->right = 50;
}

static void
impl_MusicPlayer_SetVolume(PortableServer_Servant servant,
                const MusicPlayer_Volume * volume, CORBA_Environment * ev)
{
  Event *e = new VolumeEvent(CMD_SetVolume, volume->left, volume->right );
  context->target->AcceptEvent(e);
}


static CORBA_char*
impl_MusicPlayer_GetCurrentSong(PortableServer_Servant servant, 
                         CORBA_Environment * ev)
{
   CORBA_char *retval = NULL;

   PlaylistItem *entry = context->plm->ItemAt( context->plm->GetCurrentIndex() );

   if( entry != NULL && entry->URL().c_str() )
     retval=CORBA_string_dup( entry->URL().c_str() );
   else
     retval=CORBA_string_dup( "" );

   return retval;
}


static CORBA_long
impl_MusicPlayer_GetTotalTime(PortableServer_Servant servant, CORBA_Environment * ev)
{
   CORBA_long retval;
   
   retval = mediaInfoEvent.m_totalMilliSeconds;

   return retval;
}

static CORBA_long
impl_MusicPlayer_GetCurrentTime(PortableServer_Servant servant, CORBA_Environment * ev)
{
   CORBA_long retval;
   
   timeval currentTime;
   gettimeofday( &currentTime, NULL );

   retval = (currentTime.tv_sec -startTime.tv_sec)*1000 + 
            (currentTime.tv_usec-startTime.tv_usec)/1000;
   
   if( retval < 0 )
     retval = 0;

   return retval;
}

static void
impl_MusicPlayer_SetCurrentTime(PortableServer_Servant servant,
                   const CORBA_unsigned_long time,
                   CORBA_Environment * ev)
{
  // todo
}

static void
impl_MusicPlayer_GetPlaylist(PortableServer_Servant servant,
                  MusicPlayer_StringList ** list, CORBA_Environment * ev)
{
    
    uint32_t numEntries = context->plm->CountItems();
#define CORBADEBUG
#ifdef CORBADEBUG
    printf("numEntries: %d\n", numEntries);
#endif

    *list = MusicPlayer_StringList__alloc();

    if( list != NULL ) {

      (*list)->_length  = numEntries;
      (*list)->_maximum = (*list)->_length;
      (*list)->_buffer  = CORBA_sequence_CORBA_string_allocbuf( (*list)->_length);
      (*list)->_release = CORBA_TRUE;


      for( uint32_t i=0; i < numEntries; i++) {
        PlaylistItem *entry = context->plm->ItemAt(i);
        if( entry != NULL && entry->URL().c_str() )
          (*list)->_buffer[i]=CORBA_string_dup( entry->URL().c_str() );
        else
          (*list)->_buffer[i]=CORBA_string_dup( "" );

#ifdef CORBADEBUG
        printf("%i -> %s\n", i, (*list)->_buffer[i]);
#endif
      }

#ifdef CORBADEBUG
      printf("<- zinf_getplaylist\n");
#endif

    } // if list != null
}

static void
impl_MusicPlayer_SetPlaylist(PortableServer_Servant servant,
                  const MusicPlayer_StringList * list, CORBA_Environment * ev)
{
    if( list == NULL )
      return;

    // copy the list to a vector of strings
    std::vector<std::string> songList;

    for( uint32_t i=0; i<list->_length; i++ )
      {
        songList.push_back( list->_buffer[i] );
      }

    context->plm->RemoveAll();
    context->plm->AddItems( songList );
}

static CORBA_unsigned_long
impl_MusicPlayer_GetPlaylistPos(PortableServer_Servant servant, CORBA_Environment * ev)
{
   CORBA_unsigned_long retval;
   retval = context->plm->GetCurrentIndex();

   return retval;
}

static void
impl_MusicPlayer_SetPlaylistPos(PortableServer_Servant servant,
                   const CORBA_unsigned_long number,
                   CORBA_Environment * ev)
{
    context->plm->SetCurrentIndex(number);
}

static void
impl_MusicPlayer_AddSong(PortableServer_Servant servant,
              const CORBA_char * url, CORBA_Environment * ev)
{
    context->plm->AddItem(url);
}

static void
impl_MusicPlayer_DeleteNumber(PortableServer_Servant servant,
                   const CORBA_unsigned_long number,
                   CORBA_Environment * ev)
{
    context->plm->RemoveItem(number);
}

}

void Exception( CORBA_Environment& ev ) 
{

}

/** creates the corba objects and run corba server.
 *  @see http://www.lausch.at/gnome/programming/simple-calculator-server.html
 */
void 
corba_run( void* ) 
{
  if( zinf_client != CORBA_OBJECT_NIL )
    return;

  printf( "Debug::Corba::corba_run\n");

  int argc=1;
  char *argv;
  char tmpbuf[1] = {0};

  // :TODO: this should be fixed to pass on argv?
  argv=&tmpbuf[0]; 
        
  CORBA_Environment ev;
  CORBA_exception_init(&ev); 

  // --- get root poa
  CORBA_ORB orb = CORBA_ORB_init(&argc, &argv, "orbit-local-orb", &ev);
  Exception(ev);
  PortableServer_POA root_poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(orb, "RootPOA", &ev);
  Exception(ev);

  zinf_client = impl_MusicPlayer__create( root_poa, &ev );
  Exception(ev);

  // PortableServer_POA_servant_to_reference(poa, &impl_MusicPlayer_vepv, &ev);
  if (!zinf_client) 
    {
      printf("Cannot get objref\n");
      return;
    }
      
  // --- write the object reference to home/.zinf.ior
  std::string iorfile = std::string( getenv("HOME") )+"/.MusicPlayer.ior";
  CORBA_char* objref = CORBA_ORB_object_to_string(orb, zinf_client, &ev);
  Exception(ev);

  FILE* ofp = fopen(iorfile.c_str(),"w");
  fprintf(ofp,"%s", objref);
  fclose(ofp);
    
  CORBA_free(objref); // not sure if this is right(Ralf)

  // --- activate the manager object
  PortableServer_POAManager pm = PortableServer_POA__get_the_POAManager(root_poa, &ev);
  Exception(ev);
  PortableServer_POAManager_activate(pm, &ev);
  Exception(ev);

  fprintf(stdout,"MusicPlayer-CORBA Ready. | Waiting for commands.\n");
  fflush(stdout);
  CORBA_ORB_run(orb, &ev);

  // todo...impl_MusicPlayer__destroy( zinf_client, &ev );
  zinf_client = CORBA_OBJECT_NIL;
}



corbaUI::corbaUI(FAContext * myContext)
{

  context = myContext;

 // initialize song start time with current time
  gettimeofday( &startTime, NULL );

  // start corba now. No need to wait for Init

  printf("Debug::Corba::Init\n");

  if( corbaServerThread == NULL ) 
    {
      corbaServerThread = Thread::CreateThread();
      corbaServerThread->Create( corba_run, NULL );
      printf("Debug::Corba::created thread\n");
    }
}

corbaUI::~corbaUI()
{
  if( corbaServerThread )
    {
      corbaServerThread->Destroy();
      delete corbaServerThread;
      corbaServerThread = NULL;
    }
}


Error     
corbaUI::AcceptEvent(Event * e)
{
  assert( e!=NULL );

  // cout << "corbaUI: processing event " << e->getEvent() << endl;
  switch (e->Type())
    {
    case INFO_PlaylistDonePlay:
      {
        //              Event    *e = new Event(CMD_QuitPlayer);
        
        //              m_playerEQ->AcceptEvent(e);
        //              break;
      }
    case CMD_Cleanup:
      {
        // TODO: close corba
        
        // why does I have to send this event?
        Event *e = new Event(INFO_ReadyToDieUI);
        context->target->AcceptEvent(e);
        break;
      }
    case INFO_ErrorMessage:
      {
        ErrorMessageEvent *eme = (ErrorMessageEvent *)e;
        string ErrMessage(eme->GetErrorMessage());
        
        cout << ErrMessage << endl;
        break;
      }
    case INFO_MediaInfo:
      {
        // we just save the event. Maybe we can use it later.
        mediaInfoEvent = *(MediaInfoEvent *)e;
        break;
      }
    case INFO_MediaTimeInfo:
      {
        MediaTimeInfoEvent *info = (MediaTimeInfoEvent *) e;
        
        gettimeofday( &startTime, NULL );

        
        startTime.tv_sec  -=  info->m_currentMilliSeconds/1000;
        startTime.tv_usec -= (info->m_currentMilliSeconds%1000)*1000;
        if( startTime.tv_usec < 0 ) 
          {
            startTime.tv_sec--;
            startTime.tv_usec += 1000000;
          }

        break;
      }
    case INFO_MPEGInfo:
      {
        // we just save the event. Maybe we can use it later.
        mpegInfoEvent = *(MpegInfoEvent *)e;
        break;
      }
    default:
      break;
    }

  return kError_NoErr;
}

// arch-tag: 326b2b4e-56b2-4080-9970-a4d35e7f8634

Generated by  Doxygen 1.6.0   Back to index