LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   using xine inside of an SDL app? (https://www.linuxquestions.org/questions/programming-9/using-xine-inside-of-an-sdl-app-238893/)

mmarshall 10-04-2004 11:47 PM

using xine inside of an SDL app?
 
Hello,

I am wanting to create a SDL app that, among other things, plays movies using xine-lib.

I looked over the xine hacker's guide, and I think I understand most of the stuff in the 'frontend' example. (I haven't ever seen any of those X11 functions before, but I think I get the idea as to what they do.) However, I have not the slightest clue as to how to get the 'Display *display;' thingy onto an SDL surface.

Can anyone give me a pointer on this? I have a feeling that this is one of those 'easy when you know it' deals.

Thanks!!

MWM

Marius2 10-05-2004 09:32 AM

I've been playing around with this too, in a cursory way (so I may be wrong with
my guesses). But I think you can not do this with the API SDL provides. If you really
want to stick to SDL, you probably will have to modify its source code, and you will
probably end up with code inside SDL which looks like the one in your frontend
(because it's put on top of Xlib), or sxfe sample from the xine site.
I eventually threw SDL overboard in my graphics abstraction layer (working under
both windows and linux) and am now using Xlib instead.

BTW may I ask what your purpose is in playing around with Linux graphics and
video?

mmarshall 10-05-2004 07:27 PM

Hi Marius2!

One of the things I am working on, (well, toying with...) is some sort of home control/automation/survalance/what-ever-else-i-want system, specifically designed for my family. I want most of the control to be done through a simple program, simple enough that a child (there are more than a few around here...) could control.

Some of the features I would like to implement involve playing videos... and I would like to use SDL for the gui...

I have been planning on having this app run in it's own X server, so perhaps it would work to simply have the video play in it's own window on top of the SDL app? Without any window decorations, I think it would look like it was part of the same window as the parent.

Something else I was just thinking of... One of the video drives that Xine can use uses SDL. I wonder if I could hack the Xine API a little... I will have to look over the code.

BTW, one of the main reasons that I want to use Xine instead of smpeg, is I would like to make use of the hardware MPEG2 decoding found in some of VIA's motherboards. (I don't actually have one of those boards, but I really want to get one :)

MWM

NDR008 08-14-2008 10:32 PM

Have you guy gotten anywhere?
I am making a C++ application with SDL for an digital/analogue/PWM input/output USB board to be used on a car mounted computer. It will interface with the ECU and monitor a few more things. I was originally writing the front end, but found myself using several libraries for just a few features and losing cross platform aspect.

So I went with SDL with the plan to use SDL_mixer for mp3 playback.

However I realised if I could some how use xine-lib I would then not need to worry with mpeg-4 based movies and wma, because as long as the xine engines it should be fine. From what I gather, somehow it is very possible to make xine output to an SDL overlay surface. However as sure I sound - I am by no means an expert and would appreciate ANY help...

mmarshall 08-15-2008 09:49 AM

No, I don't think that I ever got anywhere, but that was 4 years ago :D

I think you would be best off using Qt4 or Gtk+Cairo instead SDL. It's much easier to get much better results with a vector graphics engine. And you might want to use GStreamer instead of xinelib. I have found it to be easier to embed.

If you really want to use SDL, I would still go with GStreamer. I imagine that its modular architecture would make writing a custom image-sink easier.

BTW, a quick google search brought this up:
http://blog.gustavobarbieri.com.br/2...-applications/

Hope that helps :)

MWM

NDR008 08-15-2008 11:48 AM

I came across that but was going to try delay using it for as long possible because I cannot get my gstream to play wma and mpeg4 based movies yet, while my xine based players can currently play absolutely anything. But thanks.

dmail 08-15-2008 12:18 PM

There is a method of getting the Display and window in use from sdl SDL_SysWMInfo which you get from SDL_GetWMInfo. There is also a method, although it is documented with a warning "Using these variables isn't recommened and the names and presence of these variables aren't guaranteed from one release to the next.", this is using SDL_envvars and SDL_WINDOWID.

Hope that is of some use.

NDR008 08-15-2008 01:14 PM

I am completely lost on what you said. I have gone through that tutorial to use mplayer with SDL. I got the source to compile, but examining the code, it is not really using SDL, because it is still outputting to an X window as opposed to an SDL Overlay surface.

