home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / xmovie / mainwindow.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  13KB  |  556 lines

  1. #include "asset.h"
  2. #include "colormodels.h"
  3. #include "defaults.h"
  4. #include "file.h"
  5. #include "filesystem.h"
  6. #include "mainmenu.h"
  7. #include "mainwindow.h"
  8. #include "mwindowgui.h"
  9. #include "playbackengine.h"
  10. #include "playlist.h"
  11. #include "settings.h"
  12. #include "theme.h"
  13. #include "vframe.h"
  14. #include <string.h>
  15.  
  16. MainWindow::MainWindow(ArrayList<char*> *init_playlist)
  17. {
  18.     this->init_playlist = init_playlist;
  19.     engine = new PlaybackEngine(this);
  20.     defaults = new Defaults("~/.xmovierc");
  21.     defaults->load();
  22.     reset_parameters();
  23. }
  24.  
  25. MainWindow::~MainWindow()
  26. {
  27.     delete error_thread;
  28.     delete defaults;
  29.     delete gui;
  30.     if(asset) delete asset;
  31.     if(audio_file) delete audio_file;
  32.     if(video_file) delete video_file;
  33.     if(frame) delete frame;
  34.     if(playlist) delete playlist;
  35.     reset_parameters();
  36. }
  37.  
  38. int MainWindow::reset_parameters()
  39. {
  40.     audio_file = 0;
  41.     video_file = 0;
  42.     asset = 0;
  43.     frame = 0;
  44.     samplerate = 44100;
  45.     frame_rate = 10;
  46.     playlist = 0;
  47.     return 0;
  48. }
  49.  
  50. int MainWindow::create_objects()
  51. {
  52.     load_defaults();
  53.  
  54. // Create theme
  55.     theme = new GoldTheme;
  56.  
  57.     gui = new MWindowGUI(this, 
  58.                     defaults->get("X", INFINITY),
  59.                     defaults->get("Y", INFINITY),
  60.                     defaults->get("WIDTH", DEFAULTW), 
  61.                     defaults->get("HEIGHT", DEFAULTH));
  62.     gui->create_objects();
  63.     gui->load_defaults(defaults);
  64.     error_thread = new ErrorThread(gui);
  65.     gui->show_window();
  66.     return 0;
  67. }
  68.  
  69. void MainWindow::load_defaults()
  70. {
  71.     sprintf(default_path, "");
  72.     defaults->get("PATH", default_path);
  73.     every_frame = defaults->get("EVERYFRAME", 0);
  74.     aspect_w = defaults->get("ASPECTW", (float)4);
  75.     aspect_h = defaults->get("ASPECTH", (float)3);
  76.     letter_w = defaults->get("LETTERBOXW", (float)2.35);
  77.     letter_h = defaults->get("LETTERBOXH", (float)1);
  78.     smp = defaults->get("SMP", 0);
  79.     use_mmx = defaults->get("USE_MMX", 1);
  80.     square_pixels = defaults->get("ASPECTSQUARE", 0);
  81.     crop_letterbox = defaults->get("CROPLETTERBOX", 0);
  82.     convert_601 = defaults->get("601TORGB", 1);
  83.     audio_priority = defaults->get("AUDIOPRIORITY", 0);
  84.     software_sync = defaults->get("SOFTWARESYNC", 0);
  85.     prebuffer_size = defaults->get("PREBUFFER_SIZE", 2000000);
  86.     video_stream = defaults->get("VIDEOSTREAM", 0);
  87.     audio_stream = defaults->get("AUDIOSTREAM", 0);
  88. }
  89.  
  90. void MainWindow::save_defaults()
  91. {
  92.     gui->menu->save_loads(defaults);
  93.     gui->save_defaults(defaults);
  94.     defaults->update("EVERYFRAME", every_frame);
  95.     defaults->update("ASPECTW", aspect_w);
  96.     defaults->update("ASPECTH", aspect_h);
  97.     defaults->update("LETTERBOXW", letter_w);
  98.     defaults->update("LETTERBOXH", letter_h);
  99.     defaults->update("SMP", smp);
  100.     defaults->update("USE_MMX", use_mmx);
  101.     defaults->update("ASPECTSQUARE", square_pixels);
  102.     defaults->update("CROPLETTERBOX", crop_letterbox);
  103.     defaults->update("601TORGB", convert_601);
  104.     defaults->update("AUDIOPRIORITY", audio_priority);
  105.     defaults->update("PATH", default_path);
  106.     defaults->update("SOFTWARESYNC", software_sync);
  107.     defaults->update("CANVASW", canvas_w);
  108.     defaults->update("CANVASH", canvas_h);
  109.     defaults->update("PREBUFFER_SIZE", prebuffer_size);
  110.     defaults->update("VIDEOSTREAM", video_stream);
  111.     defaults->update("AUDIOSTREAM", audio_stream);
  112.     defaults->update("WIDTH", gui->get_w()), 
  113.     defaults->update("HEIGHT", gui->get_h());
  114.     defaults->update("X", gui->get_x());
  115.     defaults->update("Y", gui->get_y());
  116.     defaults->save();
  117. }
  118.  
  119. int MainWindow::run_program()
  120. {
  121.     gui->run_window();
  122.     return 0;
  123. }
  124.  
  125. int MainWindow::load_file(char *path, int use_locking)
  126. {
  127.     if(use_locking) gui->unlock_window();
  128.     stop_playback();
  129.     if(use_locking) gui->lock_window();
  130.     close_file();
  131.  
  132. // Check for playlist
  133.     playlist = new Playlist;
  134.     if(!playlist->load(path))
  135.     {
  136.         delete playlist;
  137.         playlist = 0;
  138.     }
  139.  
  140.     asset = new Asset(path);
  141.     File *test_file = new File(this);
  142.     current_percentage = 0;
  143.     current_time = 0;
  144.     gui->update_position();
  145.  
  146. // Load asset with information
  147.     test_file->set_prebuffer(prebuffer_size);
  148.     test_file->set_processors(smp ? 2 : 1);
  149.     test_file->set_mmx(use_mmx);
  150.     int result = test_file->open_file(asset);
  151.  
  152. // Open real files
  153.     if(!result)
  154.     {
  155. // success
  156.         if(asset->audio_data)
  157.         {
  158.             audio_file = test_file;
  159.             test_file = 0;
  160.             samplerate = asset->rate;
  161.             if(audio_stream >= asset->audio_streams) audio_stream = 0;
  162.             audio_file->set_audio_stream(audio_stream);
  163.             gui->menu->update_audio_streams(asset->audio_streams);
  164.         }
  165.  
  166. // Must open audio before this so FileMPEG can copy the tables
  167.         if(asset->video_data)
  168.         {
  169.             if(test_file)
  170.                 video_file = test_file;
  171.             else
  172.             {
  173.                 video_file = new File(this);
  174.                 video_file->set_prebuffer(prebuffer_size);
  175.                 video_file->set_processors(smp ? 2 : 1);
  176.                 video_file->set_mmx(use_mmx);
  177.                 video_file->open_file(asset);
  178.             }
  179.  
  180.             frame_rate = asset->frame_rate;
  181.             if(video_stream >= asset->video_streams) video_stream = 0;
  182.             video_file->set_video_stream(video_stream);
  183.             gui->menu->update_video_streams(asset->video_streams);
  184.         }
  185.  
  186.         if(asset->video_data)
  187.         {
  188. // resize frame for video
  189.             get_canvas_sizes(canvas_w);
  190.             gui->resize_canvas(canvas_w, canvas_h);
  191.         }
  192.         else
  193.         {
  194. // Shrink for audio
  195.             gui->resize_canvas(canvas_w, 0);
  196.         }
  197.  
  198.         FileSystem fs;
  199.         char string1[1024], string2[1024];
  200.         fs.extract_name(string1, asset->path);
  201.         sprintf(string2, "XMovie: %s", string1);
  202.         gui->set_title(string2);
  203.         gui->resize_scrollbar();
  204.         if(asset->video_data) flash_frame(current_percentage);
  205.         gui->update_position();
  206.         if(asset->video_data) gui->canvas->flash();
  207.         gui->menu->add_load(path);
  208.         return 0;
  209.     }
  210.     else
  211.     {
  212. // failure
  213.         switch(result)
  214.         {
  215.             case 1:
  216.                 error_thread->show_error("No such file or directory.");
  217.                 break;
  218.             case 2:
  219.                 error_thread->show_error("Unsupported file format.");
  220.                 break;
  221.             case 3:
  222.                 error_thread->show_error("The file contains no supported codecs.");
  223.                 break;
  224.         }
  225.         delete asset;
  226.         asset = 0;
  227.         return 1;
  228.     }
  229.     return 0;
  230. }
  231.  
  232. int MainWindow::set_audio_stream(int stream_number)
  233. {
  234.     this->audio_stream = stream_number;
  235.     audio_file->set_audio_stream(stream_number);
  236.     gui->menu->update_audio_streams(asset->audio_streams);
  237.     return 0;
  238. }
  239.  
  240. int MainWindow::set_video_stream(int stream_number)
  241. {
  242.     this->video_stream = stream_number;
  243.     video_file->set_video_stream(stream_number);
  244.     gui->menu->update_video_streams(asset->video_streams);
  245.     return 0;
  246. }
  247.  
  248. float MainWindow::get_aspect_ratio()
  249. {
  250.     if(square_pixels && asset && asset->video_data)
  251.         return (float)asset->width / asset->height;
  252.     else
  253.         return aspect_w / aspect_h;
  254.     return 0;
  255. }
  256.  
  257. int MainWindow::get_canvas_sizes(int width_given)
  258. {
  259.     float aspect_ratio = get_aspect_ratio();
  260.     float letterbox_ratio = letter_w / letter_h;
  261.  
  262.     if(!asset || !asset->video_data) return 1;
  263.  
  264. // Scale sizes to aspect ratio
  265.     canvas_w = width_given;
  266.     canvas_h = (int)((float)width_given / aspect_ratio);
  267.     input_w = asset->width;
  268.     input_h = asset->height;
  269.  
  270. // Crop sizes to letterbox ratio
  271.     if(crop_letterbox)
  272.     {
  273.         int old_canvas_h = canvas_h, old_canvas_w = canvas_w;
  274.         if(letterbox_ratio > aspect_ratio)
  275.         {
  276.             canvas_h = (int)(canvas_w / letterbox_ratio);
  277.             input_h = (int)(input_h * (float)canvas_h / old_canvas_h);
  278.         }
  279.         else
  280.         {
  281.             input_w = (int)(input_w * ((float)canvas_h * letterbox_ratio) / old_canvas_w);
  282.             canvas_h = (int)(canvas_w / letterbox_ratio);
  283.         }
  284.     }
  285.     return 0;
  286. }
  287.  
  288. int MainWindow::get_full_size(int &full_w, int &full_h)
  289. {
  290.     float aspect_ratio = get_aspect_ratio();
  291.     float letterbox_ratio = letter_w / letter_h;
  292.  
  293.     if(!asset) return 1;
  294.  
  295.     if(aspect_ratio > (float)asset->width / asset->height)
  296.     {
  297.         full_w = (int)((float)asset->height * aspect_ratio + 0.5);
  298.         full_h = asset->height;
  299.     }
  300.     else
  301.     {
  302.         full_w = asset->width;
  303.         full_h = (int)((float)asset->width / aspect_ratio + 0.5);
  304.     }
  305.  
  306.     if(crop_letterbox)
  307.     {
  308.         full_h = (int)(full_w / letterbox_ratio);
  309.     }
  310.     return 0;
  311. }
  312.  
  313. int MainWindow::get_yuv_cropping(int &x, int &y, int &w, int &h)
  314. {
  315.     x = 0;
  316.     w = asset->width;
  317.  
  318.     if(crop_letterbox && letter_w > letter_h)
  319.     {
  320.         float aspect_ratio = get_aspect_ratio();
  321.         float letterbox_ratio = letter_w / letter_h;
  322.  
  323.         h = (int)(((float)asset->width / letterbox_ratio) / ((float)asset->width / aspect_ratio) * asset->height + 0.5);
  324.         y = (int)((float)(asset->height - h) / 2 + 0.5);
  325.     }
  326.     else
  327.     {
  328.         h = asset->height;
  329.         y = 0;
  330.     }
  331.     return 0;
  332. }
  333.  
  334. int MainWindow::original_size(float percent)
  335. {
  336.     if(asset && asset->video_data)
  337.     {
  338.         if(!gui->yuv_bitmap)
  339.         {
  340.             gui->unlock_window();
  341.             stop_playback();
  342.             gui->lock_window();
  343.         }
  344.  
  345.         get_full_size(canvas_w, canvas_h);
  346.         gui->resize_canvas((int)(canvas_w * percent), (int)(canvas_h * percent));
  347.  
  348.         if(!gui->canvas->video_is_on())
  349.         {
  350.             flash_frame(current_percentage);
  351.             gui->canvas->flash();
  352.         }
  353.     }
  354.     return 0;
  355. }
  356.  
  357. // Display frame when paused
  358. int MainWindow::flash_frame(double percentage)
  359. {
  360.     if(asset && asset->video_data)
  361.     {
  362.         double fake_percentage;
  363.         if(!frame) this->frame = new VFrame(0, asset->width, asset->height, BC_RGB888);
  364.  
  365.         video_file->lock_read();
  366.         video_file->set_position(percentage);
  367.         video_file->read_frame(this->frame->get_data());
  368.         video_file->unlock_read();
  369.         gui->flash_frame(this->frame);
  370.         video_file->get_position(fake_percentage, current_time);
  371.         gui->update_position();
  372.     }
  373.     else
  374.     if(asset && asset->audio_data)
  375.     {
  376.         audio_file->set_position(percentage);
  377.         audio_file->get_position(current_percentage, current_time);
  378.         gui->update_position();
  379.     }
  380.     return 0;
  381. }
  382.  
  383. int MainWindow::frame_forward()
  384. {
  385.     if(asset)
  386.     {
  387.         if(asset->video_data)
  388.         {
  389. // Read the next frame
  390.             if(!frame) this->frame = new VFrame(0, asset->width, asset->height, BC_RGB888);
  391.             video_file->lock_read();
  392.             video_file->read_frame(this->frame->get_data());
  393.             video_file->unlock_read();
  394.             gui->flash_frame(this->frame);
  395.             gui->canvas->flash();
  396.             video_file->get_position(current_percentage, current_time);
  397.             gui->update_position();
  398.         }
  399.         else
  400.         if(asset->audio_data)
  401.         {
  402. // Read a second of audio
  403.             video_file->set_position(current_percentage);
  404.             video_file->set_audio_position(video_file->get_audio_position() + asset->rate);
  405.             video_file->get_position(current_percentage, current_time);
  406.             gui->update_position();
  407.         }
  408.     }
  409.     return 0;
  410. }
  411.  
  412. int MainWindow::frame_backward()
  413. {
  414.     if(asset)
  415.     {
  416.         if(asset->video_data)
  417.         {
  418.             if(!frame) this->frame = new VFrame(0, asset->width, asset->height, BC_RGB888);
  419.  
  420.             video_file->lock_read();
  421.             video_file->frame_back();
  422.             video_file->read_frame(this->frame->get_data());
  423.             video_file->frame_back();
  424.             video_file->frame_back();
  425.             video_file->unlock_read();
  426.  
  427.             gui->flash_frame(this->frame);
  428.             gui->canvas->flash();
  429.             video_file->get_position(current_percentage, current_time);
  430.             gui->update_position();
  431.         }
  432.         else
  433.         if(asset->audio_data)
  434.         {
  435.             video_file->set_position(current_percentage);
  436.             video_file->set_audio_position(video_file->get_audio_position() - asset->rate);
  437.             video_file->get_position(current_percentage, current_time);
  438.             gui->update_position();
  439.         }
  440.     }
  441.     return 0;
  442. }
  443.  
  444.  
  445. // Arm frame during playback
  446. int MainWindow::arm_frame()
  447. {
  448.     if(asset && asset->video_data)
  449.     {
  450.         if(gui->playback_colormodel == BC_YUV420P)
  451.         {
  452.             char *y_output = (char*)gui->yuv_bitmap->get_y_plane();
  453.             char *u_output = (char*)gui->yuv_bitmap->get_u_plane();
  454.             char *v_output = (char*)gui->yuv_bitmap->get_v_plane();
  455.             int in_x, in_y, in_w, in_h;
  456.  
  457.             get_yuv_cropping(in_x, in_y, in_w, in_h);
  458.  
  459.             in_w = gui->yuv_bitmap->get_w() < in_w ? gui->yuv_bitmap->get_w() : in_w;
  460.             in_h = gui->yuv_bitmap->get_h() < in_h ? gui->yuv_bitmap->get_h() : in_h;
  461.             video_file->lock_read();
  462.             video_file->read_yuv_buffer(y_output, u_output, v_output, in_x, in_y, in_w, in_h);
  463.             video_file->unlock_read();
  464.         }
  465.         else
  466.         if(video_file->frame_buffer_copy_possible(gui->bitmap->get_color_model()))
  467.         {
  468.             unsigned char **frame_buffer = gui->bitmap->get_row_pointers();
  469.             int color_model = gui->bitmap->get_color_model();
  470.  
  471.             video_file->lock_read();
  472.             video_file->read_frame_buffer(frame_buffer, 
  473.                 gui->bitmap->get_w(), 
  474.                 gui->bitmap->get_h(), 
  475.                 color_model);
  476.             video_file->unlock_read();
  477.         }
  478.         else
  479.         {
  480.             if(!frame) this->frame = new VFrame(0, asset->width, asset->height, BC_RGB888);
  481.  
  482.             video_file->lock_read();
  483.             video_file->read_frame(this->frame->get_data());
  484.             video_file->unlock_read();
  485.         }
  486.     }
  487.     return 0;
  488. }
  489.  
  490. // Show frame during playback
  491. int MainWindow::flash_armed_frame()
  492. {
  493.     if(asset && asset->video_data)
  494.     {
  495.         if(video_file->frame_buffer_copy_possible(gui->bitmap->get_color_model()))
  496.         {
  497.             gui->flash_frame(0);
  498.         }
  499.         else
  500.         {
  501.             if(this->frame)
  502.                 gui->flash_frame(this->frame);
  503.         }
  504.     }
  505.     return 0;
  506. }
  507.  
  508. int MainWindow::close_file()
  509. {
  510.     if(audio_file)
  511.     {
  512.         audio_file->close_file();
  513.         delete audio_file;
  514.     }
  515.     if(video_file)
  516.     {
  517.         video_file->close_file();
  518.         delete video_file;
  519.     }
  520.     if(playlist)
  521.     {
  522.         delete playlist;
  523.     }
  524.  
  525.     if(asset) delete asset;
  526.     if(frame) delete frame;
  527.     reset_parameters();
  528.     return 0;
  529. }
  530.  
  531. int MainWindow::exit_cleanly()
  532. {
  533.     close_file();
  534.     save_defaults();
  535.     return 0;
  536. }
  537.  
  538. int MainWindow::start_playback()
  539. {
  540.     if(asset)
  541.         engine->start_playback();
  542.  
  543.     return 0;
  544. }
  545.  
  546. int MainWindow::stop_playback()
  547. {
  548.     if(asset)
  549.         engine->stop_playback();
  550.  
  551.     gui->lock_window();
  552.     gui->playbutton->set_mode(0);
  553.     gui->unlock_window();
  554.     return 0;
  555. }
  556.