View Full Version : New Linux Media Center Application!!!
greeniguana00 07-22-07, 07:46 AM I learned OpenGL, and have begun to make my own Media Center application. So far I have the main menu done. Nothing else works yet, but it is still worth a try just to see the animations.
You can download the binary w/source here: http://la.gg/upl/MediaCenterAlpha.tar.bz2
The README tells you all about the things you can change, which is the most interesting part.
Screenshot:
http://la.gg/upl/mca.png
I just wanted to check that I am going in the right direction with this before I put any more work into it.
Now released under GPLv3.
Cool. I went into the root directory of that site and it gave me an epileptic seizure. Are you going to work in MythTV?
greeniguana00 07-22-07, 03:15 PM Cool. I went into the root directory of that site and it gave me an epileptic seizure. Are you going to work in MythTV?
la.gg is a free file hosting site that is becoming popular. You should go here: http://la.gg/ if you actually want to upload something.
This is going to be something separate from MythTV. The main goals are:
1. To be easy to install. This means it will run without any initial configuration at all, and with as few external dependencies as possible.
2. To be ultra-configurable. Every aspect of it will eventually be changeable.
3. To be developed using suggestions from AVS members.
Right now I am working on the picture viewing interface.
Currently the settings you can change are:
*Animation speed
*Button bitmaps
*Background
*Button opacity
Once I get the picture, movie, music, and settings interfaces working, I will add tons more settings to change.
waterhead 07-22-07, 06:16 PM When I run the binary all I get is a slowly spinning and growing white square on a black background. When it finally fills the screen, nothing else happens.
My system:
Dell Inspiron 1150 Laptop
2.8 Ghz P4 Mobile
512Mb ram
Intel i810 graphics (the problem?)
openSuse 10.2
2.6.18.8-0.3-default (kernel)
greeniguana00 07-22-07, 06:28 PM When I run the binary all I get is a slowly spinning and growing white square on a black background. When it finally fills the screen, nothing else happens.
My system:
Dell Inspiron 1150 Laptop
2.8 Ghz P4 Mobile
512Mb ram
Intel i810 graphics (the problem?)
openSuse 10.2
2.6.18.8-0.3-default (kernel)
Ah... I know (part of) the problem. I do not do the animation speed by the actual time. Basically, the changes in the scene from frame to frame are always the same, but the rate at which the frames are rendered in completely dependent on how powerful your hardware is. If you hold down the "a" key, the change from frame to frame will increase, and everything will go faster. I will change it so that the initial animation speed is based on actual time, and not number of frames rendered per second.
The white square means that either none of the textures have loaded, or they are not being mapped... which is bad. Make sure the binary is in the same directory as "background1.bmp" and the "buttons" folder so that it can find the bitmaps it uses. If it already is, then I am not sure why.
Try running it from the command line and see if you get any errors.
If you happen to have gcc or g++, type
gcc -o alpha alpha.cpp -lglut -lGL -lGLU -lm
or
g++ -o alpha alpha.cpp -lglut -lGL -lGLU -lm
waterhead 07-22-07, 07:54 PM I have everything in the folders as they were downloaded. I tried the gcc command, and here's the out put
paul@laptop:~/downloads/MediaCenterAlpha> gcc -o alpha alpha.cpp -lglut -lGL -lGLU -lm
alpha.cpp:18:21: error: GL/glut.h: No such file or directory
alpha.cpp: In function ‘void display()’:
alpha.cpp:412: error: ‘glutSwapBuffers’ was not declared in this scope
alpha.cpp: In function ‘void specialKeyboard(int, int, int)’:
alpha.cpp:533: error: ‘GLUT_KEY_UP’ was not declared in this scope
alpha.cpp:544: error: ‘GLUT_KEY_DOWN’ was not declared in this scope
alpha.cpp: In function ‘int main(int, char**)’:
alpha.cpp:609: error: ‘glutInit’ was not declared in this scope
alpha.cpp:611: error: ‘glutInitWindowPosition’ was not declared in this scope
alpha.cpp:612: error: ‘glutInitWindowSize’ was not declared in this scope
alpha.cpp:614: error: ‘GLUT_RGBA’ was not declared in this scope
alpha.cpp:614: error: ‘GLUT_DOUBLE’ was not declared in this scope
alpha.cpp:614: error: ‘glutInitDisplayMode’ was not declared in this scope
alpha.cpp:616: error: ‘glutCreateWindow’ was not declared in this scope
alpha.cpp:618: error: ‘glutDisplayFunc’ was not declared in this scope
alpha.cpp:619: error: ‘glutKeyboardFunc’ was not declared in this scope
alpha.cpp:620: error: ‘glutSpecialFunc’ was not declared in this scope
alpha.cpp:621: error: ‘glutPassiveMotionFunc’ was not declared in this scope
alpha.cpp:622: error: ‘glutIdleFunc’ was not declared in this scope
alpha.cpp:627: error: ‘glutMainLoop’ was not declared in this scope
I don't have g++ installed, and I don't see it as being available as a rpm.
greeniguana00 07-22-07, 10:08 PM Try installing freeglut and libglut (if they aren't already installed).
waterhead 07-22-07, 10:28 PM After the first time I saw the errors, I installed any package that had "glut" in it. Freeglut and freeglut-devel were the only two available from my package manager.
Do you know of a SuSE repository that I can get libglut from? Otherwise where can I get the sources from?
EDIT: I see that I got libglut.so from the freeglut install.
greeniguana00 07-23-07, 11:15 PM The picture interface is going to take a while to complete. The problems to solve include:
*how to dynamically load and unload images (so they don't all need to be loaded when the program starts)
*how to scale and map images of any aspect ratio
*how to scan a directory for all images in that directory
*how to support all types of image formats (bmp, jpg, gif, etc.)
You can see the picture menu in this version: http://la.gg/v/MediaCenterAlpha2.tar.bz2/
It is not a pretty sight.
nitrogen 07-25-07, 01:05 AM The picture interface is going to take a while to complete. The problems to solve include:
*how to dynamically load and unload images (so they don't all need to be loaded when the program starts)
*how to scale and map images of any aspect ratio
*how to scan a directory for all images in that directory
*how to support all types of image formats (bmp, jpg, gif, etc.)
You can see the picture menu in this version: http://la.gg/v/MediaCenterAlpha2.tar.bz2/
It is not a pretty sight.
I have a similar project written in plain C and OpenGL. I haven't done any special modules yet, but it has a plugin-capable design. Without having read your code, here's how I would suggest solving your problems (some of which had to be solved for the ancient libfbx project):
1. Dynamic images - write a class that represents an image. Create a new instance of the class when you need the image, delete it when the image isn't displayed. In your constructor you would load the image into RAM, map it into an OpenGL texture, then free your local copy of the surface. In the destructor you would simply unload the GL texture.
2. Scale and map images - you can either write a function that will copy image data onto a power-of-two texture size (inefficient), use the NPOT (non-power-of-two) textures GL extension (sometimes very slow), or chop the image into 256x256 blocks (or whatever size you choose) and use multiple polygons to display the image (can cause artifacts at the polygon borders). In your class that represents the running instance of the application, you would keep track of the screen resolution and pixel aspect ratio, and scale the polygon coordinates (thus scaling the image) as necessary.
3. There are POSIX functions for enumerating directories, which I used when I was making a playlist editor for my program, which I never finished.
4. There are image libraries that support multiple formats. I wrote my own .bmp loader (based on other .bmp code), and my own .png loader using libpng, and use the file extension to decide which one to use. You might be able to use ImageMagick's library, which supports many, many image formats.
Could you post a screen shot of your picture menu? I'll attach a shot of a slightly older version of my main menu in case it inspires you or something.
greeniguana00 07-26-07, 10:45 AM Here is what the picture interface looks like currently: http://la.gg/upl/Screenshot-1_2.jpg
Right now it can load 24-bit bitmaps of any size and aspect ratio, display them at the correct aspect ratio, rescale them so the whole image fits, and center them. Now I need to add masking to the images because they repeat.
I found dirent.h and an example of how to use it to list files in a directory. I then used it to fill an array of strings with all the names of the files in the directory.
string str2[100];
int scan_directory(char *directory)
{
DIR *thinga;
struct dirent *thingb;
int i = 0;
thinga = opendir(directory);
while ((thingb = readdir(thinga)) != NULL)
{
i++;
str2[i]=(thingb->d_name);
cout<<str2[i]<<endl;
}
closedir(thinga);
return 1;
}
nitrogen 07-27-07, 06:32 AM Right now it can load 24-bit bitmaps of any size and aspect ratio, display them at the correct aspect ratio, rescale them so the whole image fits, and center them. Now I need to add masking to the images because they repeat.
I believe there is an OpenGL texture setting to disable texture wrapping. I assume you're passing values <0 and >1 for texture coordinates, resulting in the repeating texture. Alternatively, you could size your quads to match the aspect ratio of the texture.
greeniguana00 07-27-07, 11:31 AM I believe there is an OpenGL texture setting to disable texture wrapping. I assume you're passing values <0 and >1 for texture coordinates, resulting in the repeating texture. Alternatively, you could size your quads to match the aspect ratio of the texture.
I finally found that setting!!!
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
I still need to find out how to unload textures to avoid quickly filling up all available memory with a large image collection. I found this online: To remove a texture from OpenGL's resident textures:
TextureObject passed as the texture_object argument and 2)
call the unload() method"""
but it is pretty vague.
Aha! Found it: void glDeleteTextures(GLsizei n, const GLuint *textureNames);
Deletes n texture objects, named by elements in the array textureNames. The freed texture names may now be reused (for example, by glGenTextures()).
If a texture that is currently bound is deleted, the binding reverts to the default texture, as if glBindTexture() were called with zero for the value of textureName. Attempts to delete nonexistent texture names or the texture name of zero are ignored without generating an error.
greeniguana00 07-28-07, 09:41 PM Here is the most recent version:
http://la.gg/upl/MediaCenterAlpha3.tar.bz2
The picture interface now has:
*automatic loading of all ".bmps" in the picture directory
*automatic unloading (to keep memory usage low)
*rescaling and masking images so they look nice
*the ability to display images fullscreen by pressing the "p" key
The big problem now is how to make image loading happen in the background. As you can see, it takes a couple of seconds to load the picture menu, and during that time it is completely unresponsive. Then with large image collections, each time you navigate up and down, pictures are loaded and unloaded to keep the number of pictures loaded (and memory consumption) low. Unfortunately, this means the picture interface just stops.
Click on the picture for a video of it in action:
http://la.gg/upl/Screenshot-1_4.png (http://la.gg/upl/mediacenteralpha.mp4)
nitrogen 07-29-07, 01:06 AM Here is the most recent version:
http://la.gg/upl/MediaCenterAlpha3.tar.bz2
The picture interface now has:
*automatic loading of all ".bmps" in the picture directory
*automatic unloading (to keep memory usage low)
*rescaling and masking images so they look nice
*the ability to display images fullscreen by pressing the "p" key
The big problem now is how to make image loading happen in the background. As you can see, it takes a couple of seconds to load the picture menu, and during that time it is completely unresponsive. Then with large image collections, each time you navigate up and down, pictures are loaded and unloaded to keep the number of pictures loaded (and memory consumption) low. Unfortunately, this means the picture interface just stops.
Click on the picture for a video of it in action:
Take a look at pthreads (POSIX threads). Have your images loaded in one thread while the main thread handles the display. An alternative would be adding a callback function to your bmp loader to update the display with current status. Personally I would combine the two approaches.
greeniguana00 07-29-07, 01:16 AM I tried calling the display function from the bitmap loading function every 500 bytes read, but for some reason it only ever loads one bitmap. Also the keyboard will not work using this. I guess I will need to use pthreads.
greeniguana00 07-30-07, 08:51 PM I have made a test program to try out multithreading. So far I have one thread outputting the numbers from 1 to 1,000,000, and another thread loading the bitmaps into memory. That part works fine, the only problem is that I can't do any opengl calls from in any functions when called by one of the spawned threads. Every OpenGL call causes a segmentation fault. The call that loads a texture from the temporary memory used to get the bitmap info in the right format to the video memory is what takes the most time, but I can't do it. :mad:
I found this useful bit of info: http://www.nvnews.net/vbulletin/showthread.php?t=83283 so hopefully I can get it working...
nitrogen 07-31-07, 02:52 AM I have made a test program to try out multithreading. So far I have one thread outputting the numbers from 1 to 1,000,000, and another thread loading the bitmaps into memory. That part works fine, the only problem is that I can't do any opengl calls from in any functions when called by one of the spawned threads. Every OpenGL call causes a segmentation fault. The call that loads a texture from the temporary memory used to get the bitmap info in the right format to the video memory is what takes the most time, but I can't do it. :mad:
I found this useful bit of info: http://www.nvnews.net/vbulletin/showthread.php?t=83283 so hopefully I can get it working...
You will probably need to do all of your OpenGL and X11 work in the main thread. I don't know what the current state of things is, but I recall hearing at some point that neither X11 nor many OpenGL implementations were reentrant (i.e. thread-safe). OpenGL uses a state machine, for example, that may not span threads properly.
However, if what that link says is true, then this has likely been fixed, and you just need to find out which parts of X11 and OpenGL are thread-specific. Just for simplicity, I would personally avoid multithreaded access to GL, using the extra threads just for disk I/O.
greeniguana00 07-31-07, 11:14 AM ...very strange...
For some reason the executable can't be launched via GUI when on the desktop, or none of the textures will load. It can only be launched on the desktop by command line. In any other directory, all the textures will load when it is launched by clicking on it.
greeniguana00 07-31-07, 09:11 PM I have made picture loading much faster by simply disabling the generation of mipmaps, and it will soon be even faster once I have the loading of textures from hard disk to ram as a separate thread (loading to graphics memory will still happen in the main thread).
The main thing I am working on now is getting rid of some annoying segmentation faults. They only seem to show up after the 800th bitmap has been loaded, and I don't know why.
This is the output of program running and being analyzed by Valgrind:
...
BITMAP #812: width=1024 height=768 NUM:812:Width/Height=1.33333812
unload810unload809unload808a
BITMAP #813: width=1024 height=768 NUM:813:Width/Height=1.33333813
BITMAP #814: width=1024 height=768 NUM:814:Width/Height=1.33333814
BITMAP #815: width=1132 height=1132 NUM:815:Width/Height=1815
unload30unload29unload28
BITMAP #816: width=1024 height=768 NUM:816:Width/Height=1.33333816
BITMAP #817: width=1024 height=768 NUM:817:Width/Height=1.33333817
BITMAP #818: width=1024 height=768 NUM:818:Width/Height=1.33333818
unload814unload815a
BITMAP #819: width=1024 height=768 NUM:819:Width/Height=1.33333819
BITMAP #820: width=1132 height=1132 NUM:820:Width/Height=1820
unload818unload817unload816
BITMAP #821: width=1024 height=768 NUM:821:Width/Height=1.33333821
BITMAP #822: width=1024 height=768 NUM:822:Width/Height=1.33333822
BITMAP #823: width=1024 height=768 NUM:823:Width/Height=1.33333823
unload819unload820a
BITMAP #824: width=1024 height=768 NUM:824:Width/Height=1.33333824
BITMAP #825: width=1132 height=1132 NUM:825:Width/Height=1825
unload823unload822unload821
BITMAP #826: width=1024 height=768 NUM:826:Width/Height=1.33333826
BITMAP #827: width=1024 height=768 NUM:827:Width/Height=1.33333827
BITMAP #828: width=1024 height=768 NUM:828:Width/Height=1.33333828
==14419==
==14419== Invalid read of size 4
==14419== at 0x49A22DD: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E210C is 4 bytes after a block of size 80 alloc'd
==14419== at 0x402095F: calloc (vg_replace_malloc.c:279)
==14419== by 0x409E90D: (within /usr/lib/libGL.so.1.0.9755)
==14419==
==14419== Invalid read of size 4
==14419== at 0x49A22F3: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E210C is 4 bytes after a block of size 80 alloc'd
==14419== at 0x402095F: calloc (vg_replace_malloc.c:279)
==14419== by 0x409E90D: (within /usr/lib/libGL.so.1.0.9755)
==14419==
==14419== Invalid read of size 4
==14419== at 0x49A2304: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E2118 is not stack'd, malloc'd or (recently) free'd
==14419==
==14419== Invalid read of size 4
==14419== at 0x49A231F: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E2120 is not stack'd, malloc'd or (recently) free'd
==14419==
==14419== Invalid read of size 4
==14419== at 0x49A232E: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E211C is not stack'd, malloc'd or (recently) free'd
==14419==
==14419== Invalid read of size 4
==14419== at 0x49A2335: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E2118 is not stack'd, malloc'd or (recently) free'd
==14419==
==14419== Invalid read of size 4
==14419== at 0x462DB84: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E2114 is 12 bytes after a block of size 80 alloc'd
==14419== at 0x402095F: calloc (vg_replace_malloc.c:279)
==14419== by 0x409E90D: (within /usr/lib/libGL.so.1.0.9755)
==14419==
==14419== Invalid write of size 4
==14419== at 0x49A2345: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x55E211C is not stack'd, malloc'd or (recently) free'd
unload824unload825
BITMAP #829: width=1024 height=1024 NUM:829:Width/Height=1829
BITMAP #830: width=1132 height=1132 NUM:830:Width/Height=1830
BITMAP #831: width=1024 height=768 NUM:831:Width/Height=1.33333831
unload811unload812unload813a
BITMAP #832: width=1024 height=768 NUM:832:Width/Height=1.33333832
BITMAP #833: width=1024 height=768 NUM:833:Width/Height=1.33333833
unload831unload830unload829
BITMAP #834: width=1024 height=1024 NUM:834:Width/Height=1834
BITMAP #835: width=1132 height=1132 NUM:835:Width/Height=1835
BITMAP #836: width=1024 height=768 NUM:836:Width/Height=1.33333836
unload832unload833a
BITMAP #837: width=1024 height=768 NUM:837:Width/Height=1.33333837
BITMAP #838: width=1024 height=768 NUM:838:Width/Height=1.33333838
==14419==
==14419== Invalid read of size 4
==14419== at 0x462DB04: (within /usr/lib/libGLcore.so.1.0.9755)
==14419== Address 0x4F21068 is 8 bytes inside a block of size 28 free'd
==14419== at 0x402123A: free (vg_replace_malloc.c:233)
==14419== by 0x409E949: (within /usr/lib/libGL.so.1.0.9755)
==14419==
==14419== Invalid free() / delete / delete[]
==14419== at 0x402123A: free (vg_replace_malloc.c:233)
==14419== by 0x409E949: (within /usr/lib/libGL.so.1.0.9755)
==14419== Address 0x4F21060 is 0 bytes inside a block of size 28 free'd
==14419== at 0x402123A: free (vg_replace_malloc.c:233)
==14419== by 0x409E949: (within /usr/lib/libGL.so.1.0.9755)
unload836unload835unload834
BITMAP #839: width=1024 height=1024 NUM:839:Width/Height=1839
BITMAP #840: width=1132 height=1132 NUM:840:Width/Height=1840
BITMAP #841: width=1024 height=768 NUM:841:Width/Height=1.33333841
==14419==
==14419== Invalid write of size 1
==14419== at 0x804D66F: LoadBitmap(char*) (alpha.cpp:148)
==14419== by 0x804F4B4: pictures::load(std::string) (alpha.cpp:263)
==14419== by 0x804DADB: specialKeyboard(int, int, int) (alpha.cpp:882)
==14419== by 0x404EBBD: glutMainLoopEvent (in /usr/lib/libglut.so.3.8.0)
==14419== by 0x404ED54: glutMainLoop (in /usr/lib/libglut.so.3.8.0)
==14419== by 0x804F0CF: main (alpha.cpp:1056)
==14419== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14419==
==14419== Process terminating with default action of signal 11 (SIGSEGV)
==14419== Access not within mapped region at address 0x0
==14419== at 0x804D66F: LoadBitmap(char*) (alpha.cpp:148)
==14419== by 0x804F4B4: pictures::load(std::string) (alpha.cpp:263)
==14419== by 0x804DADB: specialKeyboard(int, int, int) (alpha.cpp:882)
==14419== by 0x404EBBD: glutMainLoopEvent (in /usr/lib/libglut.so.3.8.0)
==14419== by 0x404ED54: glutMainLoop (in /usr/lib/libglut.so.3.8.0)
==14419== by 0x804F0CF: main (alpha.cpp:1056)
unload837unload838a==14419==
==14419== ERROR SUMMARY: 733 errors from 13 contexts (suppressed: 41 from 1)
==14419== malloc/free: in use at exit: 2,706,059,908 bytes in 2,689 blocks.
==14419== malloc/free: 17,376 allocs, 14,673 frees, 1,765,923,899 bytes allocated.
==14419== For counts of detected errors, rerun with: -v
==14419== searching for pointers to 2,689 not-freed blocks.
==14419== checked 2,472,530,564 bytes.
==14419==
==14419== LEAK SUMMARY:
==14419== definitely lost: 0 bytes in 0 blocks.
==14419== possibly lost: 2,339,824,328 bytes in 915 blocks.
==14419== still reachable: 366,235,580 bytes in 1,774 blocks.
==14419== suppressed: 0 bytes in 0 blocks.
==14419== Reachable blocks (those to which a pointer was found) are not shown.
==14419== To see them, rerun with: --show-reachable=yes
Segmentation fault (core dumped)
If anyone has any ideas, I'd love to hear them.
nitrogen 08-01-07, 05:27 AM I have made picture loading much faster by simply disabling the generation of mipmaps, and it will soon be even faster once I have the loading of textures from hard disk to ram as a separate thread (loading to graphics memory will still happen in the main thread).
The main thing I am working on now is getting rid of some annoying segmentation faults. They only seem to show up after the 800th bitmap has been loaded, and I don't know why.
This is the output of program running and being analyzed by Valgrind:
If anyone has any ideas, I'd love to hear them.
What is memory usage of the program and system looking like? Since the crash is in OpenGL, I wonder if you're not freeing a GL resource somewhere. I'd use gdb to trace the program after 800+ bitmaps, stepping through the code until you get the error, unless valgrind can generate stack traces for the allocations that overflowed (not just the point of SEGV, the original malloc or GL call).
greeniguana00 08-01-07, 01:23 PM The memory usage is looking like >2GB, which I didn't expect. Somehow, it keeps using more and more memory as the picture interface is navigated. Then when it tries to allocate more memory, it can't. It then tries to write to 0x0 and gives the segmentaiton fault. I could prevent this by checking that malloc is not returning a null pointer, but the main issue is the memory leak.
...just as I was typing this I found the memory leak. I added an additional (temporary) memory allocation to make it easier to turn the RGB values in the bitmaps to RGBA so that pure black would be transparent and so that I could easily add things like alpha maps for buttons in the future. Unfortunately, I forgot to free it.
greeniguana00 08-01-07, 01:29 PM It works fine now. The bitmaps load quickly and it uses about 150MB of memory. :D
I will post the next version once I make sure I haven't made other mistakes.
greeniguana00 08-01-07, 04:14 PM Here you go: http://la.gg/upl/MediaCenterAlpha4.tar.bz2
|
|