Both Xine and Mplayer say:

"Supported Video Output Devices
general:

* x11: X11 with SHM extension
* xv: X11 using overlays with the Xvideo extension (hardware YUV & scaling)
* sdl: SDL >= v1.1.7 driver"

Am I mis-understanding that?

NDR008 08-15-2008 08:09 PM

Need some help with this, I know at the minute it looks very dirty, but I am just trying to learn how to use many things at once. Once I get a good handle on it I will clean it up or start fresh. However since I am using many tutorials at once, things are going a bit skew.

Code:

Window create_x11_subwindow (Display *dpy, Window parent, int x, int y, int width, int height){
  Window win;
  int black;

  if (!dpy)
    return 0;

  black = BlackPixel (dpy, DefaultScreen (dpy));
  win = XCreateSimpleWindow (dpy, parent, x, y, width, height,
                            0, black, black);

  if (!win)
    return 0;

  if (!XSelectInput (dpy, win, StructureNotifyMask))
    return 0;

  if (!XMapWindow (dpy, win))
    return 0;

  while (1) {
    XEvent e;
    XNextEvent (dpy, &e);
    if (e.type == MapNotify && e.xmap.window == win)
      break;
  }

  XSelectInput (dpy, win, NoEventMask);

  return win;
}

SDL_SysWMinfo get_sdl_wm_info (void)
{
  SDL_SysWMinfo sdl_info;

  memset (&sdl_info, 0, sizeof (sdl_info));

  SDL_VERSION (&sdl_info.version);
  if (SDL_GetWMInfo (&sdl_info) <= 0 ||
      sdl_info.subsystem != SDL_SYSWM_X11) {
    fprintf (stderr, "This is not X11\n");

    memset (&sdl_info, 0, sizeof (sdl_info));
    return sdl_info;
  }

  return sdl_info;
}

Window create_sdl_x11_subwindow (int x, int y, int width, int height)
{
  SDL_SysWMinfo sdl_info;
  Window play_win;

  sdl_info = get_sdl_wm_info ();
  if (!sdl_info.version.major)
    return 0;

  sdl_info.info.x11.lock_func ();

  play_win = create_x11_subwindow (sdl_info.info.x11.display,
                                  sdl_info.info.x11.window,
                                  x, y, width, height);

  sdl_info.info.x11.unlock_func ();

  return play_win;
}

void check_keys(void) {
Uint8*  g_pKeys = SDL_GetKeyState(NULL);
 
  if((g_pKeys[SDLK_s]==1) && rpm < 9500 ) {rpm+=31; if (rpm > 9500) { rpm = 9500;} }
  if((g_pKeys[SDLK_x]==1) && rpm > 0 ) {rpm-=31; if (rpm < 0) { rpm = 0;} }
  if((g_pKeys[SDLK_a]==1) && speed < 260 ) {speed+=1; if (speed > 260) { speed = 260;} }
  if((g_pKeys[SDLK_z]==1) && speed > 0 ) {speed-=1; if (speed < 0) { speed = 0;} }
  if((g_pKeys[SDLK_d]==1) && af < 7 ) {af+=0.02; if (af > 7) { af = 7;} }
  if((g_pKeys[SDLK_c]==1) && af > 0 ) {af-=0.02; if (af < 0) { af = 0;} }
  if(g_pKeys[SDLK_e]==1) { digital_out[0] = !digital_out[0]; }
  if(g_pKeys[SDLK_r]==1) { digital_out[1] = !digital_out[1]; }
  if(g_pKeys[SDLK_t]==1) { digital_out[2] = !digital_out[2]; }
  if(g_pKeys[SDLK_y]==1) { digital_out[3] = !digital_out[3]; }
  if(g_pKeys[SDLK_u]==1) { digital_out[4] = !digital_out[4]; }
  if(g_pKeys[SDLK_i]==1) { digital_out[5] = !digital_out[5]; }
  if(g_pKeys[SDLK_o]==1) { digital_out[6] = !digital_out[6]; }
  if(g_pKeys[SDLK_p]==1) { digital_out[7] = !digital_out[7]; }
  if(g_pKeys[SDLK_KP2]==1) { mode = 2; }
  if(g_pKeys[SDLK_KP1]==1) { mode = 1; }
  if(g_pKeys[SDLK_w]==1) { fullscreen = toggle_fullscreen(fullscreen); }
  if(g_pKeys[SDLK_p]==1) {clean_up();}
}

