session.cc
上传用户:psq1974
上传日期:2007-01-06
资源大小:1195k
文件大小:16k
源码类别:

mpeg/mp3

开发平台:

C/C++

  1. /* Copyright (C) 1998, 1999 State University of New York at Stony Brook
  2.    Author: Andrew V. Shuvalov ( andrew@ecsl.cs.sunysb.edu )
  3.    Software license is located in file "COPYING"
  4. */
  5. #include <gtk--.h>
  6. #include <fcntl.h>
  7. #include "gtk_main_win.h"
  8. #include "gtk_text_win.h"
  9. #include "gtk_search_win.h"
  10. #include "gtk_superuser.h"
  11. #include "db_connection.h"
  12. #include "word_db.h"
  13. #include "playback_window.h"
  14. #include "broadcast_win.h"
  15. #include "session.h"
  16. Session::Session( int *pargc, char ***pargv ) : Gtk_Main( pargc, pargv ),
  17.   playbackWindow( 0 ), preferencesWindow( 0 ), searchSystem( 0 ),
  18.   searchWindow( 0 ), suLoginWindow( 0 ), suPrefWindow( 0 ),
  19.   broadcastWindow( NULL ), superuser( false )
  20. {
  21.   // first init environment
  22.   loadAllConfig();
  23.   mainWindow = new MainWindow( *this );
  24.   mainWindow->set_usize
  25.     ( topWindowInitSizeX, topWindowInitSizeY ); 
  26.   mainWindow->show();
  27.   dbConnection = new DbConnection();
  28.   wordDb = new WordDb();
  29.   // add the timeout callback
  30.   connect_to_method( Gtk_Main::timeout( 100 ), 
  31.      this, &Session::timeout );
  32.   argv0 = *pargv[0];
  33. }
  34. void Session::cleanup()
  35. {
  36.   cerr << "cleanup..." << endl;
  37.   if( playbackWindow )
  38.     {
  39.       playbackWindow->prepare_to_die();
  40.       delete playbackWindow;
  41.       playbackWindow = 0;
  42.     }
  43. }
  44. void Session::loadAllConfig()
  45. {
  46.   string home = getenv( "HOME" );
  47.   if( home.length() == 0 )
  48.     throw GeneralException( "environment HOME must be defined" );
  49.   mkdir( ( home + "/.vclient" ).c_str(), 0750 );
  50.   gdbmMainConfigFile = home + "/.vclient/maincnf";
  51.   GDBM_FILE dbf = gdbm_open( (char *)gdbmMainConfigFile.c_str(), 1024, 
  52.      GDBM_WRCREAT, 0750, NULL );
  53.   if( !dbf )
  54.     throw GeneralException( "can't open/create database %s", 
  55.     gdbmMainConfigFile.c_str() );
  56.   
  57.   // defaults
  58.   homeLibPath.init( dbf, "Home path to vclient package", "homelib", 
  59.     "/usr/local/vclient", this );
  60.   notLoadedPixmap.init
  61.     ( dbf, "Pixmap of movie, not loaded locally", "notloadxpm", 
  62.       ( homeLibPath.str() + "/images/g_yellow.xpm" ).c_str(), this );
  63.   loadedPixmap.init
  64.     ( dbf, "Pixmap of movie loaded locally", "loadxpm",
  65.       ( homeLibPath.str() + "/images/g_yellow_on.xpm" ).c_str(), this );
  66.   PlayPixmap.init( dbf, "Play pixmap", "playxpm",
  67.    ( homeLibPath.str() + "/images/play.xpm" ).c_str(), this );
  68.   StopPixmap.init( dbf, "Stop pixmap", "stopxpm",
  69.    ( homeLibPath.str() + "/images/stop.xpm" ).c_str(), this );
  70.   RecPixmap.init( dbf, "Record pixmap", "recxpm", 
  71.   ( homeLibPath.str() + "/images/record.xpm" ).c_str(), this );
  72.   movieDbServerName.init(dbf,"The name of movie database server", "dbservname",
  73.  "localhost", this );
  74.   movieDbServerSock.init( dbf, "TCP Socket of movie database server", 
  75.   "dbservsock", "7077", this );
  76.   best1PushServIP.init( dbf, "IP of the most preferred push server", 
  77. "best1puship", "127.0.0.1", this );
  78.   best2PushServIP.init( dbf, "IP of the second preferred push server", 
  79. "best2puship", "127.0.0.1", this );
  80.   inputPushSock.init( dbf, "UDP Socket for incoming push-video server packets",
  81.          "pushlocalsock", "7079", this );
  82.   //  pushVideoServerName.init(dbf, "The name of push-video server","pushservname",
  83.   //    "localhost", this );
  84.   //  pushVideoServerSock.init( dbf, "control UDP Socket of push-video server",
  85.   //     "pushservsock", "7078", this );
  86.   
  87.   //  broadcastChannelNumber.init( dbf, "number of broadcast channels",
  88.   //        "channelsnum", "1", this );
  89.   // reserve space in channels prefernces:
  90.   //  inputPushBroadcastServer.reserve( broadcastChannelNumber );
  91.   //  inputPushBroadcastSock.reserve( broadcastChannelNumber );
  92.   // loop over all channels
  93.   //    for( int i = 0; i < broadcastChannelNumber; i++ )
  94.   //      {
  95.   //        char buf[10];
  96.   //        snprintf( buf, sizeof( buf ), "%d", i );
  97.   //        inputPushBroadcastServer[i] = new ConfigItemStr();
  98.   //        inputPushBroadcastServer[i]->init
  99.   //   ( dbf, ( string( "server name for incoming push-video broadcast "
  100.   //    "packets( Optional ). Channel " ) + buf ).c_str(),
  101.   //     ( string( "pushbroadcastserver" ) + buf ).c_str(),
  102.   //     "", this );
  103.   //        inputPushBroadcastSock[i] = new ConfigItemInt();
  104.   //        inputPushBroadcastSock[i]->init
  105.   //   ( dbf, ( string( "UDP Socket for incoming push-video "
  106.   //    "broadcast packets. Channel " ) + buf ).c_str(),
  107.   //     ( string( "pushbroadcastsock" ) + buf ).c_str(),
  108.   //     "7080", this );
  109.   //      }
  110.   mtvPlayerName.init( dbf, "MpegTV player executable name",
  111.       "mpegtvexec", "mtvp", this );
  112.   mtvPlayerArguments.init( dbf, "MpegTV player execute arguments ( optional )",
  113.    "mpegtvexargs", "", this );
  114.   sihPlugin.init( dbf, "Video player SII plugin", "sihPlugin", 
  115.   "/usr/local/lib/libvclientsih.so", this );
  116.   topWindowInitSizeX.init( dbf, "Initial X size of main window", "topxs",
  117.    "600", this );
  118.   topWindowInitSizeY.init( dbf, "Initial Y size of main window", "topys",
  119.    "500", this );
  120.   verbose.init( dbf, "Verbose level (0,1..)", "verbose",
  121. "1", this );
  122.   vServVerbose.init(dbf, "Remote server verbose level (0,1..)", 
  123.     "verboseRemote", "1", this );
  124.   receiveBufferSize.init( dbf, "Input Mpeg stream buffer size", 
  125.   "receiveBufferSize", "1000000", this );
  126.   receiveBufferLowWaterMark.init( dbf, "Input buffer low water mark", 
  127.   "receiveBufferSize", "400000", this );
  128.   receiveBufferHighWaterMark.init( dbf, "Input buffer low water mark", 
  129.    "receiveBufferSize", "800000", this );
  130.   gdbm_close( dbf );
  131. }
  132. void Session::saveAllConfig()
  133. {
  134.   GDBM_FILE dbf = gdbm_open( (char *)gdbmMainConfigFile.c_str(), 1024, 
  135.      GDBM_WRCREAT, 0750, NULL );
  136.   if( !dbf )
  137.     throw GeneralException( "can't open/create database %s", 
  138.     gdbmMainConfigFile.c_str() );
  139.   
  140.   for( int i = 0; i < configItems.size(); i++ ) 
  141.     {
  142.       configItems[i]->store( dbf );
  143.     }
  144.   gdbm_close( dbf );
  145. }
  146. void Session::run()
  147. {
  148.   // default
  149.   mainWindow->display_messagenl( "Start video server client" );
  150.   connect_to_dbserver();
  151.   vector< string > msgs;
  152.   string dbname = dbConnection->get_database_name( msgs );
  153.   if( msgs.size() )
  154.     mainWindow->display_messages( msgs );
  155.   // make this database current
  156.   update_movie_list( dbname );
  157.   Gtk_Main::run();
  158. }
  159. void Session::connect_to_dbserver()
  160. {
  161.   if( dbConnection )
  162.     {
  163.       delete dbConnection;
  164.       dbConnection = NULL;
  165.     }
  166.   try {
  167.     dbConnection = new DbConnection();
  168.     dbConnection->connect( movieDbServerName.c_str(), 
  169.    movieDbServerSock );
  170.     vector< string > msgs;
  171.     dbConnection->wait_input();  // this means that something is expected,
  172.     //                           // at least the prompt
  173.     dbConnection->skip_to_prompt( msgs );
  174.     if( msgs.size() )
  175.       mainWindow->display_messages( msgs );
  176.     msgs.clear();
  177.     // let's debug
  178.     dbConnection->set_debug( msgs, verbose );
  179.     // display current db name
  180.     string dbname = dbConnection->get_database_name( msgs );
  181.     if( msgs.size() )
  182.       mainWindow->display_messages( msgs );
  183.     msgs.clear();
  184.     mainWindow->display_messagenl( "Connected to database " + dbname );
  185.     mainWindow->display_database_name( dbname );
  186.   }
  187.   catch( NetworkException e ) {
  188.     mainWindow->display_messagenl( "Network exception" );
  189.     mainWindow->display_messagenl( e.getText() );
  190.   }
  191.   catch( SyntaxException e ) {
  192.     mainWindow->display_messagenl( "Syntax exception" );
  193.     mainWindow->display_messagenl( e.getText() );
  194.   }
  195.   catch( DatabaseException e ) {
  196.     mainWindow->display_messagenl( "Database exception" );
  197.     mainWindow->display_messagenl( e.getText() );
  198.     delete dbConnection;
  199.     dbConnection = NULL;
  200.   }
  201. }
  202. void Session::update_movie_list( const string &dbname )
  203. {
  204.   vector< string > msgs;
  205.   if( !dbConnection )
  206.     {
  207.       connect_to_dbserver();
  208.     }
  209.   if( !dbConnection ) // still
  210.     {
  211.       put_message( 0, "update movie list: not connected" );
  212.       return;   // well, i'm sorry
  213.     }
  214.   try {
  215.     dbConnection->load_new_database( msgs, dbname );
  216.   } catch( DatabaseException e ) {
  217.     mainWindow->display_messagenl( "Database exception" );
  218.     mainWindow->display_messagenl( e.getText() );
  219.     delete dbConnection;
  220.     dbConnection = NULL;
  221.     const map< int, MovieItem > movies;
  222.     // display empty list
  223.     mainWindow->update_movie_list( movies );
  224.     return;
  225.   }
  226.   if( msgs.size() )
  227.     mainWindow->display_messages( msgs );
  228.   msgs.clear();
  229.   const map< int, MovieItem >& movies = dbConnection->get_movies();
  230.   mainWindow->update_movie_list( movies );
  231. }
  232. // ----------------------------- called by mainWindow ----------------------
  233. const MovieItem &Session::get_movie_by_id( int id ) const
  234.   static MovieItem nothing;
  235.   if( !dbConnection )
  236.     return nothing;
  237.   
  238.   return dbConnection->get_movie_by_id( id ); 
  239. }
  240. void Session::display_movie_text_window( int id, time_t timepos )
  241. {
  242.   if( textWindowsMap.find( id ) == textWindowsMap.end() )
  243.     {
  244.       // create 
  245.       TextWindow *win = new TextWindow( id, *this );
  246.       textWindowsMap[ id ] = win;
  247.       win->show();
  248.       if( timepos > 0 )
  249. win->select_text_line_by_time( timepos );
  250.     }
  251.   else
  252.     {
  253.       textWindowsMap[ id ]->show();
  254.       if( timepos > 0 )
  255. textWindowsMap[ id ]->select_text_line_by_time( timepos );
  256.     }
  257. }
  258. void Session::display_movie_text_window_go_line( int id, unsigned linenum )
  259. {
  260.   display_movie_text_window( id );
  261.   textWindowsMap[ id ]->select_text_line( linenum );
  262. }
  263. void Session::edit_preferences()
  264. {
  265.   if( !preferencesWindow )
  266.     preferencesWindow = new PrefWindow( *this );
  267.   preferencesWindow->show();
  268. }
  269. // ----------------------------- called by textWindow ----------------------
  270. const TextOfMovieT *Session::get_movie_text( int id )
  271. {
  272.   if( !dbConnection )
  273.     return NULL;
  274.   {
  275.     const TextOfMovieT *tom = wordDb->get_movie_text( id );
  276.     if( tom )
  277.       return tom;
  278.   }
  279.   // try to load text from database
  280.   TextOfMovieT *tom = new TextOfMovieT();
  281.   vector< string > msgs;
  282.   dbConnection->load_movie_text( msgs, id, tom );
  283.   wordDb->add_new_movie_text( id, tom );
  284.   if( msgs.size() )
  285.     mainWindow->display_messages( msgs );
  286.   msgs.clear();
  287.   mainWindow->update_pixmap_by_id( id );
  288.   return tom;
  289. }
  290. bool Session::is_movie_text_loaded( int id )
  291. {
  292.   const TextOfMovieT *tom = wordDb->get_movie_text( id );
  293.   return tom != NULL;
  294. }
  295. int Session::close_text_window( GdkEventAny *ev )
  296. {
  297.   int id = (int) gtk_object_get_user_data( GTK_OBJECT( ev->window ));
  298.   cout << "destroy " << id << endl;
  299.   if( textWindowsMap.find( id ) == textWindowsMap.end() )
  300.     return 0;
  301.   textWindowsMap[ id ] = NULL;
  302.   textWindowsMap.erase( id );
  303.   return 0;
  304. }
  305. void Session::menu_close_text_window( int id )
  306. {
  307.   if( textWindowsMap.find( id ) == textWindowsMap.end() )
  308.     return;
  309.   cout << "destroy menu " << id << endl;
  310.   textWindowsMap[ id ]->hide();
  311. }
  312. void Session::notify_text_win_die( int movieId )
  313. {
  314.   if( textWindowsMap.find( movieId ) == textWindowsMap.end() )
  315.     return;
  316.   cout << "die " << movieId << endl;
  317.   textWindowsMap[ movieId ] = NULL;
  318.   //  delete textWindowsMap[ movieId ];
  319.   textWindowsMap.erase( movieId );
  320. }
  321. void Session::playVideo( TextWindow &tw, struct tm t, int id )
  322. {
  323.   if( !dbConnection )
  324.     return;
  325.   vector< string > msgs;
  326.   //  stop(); - it's bad idea to close and reopen socket
  327.   MovieFilesT movieFiles;
  328.   dbConnection->getMovieFileListByTime( id, t, movieFiles, *this, msgs );
  329.   if( !movieFiles.size() ) // nothing?
  330.     {
  331.       put_message( 1, "movie is empty, nothing to play" );
  332.       return;
  333.     }
  334.   try {
  335.     if( !playbackWindow )
  336.       playbackWindow = new PlaybackWindow( argv0.c_str(), *this );
  337.     playbackWindow->playback_mode( movieFiles, t, id );
  338.   } catch ( PlayerException e ) {
  339.     mainWindow->display_messagenl( e.getText() );
  340.     delete playbackWindow;
  341.     playbackWindow = 0;
  342.   }
  343.   if( msgs.size() )
  344.     mainWindow->display_messages( msgs );
  345. }
  346. void Session::playBroadcast( const string &url )
  347. {
  348.   try {
  349.     if( !playbackWindow )
  350.       playbackWindow = new PlaybackWindow( argv0.c_str(), *this );
  351.     playbackWindow->broadcast_mode( url );
  352.   } catch ( PlayerException e ) {
  353.     mainWindow->display_messagenl( e.getText() );
  354.     delete playbackWindow;
  355.     playbackWindow = 0;
  356.     return;
  357.   }
  358. }
  359. void Session::stop()
  360. {
  361.   if( !playbackWindow )
  362.     return;
  363.   playbackWindow->stop();
  364. }
  365. void Session::start_recording( int channel_id )
  366. {
  367.   if( !dbConnection )
  368.     {
  369.       put_message( 0, "!start recording: not connected" );
  370.       return;   // well, i'm sorry
  371.     }
  372.   
  373.   vector< string > msgs;
  374.   dbConnection->start_recording( channel_id, msgs );
  375.   if( msgs.size() )
  376.     mainWindow->display_messages( msgs );
  377. }
  378. void Session::stop_recording( int channel_id )
  379. {
  380.   if( !dbConnection )
  381.     {
  382.       put_message( 0, "!stop recording: not connected" );
  383.       return;   // well, i'm sorry
  384.     }
  385.   
  386.   vector< string > msgs;
  387.   dbConnection->stop_recording( channel_id, msgs );
  388.   if( msgs.size() )
  389.     mainWindow->display_messages( msgs );
  390. }
  391. void Session::select_text_line_by_time( int movieId, time_t t )
  392. {
  393.   textWindowsMapT::iterator win;
  394.   win = textWindowsMap.find( movieId );
  395.   if( win == textWindowsMap.end() )
  396.     return;
  397.   (*win).second->select_text_line_by_time( t );
  398. }
  399. /** called by broadcast window */
  400. void Session::fill_channellist( channel_infos_mapT &channel_infos_map )
  401. {
  402.   try {
  403.     if( !dbConnection )
  404.       return;
  405.     vector< string > msgs;
  406.     dbConnection->fill_channellist( msgs, channel_infos_map );
  407.     if( msgs.size() )
  408.       mainWindow->display_messages( msgs );
  409.   } catch( SyntaxException e ) {
  410.     channel_infos_map.clear();
  411.     put_message( 0, "fill_channellist: %s", e.getText().c_str() );
  412.   }
  413. }
  414. /** this is main destroy application callback. called from main window
  415.  */
  416. void Session::callback_destroy_session()
  417. {
  418.   cleanup();
  419.   cerr << "Hasta la vista!" << endl;
  420. }
  421. void Session::callback_search()
  422. {
  423.   if( !searchWindow )
  424.     searchWindow = new SearchWindow( *this );
  425.   searchWindow->show();
  426. }
  427. void Session::callback_superuser()
  428. {
  429.   if( !suLoginWindow )
  430.     suLoginWindow = new SuLoginWindow( *this );
  431.   suLoginWindow->show();
  432. }
  433. void Session::callback_server_preferences()
  434. {
  435.   if( ! suPrefWindow )
  436.     suPrefWindow = new SuperuserPreferenciesWindow( *this );
  437.   
  438.   suPrefWindow->show();
  439. }
  440. void Session::callback_broadcast()
  441. {
  442.   if( !broadcastWindow )
  443.     broadcastWindow = new BroadcastWindow( *this );
  444.   broadcastWindow->show();
  445. }
  446. void Session::loadServerProperties( ServerConfigItemVec &props )
  447. {
  448.   vector< string > msgs;
  449.   if( dbConnection )
  450.     dbConnection->loadServerProperties( msgs, props );
  451.   if( msgs.size() )
  452.     mainWindow->display_messages( msgs );
  453. }
  454. void Session::saveServerProperties( ServerConfigItemVec &props )
  455. {
  456.   vector< string > msgs;
  457.   if( dbConnection )
  458.     dbConnection->saveServerProperties( msgs, props );
  459.   if( msgs.size() )
  460.     mainWindow->display_messages( msgs );
  461. }
  462. void Session::login_superuser( string passwd )
  463. {
  464.   if( !dbConnection )
  465.     return;
  466.   vector< string > msgs;
  467.   try
  468.     {
  469.       if( dbConnection->login_superuser( passwd, msgs ))
  470. {
  471.   // success
  472.   mainWindow->show_superuser_status( true );
  473.   if( msgs.size() )
  474.     mainWindow->display_messages( msgs );
  475.   mainWindow->status_changed_to_superuser( true );
  476. }
  477.       else
  478. mainWindow->display_messagenl( "Superuser login denied" );
  479.     }
  480.   catch( DatabaseException e ) 
  481.     {
  482.       delete dbConnection;
  483.       dbConnection = NULL;
  484.       mainWindow->display_messagenl( "Disconnected from database server" );
  485.     }
  486. }
  487. // ----------------------------- called by timeout ----------------------
  488. gint Session::timeout()
  489. {
  490.   try 
  491.     {
  492.       if( playbackWindow )
  493. playbackWindow->timeout();
  494.     }
  495.   catch( PlayerException e ) {
  496.     mainWindow->display_messagenl( "Player exception" );
  497.     mainWindow->display_messagenl( e.getText() );
  498.     delete playbackWindow;
  499.     playbackWindow = NULL;
  500.   }
  501.   return true;
  502. }
  503. // ----------------------------- utils ---------------------------------
  504. void Session::put_message( int debl, const string &msg )
  505. {
  506.   if( debl <= verbose )
  507.     mainWindow->display_messagenl( msg );
  508. }
  509. void Session::put_message( int debl, const char *format, ... )
  510. {
  511.   if( debl > verbose )
  512.     return;
  513.   va_list ap;
  514.   va_start( ap, format );
  515.   char buf[1024];
  516.   vsnprintf( buf, sizeof( buf ), format, ap );
  517.   mainWindow->display_messagenl( buf );
  518.   va_end( ap );
  519. }
  520. // ----------*******---------- GeneralException ==========================
  521. GeneralException::GeneralException( const char *format, ... )
  522. {
  523.   va_list ap;
  524.   va_start( ap, format );
  525.   init( format, ap );
  526.   va_end( ap );
  527. }