Ive been up for 10 hours trying to figure out this. Ive tried out a bunch of different libraries to try to get ogg or mp3 files to play with allegro 4. I downloaded DUMB library and copied the include and lib files to mingw respective places (i use codeblocks).
What is the correct way to install a library to my compiler?
here is my code so far..
#include <allegro.h>
#include <iostream>
#include <stdlib.h>
#include <aldumb.h>
#include "CUSTOM_FUNCTIONS_HEADER.h"
#include "status_screen_functions_header.h"
#define WHITE makecol(255,255,255)
//General Game Settings
int volume = 128;
int pan = 128;
int pitch = 1000;
#
int main(int argc, char *argv[]){
allegro_init();
atexit(&dumb_exit);//initialize dumb
dumb_register_stdfiles(); //tELL DUMB HOW TO OPEN FILES
install_keyboard();
if(install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0){
allegro_message("error initializing the sound system");
}
set_color_depth(16);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 1100, 550, 0, 0);
write_status_screen("Status$>_Allegro Engine Initialization Successfull");
//******************************************************************************//
//*****************************************************************************//
//Write code below this line since allegro has been initialized//
BITMAP *dragon;
BITMAP *main_title, *main_menu;
BITMAP *buffer;
/*Menu music*/
// load_sample("OG_MUSIC\\straight_outta_compton_menu.ogg");
//Setup Audiostream for Main Menu Music//
write_status_screen("Status$> Loading OG Music Stream: \"Straight Outta Compton.OGG\"");
DUH *myduh;
myduh = dumb_load_it_quick("OG_MUSIC\\straight_outta_compton_menu.ogg");
AL_DUH_PLAYER *dp = al_start_duh(myduh, 2, 0,
volume, 4096, 48000);;
//logg_get_stream("straight_outta_compton_menu.ogg", volume, pan, true);
SAMPLE *menu_guntrigger = load_sample("OG_MUSIC\\gun_menu_choose.wav");
/*Menu count*/
int menct = 0;
buffer = create_bitmap(1100, 480);
textprintf_ex(screen, font, 0, 0, WHITE, 0, "Resolution = %ix%i ", SCREEN_W, SCREEN_H);
dragon = load_bitmap("BITMAPS\\COMPTON_START_MENU_FADED_TWO.bmp", NULL);
main_title = load_bitmap("BITMAPS\\OGM_TITLE.bmp", NULL);
main_menu = load_bitmap("BITMAPS\\MAIN_MENU.bmp", NULL);
write_status_screen("Status$>_Bitmaps loaded into memory!");
write_status_screen("Status$> Loading OG Sound Effects......:");
rest(650);
rest(700);
int frames_drawn = 0;
while(!key[KEY_ESC]){
/*Handle Controls First modulus 2 to make selection easier, every second frame, keypress is captured. DO NOT DO THIS FOR ACTUAL GAMEPLAY*/
if(key[KEY_UP] && frames_drawn % 2 == 0){
play_sample(menu_guntrigger, volume, pan, pitch, FALSE);
menct--;
} else if (key[KEY_DOWN] && frames_drawn % 3 == 0){
play_sample(menu_guntrigger, volume, pan, pitch, FALSE);
menct++;
}
if (menct > 3){
play_sample(menu_guntrigger, volume, pan, pitch, FALSE);
menct = 0;
}else if (menct <0){
play_sample(menu_guntrigger, volume, pan, pitch, FALSE);
menct = 3;
}
rest(10);
//Erase everything
clear(buffer);
//status box
rectfill(screen, 0, 480, 1100, 483, WHITE);
/*Draw the frame based on user input*/
draw_sprite(buffer, dragon, 0, 0);
draw_sprite(buffer, main_title, 315, 10);
drawframe(buffer, main_menu, 485, 145, 332, 305, 0, 0, 4, menct);
//blit(main_title, screen, 0, 0, 50, 50, 540, 96);
//masked_blit(main_title, screen, 0, 0, 50, 50, 540, 96);
//masked_blit(source, dest, framex, framey, x, y, width, height);
textprintf_ex(buffer, font, 900, 470, WHITE, 0, "Written By: Kelvin Silva", bitmap_color_depth(screen));
textprintf_ex(buffer, font, 0, 470, WHITE, 0, "Frames Drawn: %i", frames_drawn);
blit(buffer, screen, 0, 0, 0, 0, 1100, 480);
/*pollduh*/
al_poll_duh(dp);
/*Wait for vsync, rest a little, update framecount and prompt for more input*/
vsync();
frames_drawn++;
rest(50);
}
write_status_screen("Status$>_Game Loop Ended...");
clear_status_screen();
//NOTE NEED TO SETUP MEMORY DESTRUCTION
destroy_bitmap(dragon);
destroy_bitmap(main_title);
destroy_bitmap(buffer);
allegro_exit();
return 0;
}
END_OF_MAIN()
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_start_duh':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|48|undefined reference to `al_assert'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|49|undefined reference to `al_assert'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|62|undefined reference to `play_audio_stream'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|69|undefined reference to `voice_set_priority'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|74|undefined reference to `stop_audio_stream'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_stop_duh':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|92|undefined reference to `stop_audio_stream'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_pause_duh':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|103|undefined reference to `voice_stop'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_resume_duh':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|113|undefined reference to `voice_start'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_duh_set_priority':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|123|undefined reference to `voice_set_priority'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_poll_duh':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|156|undefined reference to `get_audio_stream_buffer'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|166|undefined reference to `free_audio_stream_buffer'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|167|undefined reference to `stop_audio_stream'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|179|undefined reference to `free_audio_stream_buffer'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_duh_encapsulate_sigrenderer':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|208|undefined reference to `al_assert'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|209|undefined reference to `al_assert'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|215|undefined reference to `play_audio_stream'|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|222|undefined reference to `voice_set_priority'|
d:\programs\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\..\..\..\libaldmd.a(alplay.o)||In function `al_duh_decompose_to_sigrenderer':|
D:\Users\Kelvin_Silva\Downloads\dumb-0.9.3\dumb-0.9.3\src\allegro\alplay.c|248|undefined reference to `stop_audio_stream'|
||=== Build finished: 18 errors, 0 warnings (0 minutes, 0 seconds) ===|
DUMB requires you to link with two libraries, the core libdumb and then the aldumb "glue". Looks like you are only linking with the latter. Order matters too.
Note that DUMB is used to play MOD files (and various variants). If you want ogg support, it comes built in Allegro 4.4 if you have the official ogg libraries installed.
Also, if you are just getting started, then you should really use Allegro 5. Version 4 isn't really supported any longer and doesn't work as well on modern operating systems.
Related
I wrote a font parser and renderer based on some functionality in the freetype library, but it currently only works for font files that I specify. I'd like to be able to retrieve fonts from the Windows Font Mapper and then parse and render them, but I can't figure out how to get the actual font data from a logical font.
I thought that the easy way to accomplish this would be to get the font file name from the logical font, but based on other stack overflow posts, there isn't any good solution to this because there isn't a 1 to 1 mapping of physical fonts to the logical font you specify.
This code shows how I'm currently retrieving a handle to a logical font:
HFONT windowsFont = CreateFontA(72, 0, 0, 0, 0,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "Arial");
HDC deviceContext = GetDC(windowHandle);
SelectObject(deviceContext, windowsFont);
DWORD fontSize = GetFontData(deviceContext, 0, 0, NULL, 0);
void *fontData = malloc(fontSize);
fontSize = GetFontData(deviceContext, 0, 0, fontData, 0);
char *fontFileData;
size_t fontFileSize;
// This is a function that I wrote that does what you'd expect. It opens
// a file, reads all the bytes to a buffer and closes the file
readFileToBuff(&fontFileData, &fontFileSize, "c:/windows/fonts/arial.ttf");
assert(fontFileSize == fontSize); // This passes
assert(((char)fontFileData) == ((char)fontData)); // This fails
Based on this stack overflow post which is for Java, I'm thinking that what I want to do may not be possible. It seems that the only solution may be to look at all the system font files and try to figure out what they are.
How to get ttf font data from system fonts in java
This surprises me though, because it seems that it would be relatively common for a program to want to render fonts themselves, without relying on the Windows renderer. Does anyone know of a way to get the font data, or how other people have solved this problem?
I don't understand why it's getting the exact same amount of bytes as
the file, but the data isn't the same.
From the official sample, I found the correct way to use GetFontData.
This is the modified code, and the returned data is the same as fontFileData.
HRESULT hr = S_OK;
LPVOID ptr = NULL;
HGLOBAL hGlobal = NULL;
...
HFONT windowsFont = CreateFontA(72, 0, 0, 0, 0,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "Arial");
HDC deviceContext = GetDC(hWnd);
SelectObject(deviceContext, windowsFont);
DWORD fontSize = GetFontData(deviceContext, 0, 0, NULL, 0);
hGlobal = GlobalAlloc(GMEM_MOVEABLE, fontSize);
ptr = GlobalLock(hGlobal);
if (!ptr)
{
hr = HRESULT_FROM_WIN32(GetLastError());
fwprintf(stderr, L"ERROR: Could not lock global memory object: %08X\n", hr);
}
else
{
if (GetFontData(deviceContext, 0, 0, ptr, fontSize) == GDI_ERROR)
{
fwprintf(stderr, L"ERROR: Could not get font data\n");
hr = E_UNEXPECTED;
}
GlobalUnlock(hGlobal);
}
char *fontFileData;
size_t fontFileSize;
// This is a function that I wrote that does what you'd expect. It opens
// a file, reads all the bytes to a buffer and closes the file
readFileToBuff(&fontFileData, &fontFileSize, "c:/windows/fonts/arial.ttf");
assert(fontFileSize == fontSize); // This passes
assert(((char)fontFileData) == ((char)fontData)); // This fails
Currently I have generated the PDF page as bitmap by using FPDF_RenderPageBitmap method.
is there any method for rendering the PDF page as EMF or as metafile in PDFium?
In the pdfium project there is a sample folder that has a pdfium_test.cc file that has examples of output in different formats. PNG, EMF, BMP, TXT, and PPM are all in the at the present time.
The current code to render an EMF
void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
int width = static_cast<int>(FPDF_GetPageWidth(page));
int height = static_cast<int>(FPDF_GetPageHeight(page));
char filename[256];
snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num);
HDC dc = CreateEnhMetaFileA(nullptr, filename, nullptr, nullptr);
HRGN rgn = CreateRectRgn(0, 0, width, height);
SelectClipRgn(dc, rgn);
DeleteObject(rgn);
SelectObject(dc, GetStockObject(NULL_PEN));
SelectObject(dc, GetStockObject(WHITE_BRUSH));
// If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
Rectangle(dc, 0, 0, width + 1, height + 1);
FPDF_RenderPage(dc, page, 0, 0, width, height, 0,
FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);
DeleteEnhMetaFile(CloseEnhMetaFile(dc));
}
On Windows, you want to call FPDF_RenderPage and pass in the HDC this should allow you to get the EMF data out. You can see the chromium printing code for example usage. There is also FPDF_SetPrintMode which lets you set different modes.
I'm trying to save some HBITMAPs into an array, and display them at a later time. Creating a HBITMAP from a DC works, but when I try to display a saved HBITMAP I seem to get the wrong one. This leads me to think that I haven't really understood how HTBIMAPs are stored in memory. I was assuming that the data type HBITMAP is essentially a pointer to the object in memory and that that's all I need, but maybe there is more to it?
Here's a sample code:
HBITMAP aBitMaps[NUM_BITMAPS];
int iNumBitMaps;
void SaveScreen(CDC *dc)
{
if (iNumBitMaps>0)
{
if (iNumBitMaps>=NUM_BITMAPS)
{
iNumBitMaps=NUM_BITMAPS-1;
DeleteObject(aBitMaps[iNumBitMaps]);
}
for (int i=iNumBitMaps;i>0;i--)
{
aBitMaps[i] = aBitMaps[i-1];
}
}
iNumBitMaps++;
aBitMaps[0] = CreateCompatibleBitmap(dc->m_hDC, 800, 800);
HDC hdcMem = CreateCompatibleDC(dc->m_hDC);
SelectObject(hdcMem, aBitMaps[0]);
BitBlt(hdcMem, 0, 0, 800, 800, dc->m_hDC, 0, 0, SRCCOPY);
ReleaseDC(hdcMem);
}
void RestoreScreen(CDC *dc, int i)
{
if (i>=NUM_BITMAPS) i = NUM_BITMAPS-1;
if (i<0) i = 0;
HDC hdcMem = CreateCompatibleDC(dc->m_hDC);
SelectObject(hdcMem, aBitMaps[i]);
BitBlt(dc->m_hDC, 0, 0, 800, 800, hdcMem, 0, 0, SRCCOPY);
ReleaseDC(hdcMem);
}
So, the idea is essentially to push the HBITMAP pointers to an array, and at a later time display any of the stored images by selecting it into a memory DC and then copying it to the actual DC. What's wrong with this?
I'm using VC++, Visual Studio 2010, no MFC.
EDIT:
I did some more tests. For debugging, I tried to display all stored bitmaps (shifted in position) by adding the following for loop to SaveScreen
...
BitBlt(hdcMem, 0, 0, 800, 800, dc->m_hDC, 0, 0, SRCCOPY);
for (int j=0; j<iNumBitMaps;j++)
{
SelectObject(hdcMem, aBitMaps[j]);
BitBlt(dc->m_hDC, 20*(j+1), 100*(j+1), 800+20*(j+1), 800+100*(j+1), hdcMem, 0, 0, SRCCOPY);
}
ReleaseDC(hdcMem);
This then does display iNumBitMaps times the image, but it's always the same image (namely the one I stored in aBitMaps[0]). I did verify in the debugger, that aBitMaps contains all different pointers. So, somehow I think I don't correctly load the bitmaps into the memory DC.
I figured it out. In my code above there were two mistakes (of which I'm aware of). First, the memory DC must be deleted after use, so ReleaseDC must be replaced by DeleteDC.
Second, one must know that an object that is selected into a DC cannot be selected into another DC. Hence it is important that after operating on an object in the memory DC, the object must be unloaded by selecting the DC's previous object. The correct contruction is thus essentially
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, aBitMaps[0]);
BitBlt(...);
HBITMAP hbmNew = (HBITMAP)SelectObject(hdcMem, hbmOld);
where now hbmNew points to the same object as aBitMaps[0].
Background
I am working on a rendering client that draws graphical information it receives from a server. The server sends packets containing non-overlapping rectangles with different solid colors at a frame rate variably defined on the server. I currently have it configured so that the size of the screen being transmitted by the server is different than the size of the window onto which the client is drawing, so scaling is done. I need the client to draw these rectangles as quickly as possible to not fall behind the server's stream.
Currently, I am using SDL 2.0. I am using the streaming texture technique described in the SDL 2 Migration Guide to draw the rectangles onto an SDL_Surface. When the time to display a frame arrives, I calll SDL_UpdateTexture() to overwrite the pixel data for an SDL_Texture, and then I use SDL_RenderCopyEx() to copy the texture to the renderer. I need this function instead of SDL_RenderCopy() so I can specify SDL_FLIP_VERTICAL to account for the fact that the coordinates passed are bitmap-style.
Question
My current approach does not render the rectangles quickly enough. To get the client to be able to keep up with the server, I currently have to reduce the server's upload rate from 30+ FPS to 15- FPS. Even then, I have to make the socket's buffer dangerously large, and I end up getting to watch the client's rendering slowly fall behind and eventually result in packet loss.
What is the fastest way to get SDL to render these rectangles? If I am currently using the fastest method, what other APIs would others recommend to make a client that can keep up?
I have included a stripped-down version of my source code so others can look for improvements/mistakes.
Technical Details
I am using C++11, MinGW32, and SDL2 with Eclipse Kepler CDT and GCC 4.8.2 on Window 7 64-bit.
Stripped Code
int main(int argc, char** args) {
// omitted initialization code
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow(
"RTSC",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
windowWidth,
windowHeight,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface* surface = SDL_CreateRGBSurface(
0,
sourceWidth,
sourceHeight,
24,
0xFF << 16,
0xFF << 8,
0xFF,
0
);
SDL_FillRect(surface, nullptr, 0);
SDL_Texture* texture = SDL_CreateTexture(
renderer,
surface->format->format,
SDL_TEXTUREACCESS_STREAMING,
sourceWidth,
sourceHeight
);
bool running {true};
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
switch (event.windowevent.event) {
case SDL_WINDOWEVENT_CLOSE:
running = false;
break;
default:
break;
}
break;
default:
break;
}
}
// omitted packet reception and interpretation code
for (uint32_t i {0}; i < receivedRegions; ++i) {
Region& region = regions[i];
SDL_Rect rect {
(int) region.x,
(int) region.y,
(int) region.width,
(int) region.height
};
uint32_t color =
(region.red << 16) +
(region.green << 8) +
region.blue;
SDL_FillRect(surface, &rect, color);
}
// omitted logic for determining whether to present the frame
SDL_RenderClear(renderer);
SDL_UpdateTexture(texture, nullptr, surface->pixels, surface->pitch);
SDL_RenderCopyEx(
renderer,
texture,
nullptr,
nullptr,
0,
nullptr,
SDL_FLIP_VERTICAL
);
SDL_RenderPresent(renderer);
SDL_FillRect(surface, nullptr, 0);
}
// omitted clean-up and return code
}
This is embarassing. Because of earlier instrumentation I had done on my server, I assumed all the problem was with the SDL rendering client. However, it turns out the client slows only when the server does. It has nothing to do with SDL at all. Sorry.
In short, I want to write a Gnome-Shell-style window switcher. So I need to fetch snapshots of all the windows. My current program looks like this:
char filename[101];
sprintf(filename, "%d.png", (int)win_list[i]);
GdkWindow *win_gdk = gdk_x11_window_foreign_new_for_display
(gdk_display_get_default(), win_list[i]);
gint _w, _h;
gdk_drawable_get_size(GDK_DRAWABLE(win_gdk), &_w, &_h);
XEvent _xevent;
_xevent.xexpose =
(XExposeEvent)
{
.type = Expose,
.send_event = True,
.display = xsu_vars.dpy,
.window = win_list[i],
.x = 0, .y = 0, .width = _w, .height = _h,
.count = 0
};
XSendEvent(xsu_vars.dpy, win_list[i], False, 0, &_xevent);
GdkPixbuf *_pb = gdk_pixbuf_get_from_drawable(
NULL, GDK_DRAWABLE(win_gdk), NULL, 0, 0, 0, 0, _w, _h);
if(_pb != NULL) {
cairo_surface_t *_surf_cairo = cairo_image_surface_create(
CAIRO_FORMAT_RGB24, _w, _h);
cairo_t *_cr = cairo_create(_surf_cairo);
gdk_cairo_set_source_pixbuf(_cr, _pb, 0, 0);
cairo_paint(_cr);
cairo_surface_write_to_png(_surf_cairo, filename);
printf("%s saved successfully!\n", filename);
} else {
printf("failed...\n");
}
The program works well well, but it will not generate correct images for those windows which are on a different desktop of minimized -- they would look like this:
Note that I send a expose event to all windows before generating pixbufs of them.
UPDATE:
It seems that xlib doesn't support that. So the only way may be creating cache manually.
This is possible with Composite extension - see "Preventing the backing pixmap from being freed when the window is hidden/destroyed" section in tutorial.
Yes, your update is correct. When a window is unmapped (or covered up), X just discards its contents; they don't exist anywhere in order to be snapshotted.
I believe libwnck contains code to do this and other parts of writing a switcher, btw. It's basically a library for writing things like window switchers.