void clean_up(void) {
/*
//Free the surfaces
SDL_FreeSurface( g_pDisplaySurface );
SDL_FreeSurface( g_pText );
SDL_FreeSurface(LEDimage);
SDL_FreeSurface(temp);
//Close the font that was used
TTF_CloseFont( font_rpm );
TTF_CloseFont( font_speed );
//Quit SDL_ttf
TTF_Quit();
*/
//Quit SDL
k8061_CloseDevices();
SDL_Quit();
exit(0);
}

void create_mplayer (const char *filename, Window win, FILE **mplayer_fp)
{
  char cmdline[1024];

  snprintf (cmdline, 1024, "mplayer -ao sdl -slave -wid 0x%lx a.avi", win);

  *mplayer_fp = popen (cmdline, "w");
  run = 1;
}

void main_loop (FILE *mplayer_fp)
{
  SDL_Surface *screen;
  Uint32 color;
  unsigned c_shift, run;

  fprintf (stderr, "Type 'q' or Escape to exit\n");

  while (run) {
    SDL_Event event;

    while (SDL_PollEvent (&event)) {
      switch (event.type) {
      case SDL_QUIT:
        fprintf (mplayer_fp, "quit\n");
        run = 0;
        break;

      case SDL_KEYDOWN:
        switch (event.key.keysym.sym) {
        case SDLK_q:
        case SDLK_ESCAPE:
          fprintf (mplayer_fp, "quit\n");
          run = 0;
          break;
        default:
          break;
        }
        break;

      default:
        break;
      }
    }

    SDL_FillRect (g_pDisplaySurface, NULL, color);
    SDL_Flip (g_pDisplaySurface);
    color |= 0x1 << c_shift;
    c_shift ++;

    if (c_shift >= 32) {
      c_shift = 0;
      color = 0;
    }

    SDL_Delay (20);
  }
}

int main(int argc, char* argv[])
{
  int frame = 0;
  Timer fps;
  Timer update;
  Timer rpm_ticks;
  int fps_30;
  Window play_win;
 
  k8061_Init();
  cardaddress = k8061_OpenDevices();
  if (k8061_GetDeviceCount() != 0) { connected = true;}

  SDL_Init(SDL_INIT_VIDEO);
  if(TTF_Init()==0)
  {
    atexit(clean_up);
  }
 
  g_pDisplaySurface = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_ANYFORMAT);
  if(!g_pDisplaySurface) {cout << "Could not Set Video Mode" << endl; exit(1);}
  SDL_ShowCursor(false);

  g_Display.x = g_Display.x = 0;
  g_Display.w = SCREEN_WIDTH;
  g_Display.h = SCREEN_HEIGHT;
 
  font_rpm = TTF_OpenFont("LEDBDREV.TTF", 48);
  if (font_rpm == NULL) {cout << "Font not found1" << endl;}
 
  font_speed = TTF_OpenFont("LEDBDREV.TTF", 28);
  if (font_speed == NULL) {cout << "Font not found2" << endl;}
 
  font_af = TTF_OpenFont("LEDBDREV.TTF", 20);
  if (font_speed == NULL) {cout << "Font not found2" << endl;}
 
  temp = IMG_Load("LED.png");
  if(!temp) {cout << "File not found" << endl; exit(1);}
  LEDimage = SDL_DisplayFormat(temp);
  SDL_FreeSurface(temp);
 
  temp = IMG_Load("warnings_s.png");
  if(!temp) {cout << "File not found" << endl; exit(1);}
  warningsIMG = SDL_DisplayFormat(temp);
  SDL_FreeSurface(temp);
 
  temp = IMG_Load("background3.png");
  if(!temp) {cout << "File not found" << endl; exit(1);}
  background= SDL_DisplayFormat(temp);
  SDL_FreeSurface(temp);

  for (int i = 0; i < 3; i++){
  for (int j = 0; j < 2; j++){
  LED[i][j].x = j*24; LED[i][j].y = i*24; LED[i][j].w = LED[i][j].h=24;
  }
  }
 
  for (int i = 0; i < 5; i++){
  for (int j = 0; j < 2; j++){
  warnings[i][j].x = j*40; warnings[i][j].y = i*40; warnings[i][j].w = warnings[i][j].h = 40;
  }
  }
 
  SDL_SetColorKey(LEDimage,SDL_SRCCOLORKEY, SDL_MapRGB(g_pDisplaySurface->format, 0, 0, 0));
  SDL_SetColorKey(warningsIMG,SDL_SRCCOLORKEY, SDL_MapRGB(g_pDisplaySurface->format, 0, 0, 0));
   
  g_STxtRect.x = 0;
  g_STxtRect.y = 0;
  update.start();
  fps.start();
  rpm_ticks.start();
 
for(;;){
  for(;mode==1;)
  { 
   
    //SDL_FillRect( g_pDisplaySurface, &g_Display, SDL_MapRGB( g_pDisplaySurface->format, 0, 0, 0));
    check_keys();
   
   
    if(SDL_PollEvent(&g_Event)==0)
    {
      SDL_BlitSurface(background,NULL,g_pDisplaySurface,NULL);
      draw_rpm();
      draw_rpm_bar();
      draw_speed();
      draw_speed_bar();
      //draw_warnings();
      draw_af_bar();
      draw_af();
      ndrIODigital();
    }
    //SDL_UpdateRect(g_pDisplaySurface,0,0,0,0); //For Non Fullscreen
    SDL_Flip(g_pDisplaySurface);
    frame++;
   
    if( update.get_ticks() > 200 )
        {
            //The frame rate as a string
            std::stringstream caption;
           
            fps_30 = frame / ( fps.get_ticks() / 1000.f );
            //Calculate the frames per second and create the string
            caption << "Average Frames Per Second: " << fps_30;
            //cout << fps_30 << endl;
           
            //Reset the caption
            SDL_WM_SetCaption( caption.str().c_str(), NULL );
           
            //Restart the update timer
            update.start();
        }
    if (rpm > peak_rpm) { peak_rpm = rpm; rpm_ticks.start();}
    if( rpm_ticks.get_ticks() > 2000 ) {peak_rpm =0; }
  cout << "Console Loop" << endl;
  }
 
  for(;mode==2;){
      play_win = create_sdl_x11_subwindow (60, 60, SCREEN_WIDTH-120, SCREEN_HEIGHT-120);
      mplayer_fp = NULL;
      create_mplayer (argv[1], play_win, &mplayer_fp);
      main_loop (mplayer_fp);
      mode=1;
      pclose (mplayer_fp);
    }
  }
  return(0);
}

Issue 1:
when in mode==2;
The original parent window is no longer handling the key events. Which is fine, only that I have to click on the new Sub Window (that is playing the video). I intend to use this program in an environment where I won't have any keyboards or mice for such things. Anyway to make the new window active without clicking on it?
[workaround]
After switching from mplayer to xine (see Issue 3) this problem got cured when I set the main SDL window created at the start main to the full resolution of my desktop and with SDL_NOFRAME, and creating an X11 video of the same size and telling Xine to output to the same size too (as in issue 3).

Issue 2:
Once playing the video, I think mplayer is capturing the key events. (and not my application, I am guessing this because the arrow keys are working to go FF / RR through the video). I do not mind this, but when I press 'q', the video stops and starts again. When I press q again, the video stops (as it is meant to), and I go back to the loop of mode==1 (as desired).
Why do I have this issue of pressing 'q' twice?

Issue 3:
After exiting mode==2, I am left with the XSimpleWindow in the middle of my parent window. How can I get rid of this?
I tried XDestorySubwindows(dpy, play_win); but that just closes everything.
[Workaround] Using xine instead of mplayer by changing:
snprintf (cmdline, 1024, "mplayer -ao sdl -slave -wid 0x%lx a.avi", win);
to
snprintf (cmdline, 1024, "xine -I -G %ix%i --no-splash --wid 0x%lx a.avi",(SCREEN_WIDTH), (SCREEN_HEIGHT), win);
Xine closes the window behind it somehow.


If anyone wants the FULL source to try compile it I would be more than happy to send it, but I would have to do some editing because it is communicating to a USB interface board. I could also paste the full source if it helps. Thanks.



Only real annoying issue left is Issue 2 which is super annoying.


All times are GMT -5. The time now is 07:27 AM.