The MASM Forum

General => The Campus => Topic started by: Guenther78 on October 31, 2013, 06:16:17 AM

Title: Video as a screensaver
Post by: Guenther78 on October 31, 2013, 06:16:17 AM
Hello All,

I want to write a screensaver in assembly. A screensaver is like a normal program, the only difference is, that the ending is .scr instead of .exe.
I want to use mci, so that the program can be used by everyone with a windows operating system. The user need not to have directX.

I tried to start a procedure from the main program like in Iczelions Turorial part 14:
http://win32assembly.programminghorizon.com/tut14.html (http://win32assembly.programminghorizon.com/tut14.html)


The called procedure is a short program, that consists in starting the playing of the video.


include     \masm32\include\winmm.inc
includelib  \masm32\lib\Winmm.lib

.data
MsgOrder        db "play video.wmv fullscreen repeat"

.code
start:
      invoke mciSendString, addr MsgOrder,  NULL, 0, 0


But when the video ist playing, how can I stop it? The main program, that contains the message loop is not active.

How can I make it, that the main program can receive messages from windows?

Key is pressed or mouse is moved-> stop the process!

Regards, Guenther
Title: Re: Video as a screensaver
Post by: dedndave on October 31, 2013, 06:25:53 AM
not really a "normal" exe, per se
i think it's a special dialog class....

http://msdn.microsoft.com/en-us/library/cc144066%28v=vs.85%29.aspx#About_Screen_Savers (http://msdn.microsoft.com/en-us/library/cc144066%28v=vs.85%29.aspx#About_Screen_Savers)
Title: Re: Video as a screensaver
Post by: Gunther on October 31, 2013, 06:51:53 AM
Good link, Dave. Thank you.  :t

Gunther
Title: Re: Video as a screensaver
Post by: dedndave on October 31, 2013, 01:26:32 PM
i seem to recall some examples on the old forum
never wanted to write one, so i don't have one handy
Title: Re: Video as a screensaver
Post by: Tedd on November 01, 2013, 02:11:33 AM
There is a little bit more to screensavers than just renaming to .scr -- there are various things you need to respond to, particularly when there was user activity.
More info: http://www.wischik.com/scr/howtoscr.html (http://www.wischik.com/scr/howtoscr.html)

As for controlling your video playback, you'll have to create your own MCI window, so you have a handle to direct messages at - then you can tell it when to play and stop, but that's obviously a bit more involved than a one-liner. Start with MCIWndCreate.
Title: Re: Video as a screensaver
Post by: TWell on November 01, 2013, 02:26:02 AM
Thank's Tedd for that link. :t
BTW: create thread for video and stop it, if user move mouse or hit key.
Title: Re: Video as a screensaver
Post by: dedndave on November 01, 2013, 03:02:08 AM
i think you can use mciSendCommand to terminate any video or audio that's playing
Title: Re: Video as a screensaver
Post by: jj2007 on November 01, 2013, 11:50:07 AM
Quote from: TWell on November 01, 2013, 02:26:02 AM
BTW: create thread for video and stop it, if user move mouse or hit key.

How would you stop it? TerminateThread?
Title: Re: Video as a screensaver
Post by: Guenther78 on November 02, 2013, 03:17:52 AM
Thanks for the replies and the links!


@ dedndave: You are right, in the old forum are some information:

http://www.masmforum.com/board/index.php?PHPSESSID=143b067e31fa6d7971f9bd4a87780197&action=search2 (http://www.masmforum.com/board/index.php?PHPSESSID=143b067e31fa6d7971f9bd4a87780197&action=search2)

And I can stop the Video with the following Code:

mciSendString(TEXT("Close"),  NULL, 0, 0);


@ jj2007:

I think I have to terminate the Video. If start a thread, then I have to get the focus back from the called thread to the calling program. Here are some possibilities:

http://www.masmforum.com/board/index.php?topic=2415.0 (http://www.masmforum.com/board/index.php?topic=2415.0)


Now I will have a closer look to the two links. I will post the code when I am ready.

Regards, Guenther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 19, 2013, 11:07:56 PM
Hello,

I was not able to implement it like in the links from Dedndave and Tedd. The linker can not find "DefScreenSaverProc". I looked in the internet and found the following side:

http://www.asmcommunity.net/forums/topic/?id=21139 (http://www.asmcommunity.net/forums/topic/?id=21139)

Here they build a screensaver with Masm. The also use a definition file (like in the link from Dedndave), but I have no idea, how to work with it.

So, I wrote a screensaver two or three months ago in C#. I was able to play a video file with mci. I played it in a picture box, so that the main window has the input focus. It works sometimes. It had worked on my windows 7. Later I have installed the windows SDK. After that it doesn't work.
And on a windows 8 I got a shame error. Later I changed the framework and it runs after that.

But I want that the screensaver works on every windows and is independent which framework is used. This was the reason, to write it with using the win32 api.

So it must be possible to write it with the win32 api, too. The video is located in C:\Windows\Temp. I did the following steps:


Create a fullscreen window

To create a fullscreen window I need the size of the desktop. I get this with with the GetSystemmetrix funciton:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx)

The background color should be black.

      invoke CreateSolidBrush,0
mov   wc.hbrBackground,eax



Create a PictureBox in Win 32

In the following links this is done:

http://stackoverflow.com/questions/1754037/how-to-add-picture-box-in-win32-api-using-visual-c (http://stackoverflow.com/questions/1754037/how-to-add-picture-box-in-win32-api-using-visual-c)
http://social.msdn.microsoft.com/Forums/en-US/fe6963e8-db6e-4e5e-b145-9cef74d49b57/picturebox-in-win32c?forum=vssmartdevicesnative (http://social.msdn.microsoft.com/Forums/en-US/fe6963e8-db6e-4e5e-b145-9cef74d49b57/picturebox-in-win32c?forum=vssmartdevicesnative)

I used "static" as a class name and "SS_BITMAP" as one of the window styles. As size I used the size of the video. The value of the upper left corner of the picture box is calculated with the video size and the desktop size.


Play the video in the Picture Box

Here I found a way how to play a video in a picture box:

http://social.msdn.microsoft.com/Forums/vstudio/de-DE/8d9d3dec-368a-491b-b628-c314d2751f57/how-to-play-video-in-c2008?forum=csharpgeneral (http://social.msdn.microsoft.com/Forums/vstudio/de-DE/8d9d3dec-368a-491b-b628-c314d2751f57/how-to-play-video-in-c2008?forum=csharpgeneral)

In the .data section I declared some orders:

Order0                  db "open C:\\windows\\temp\\video.wmv Type mpegvideo alias MyVideo1",0
Order1                  db "window MyVideo1 handle ",0
Order2                  db "seek MyVideo1 to 0",0
Order3                  db "play MyVideo1 repeat",0


The handle of the picture box I got from the CreateWindowEx function in the step ago, I only have to convert this handle to a string and to cat this string to Order1.
  invoke ltoa,hwndPictureBox,ADDR buffer                             
            invoke szCatStr,ADDR Order1,ADDR buffer



Stop the program

The program should stop, when it receives messages like WM_KEYDOWN or WM_MOUSEMOVE. So the parent window should have the input focus.

invoke SetFocus, hWnd


The program should react on the Message WM_MOUSEMOVE, but it doesn't if the cursor is inside the picture box. So I set the cursor out of it.

invoke SetCursorPos, x_cursor, y_cursor


The problem is, that the program receives this message although the mouse is not moved. I had to get the cursor position and compare it to the coordinates i had set the cursor to.

            invoke GetCursorPos, ADDR pt
            mov eax,pt.x
            .IF eax!=x_cursor
               invoke PostQuitMessage,NULL
            .ENDIF
            mov eax,pt.y
            .IF eax!=y_cursor
                invoke PostQuitMessage,NULL
            .ENDIF


The function GetCursorPos gives the coordinates back in a Point Structure.

POINT STRUCT
x DWORD ?
y DWORD ?
POINT ENDS
pt POINT <>


My problem is, that there is still a thin grey border around it, I can still see the cursor and, the biggest problem, I still can see the task bar. In the old forum there is a solution, I will try it in the near future.

http://www.masmforum.com/board/index.php?PHPSESSID=d52d81140238854679a6a365274e53d4&topic=17221.msg144070#msg144070 (http://www.masmforum.com/board/index.php?PHPSESSID=d52d81140238854679a6a365274e53d4&topic=17221.msg144070#msg144070)

I attached the source code. If You try it, please add a file "video.wmv" in the temp dictionary.

This is my first big project in MASM32. If You have comments or ideas, what I could make better, please tell me.


Regards, Guenther
Title: Re: Video as a screensaver
Post by: dedndave on December 20, 2013, 03:46:45 AM
to activate a screensaver, the system sends WM_SYSCOMMAND (check the docs)

i see there is an issue with DefScreenSaverProc, however
in the masm32 version 10 package, there was a scrnsave.inc and scrnsave.lib that had DefScreenSaverProc
but, i see it's not present in the version 11 package scrnsave.inc/lib files   :redface:

you might be able to make one of these work:
1) use LoadLibrary and GetProcAddress, PROTO, TYPEDEF
2) use the old versions of scrnsave.inc/lib
3) create a new scrnsave.inc/lib by updating the ones in masm32 version 11
Title: Re: Video as a screensaver
Post by: anunitu on December 20, 2013, 04:19:18 AM
I remember from a while back a program that allowed a desktop wallpaper that was animated. I don't remember the name,but it might be dremples or something. I found it,I don't know if there is any source or an explanation of how it was done. It also mentions it can be a screen saver.

http://www.geisswerks.com/about_drempels.html

Just checked and there is source code you can DL,not sure what language it is in,but it might offer some insights.

http://www.geisswerks.com/drempels/index.html

Source is at the second link
Title: Re: Video as a screensaver
Post by: Guenther78 on December 21, 2013, 05:19:34 AM
Hello!

@Dedndave:
I took the example from http://www.asmcommunity.net/forums/topic/?id=21139 (http://www.asmcommunity.net/forums/topic/?id=21139) and added the new old scrnsave.lib. Now I have the unresolved external symbol __except_list. But I found _except_list in the library file (I opened it with the editor). But now the linker found the missed function DefScreenSaverProc.

@anunitu:
Thanks for the links, I will have a look at them later.

Regards, Guenther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 21, 2013, 06:28:05 AM
Hello,

I saw that there is one underline more in the error message (_except_list) than in the lib-file (_except_list). I added a "_" it in the .lib-file. Now comes the linker error LNK1102 (out of memory). "Not enough memory for tool to run" says msdn.

Regards, Günther
Title: Re: Video as a screensaver
Post by: vogelsang on December 21, 2013, 06:51:06 AM
Maybe this will be helpful:
http://forum.nasm.us/index.php?topic=1749.0 (http://forum.nasm.us/index.php?topic=1749.0)
Title: Re: Video as a screensaver
Post by: Guenther78 on December 22, 2013, 01:18:06 AM
Hello,

@vogelsang:
Thanks for this interesting link.

@dedndave:
I was not able to make the screensaver run with your solution.

The best way is to play the video in fullscreen. The video is big and there is now task bar. The only problem is, that it does not react on messages like WM_KEYDOWN and WM_MOUSEMOUVE.
I found another solution!!!!
I use the timer, on every WM_TIMER message the program gets the position of the cursor and compare it with its position it had during WM_CREATE!
The only problem is, that it does not stop at keyboard pressing or mouse clicks...
But it stops if the user moves the mouse!

Best Regards, Guenther
Title: Re: Video as a screensaver
Post by: jj2007 on December 22, 2013, 02:32:56 AM
Quote from: Guenther78 on December 22, 2013, 01:18:06 AM
I found another solution!!!!
I use the timer, on every WM_TIMER message the program gets the position of the cursor and compare it with its position it had during WM_CREATE!

Günther,

That will work in most cases but notebooks in particular may show slowly "creeping" mouse cursors. Perhaps you could compare the distance between two WM_TIMER messages, and ignore those with a one pixel value.

Cheers,
Jochen
Title: Re: Video as a screensaver
Post by: Farabi on December 22, 2013, 09:42:51 AM
Hi Guenter,
Im sorry I havent had any advice yet about playing a movie on windows, I only know how to use camera using capCreateWindows. Maybe capCreateWindows can open a movie file too but I havent tried it yet.
Title: Re: Video as a screensaver
Post by: Guenther78 on December 23, 2013, 09:33:56 PM
Hello!

@ jj2007
Good idea, I will implement it.

@ Farabi
playing a movie on windows works with mci, in my first example the program plays the movie in a picture box:

.data
Order0                  db "open C:\\windows\\temp\\video.wmv Type mpegvideo alias MyVideo1",0
Order1                  db "window MyVideo1 handle ",0
Order2                  db "seek MyVideo1 to 0",0
Order3                  db "play MyVideo1 repeat",0
...
.code
...
             invoke mciSendString,ADDR Order0,0,0,0
             invoke ltoa,hwndPictureBox,ADDR buffer                             
             invoke szCatStr,ADDR Order1,ADDR buffer
             invoke mciSendString,ADDR Order1,0,0,0
             invoke mciSendString,ADDR Order2,0,0,0
             invoke mciSendString,ADDR Order3,0,0,0
...


And in my second example the program plays the movie in fullscreen:

.data
Order4                  db "play C:\\windows\\temp\\video.wmv fullscreen repeat",0
...
.code
...
            invoke mciSendString, ADDR Order4,0,0,0
...


But the function capCreateCaptureWindow may help me in my next projects.

Best regards,

Günther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 24, 2013, 10:48:51 PM
Hello!

Now I am trying to ignore differences of cursor positions with one pixel difference. Here is the code:


            ; Get current position
           invoke GetCursorPos, ADDR pt

            ; Has the cursor moved more than one pixel?
            mov eax,pt.x
            sub eax,x_cursor
            .IF eax > 1
                .IF eax < -1
                    invoke PostQuitMessage,NULL
                .ENDIF
            .ENDIF
            mov eax,pt.y
            sub eax,y_cursor
            .IF eax > 1
                .IF eax < -1
                    invoke PostQuitMessage,NULL
                .ENDIF
            .ENDIF

            ; Save current cusor position
            mov eax,pt.x
            mov x_cursor,eax
            mov eax,pt.y
            mov y_cursor,eax


Is this all right? Do you have better ideas?

I chose 500ms for the timer. Is that to long?

Best regards,

Günther
Title: Re: Video as a screensaver
Post by: jj2007 on December 24, 2013, 11:24:57 PM
            .IF eax > 1
                .IF eax < -1


See Tips, Tricks and_Traps (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm), "The .if eax<0 trap"

Otherwise it looks convincing ;-)
Title: Re: Video as a screensaver
Post by: Guenther78 on December 25, 2013, 12:44:32 AM
Thanks, I will replace ".if eax<0" by ".if sdword ptr eax<0".

Günther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 28, 2013, 10:34:47 AM
Hello,

the screensaver works. But I want that it plays a special Video:

http://www.youtube.com/watch?v=e2nMHAI1dU4 (http://www.youtube.com/watch?v=e2nMHAI1dU4)


I have this video file with a better quality and a darker ambient.
So I tried to implement it as an embedded resource and created a file rsrc.rc:

#define ID_VIDEO 100
ID_VIDEO RCDATA "FetteKiste.wmv"



How to use embedded binary resources is explained here:

http://blog.kowalczyk.info/article/zy/Embedding-binary-resources-on-Windows.html (http://blog.kowalczyk.info/article/zy/Embedding-binary-resources-on-Windows.html)


If the video can not be played cause it does not exist, I create the file new:


            ; Play the video in fullscreen           
            invoke mciSendString, ADDR Order4,0,0,0

            .IF eax != NULL
                invoke  FindResource,NULL,ID_VIDEO,RT_RCDATA
                mov     hwndVideo,eax

                invoke  LoadResource,NULL,hwndVideo
                mov     hwndVideoData,eax
   
                invoke  LockResource,hwndVideoData
                mov     firstByteVideo,eax

                invoke  SizeofResource,NULL,hwndVideo
                mov     sizeOfVideo,eax

                invoke CreateFile,ADDR videoname,\
                    GENERIC_READ or GENERIC_WRITE ,\
                    FILE_SHARE_READ or FILE_SHARE_WRITE,\
                    NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,\
                    NULL
                mov hFile,eax

                invoke WriteFile,hFile,firstByteVideo,sizeOfVideo,ADDR SizeReadWrite,NULL
                invoke CloseHandle,hFile

                ; Try again to play the video
                invoke mciSendString, ADDR Order4,0,0,0
            .ENDIF


I have the problem that Avira Antivir thinks that my program have the "TR/ATRAPS.Gen" trojan. I think it has to do with the RCDATA value. If I use RT_RCDATA like in the .asm file, then the program runs and Avira is not constraining it.

But if I remove the .wmv file, the file is not created. So I have to use RCDATA in the .rc file.

I think it will be the best, if the screensaver and the video file are in the same dictionary. I mean that other people can download a zip file with the two files in it. The video is not embedded in the screensaver.

I wanted that the video file is an embedded resource that will be saved under Windows/Temp. In this folder I have writing permissions without running a program as admin. If the video file is in the same folder like the screensaver, than it can not be in the Windows/System32 (where the default screensavers are) folder, because videos can not be played from this folder (I use Windows 7).

So, I think the best way is to make a zip file with both files in it, a screensaver and a video that is played. Or do anyone of you have an idea how I can embedded and save a file without being constrained by antivirus programs? I have attached the .rc and the .asm files that works with the video file as an embedded resource.

Best Regards, Guenther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 30, 2013, 12:50:53 AM
Hello,

I tried to implement another Video:

http://www.youtube.com/watch?v=RQJRfJVHT-I

The solution with the video inside the folder with the screensaver does not run. The .exe and the .scr runs, but if I installed the saver, than a small black box in the upper left of the desktop appears, that means, that the saver does not find the video.

So I got back to implement the video in the program. The program writes it to Windows/Temp.
And that works. Also if Avira is activated (see my post before). Also the problem is not the code, it is the embedded resource!

I added another file in the previous screensaver as a resource. I thought, that Avira sees some bytes in the video, that are similar to this one in a trojan. And after adding another file in the .rc file, Avira makes no trouble.

I hope, that this project is done now. But if You have some ideas, please let me know.

Regards, Guenther
Title: Re: Video as a screensaver
Post by: dedndave on December 30, 2013, 06:38:36 AM
you might try this routine
use RT_RCDATA as the resource type (in both the RC file and the function call)

;###################################################################################################

LoadFromRsrc PROTO :HINSTANCE,:LPSTR,:UINT

;###################################################################################################

        .CODE

;***************************************************************************************************

LoadFromRsrc PROC USES EBX ESI EDI hinstLfr:HINSTANCE,lpszLfr:LPSTR,uTypeLfr:UINT

;Load From Resource - DednDave, 9-2012
;
;Call With: hinstLfr:HINSTANCE = handle of module containing the resource (NULL = current process)
;           lpszLfr:LPSTR      = pointer to resource name string or integer resource ordinal
;           uTypeLfr:UINT      = integer type of resource
;
;  Returns: EAX = hgLfrData:HGLOBAL, global allocation handle or 0 if error
;           ECX = uLenLfrData:UINT , size of resource data or 0 if error
;           EDX = lpLfrData:LPVOID , pointer to resource data or 0 if error
;
;     Note: When done using the resource data, use GlobalUnlock and GlobalFree as follows:
;
;           INVOKE  GlobalUnlock,hgLfrData
;           INVOKE  GlobalFree,hgLfrData

;--------------------------------------------

    LOCAL   hrsrcLfr        :HRSRC
    LOCAL   hgLfr           :HGLOBAL
    LOCAL   uLenLfrData     :UINT
    LOCAL   lpLfrData       :LPVOID

;--------------------------------------------

    xor     ebx,ebx
    mov     uLenLfrData,ebx
    mov     lpLfrData,ebx
    INVOKE  FindResource,hinstLfr,lpszLfr,uTypeLfr
    .if eax
        mov     hrsrcLfr,eax
        INVOKE  LoadResource,hinstLfr,eax
        .if eax
            mov     hgLfr,eax
            INVOKE  LockResource,eax
            .if eax
                xchg    eax,esi
                INVOKE  SizeofResource,hinstLfr,hrsrcLfr
                .if eax
                    mov     uLenLfrData,eax
                    add     eax,31
                    and     al,-32
                    INVOKE  GlobalAlloc,GMEM_MOVEABLE,eax
                    .if eax
                        xchg    eax,ebx
                        INVOKE  GlobalLock,ebx
                        .if eax
                            mov     ecx,uLenLfrData
                            xchg    eax,edi
                            mov     edx,ecx
                            mov     lpLfrData,edi
                            shr     ecx,2
                            rep     movsd
                            and     edx,3
                            .if !ZERO?
                                mov     ecx,edx
                                rep     movsb
                            .endif
                        .else
                            xchg    eax,ebx
                            INVOKE  GlobalFree,eax
                            mov     uLenLfrData,ebx
                        .endif
                    .else
                        mov     uLenLfrData,eax
                    .endif
                .endif
            .endif
            INVOKE  FreeResource,hgLfr
        .endif
    .endif
    mov     edx,lpLfrData
    xchg    eax,ebx
    mov     ecx,uLenLfrData
    ret

LoadFromRsrc ENDP

;***************************************************************************************************
Title: Re: Video as a screensaver
Post by: Guenther78 on December 31, 2013, 12:13:31 AM
Hello,

thank You for this program, dedndave. I tried to implement it. I call the function after receiving WM_CREATE:

invoke LoadFromRsrc, NULL, ID_VIDEO, RT_RCDATA

But the eax register after the call is 0, I think, that is because the allocation failed.
And if I use RCDATA instead of RT_RCDATA in the .rc file, it works. But Avira makes trouble.
I have no idea, the solution with adding a second file in the .rc works, but that is no real solution.

Regards, Guenther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 31, 2013, 01:24:48 AM
Hello,

I found the error in the rc file: the value of RT_RCDATA is unknown, because the rc compiler does not know it. I had a look to windows.inc and I see that the value is 10.


#define RT_RCDATA 10
#define ID_VIDEO 100
ID_VIDEO RT_RCDATA "FetteKiste.wmv"


But Avira still does not like it.

Rgards, Guenther
Title: Re: Video as a screensaver
Post by: Guenther78 on December 31, 2013, 03:27:49 AM
Hello,

the error must be in the video file. I converted it from wmv to mpg and it runs now. Avira makes no trouble!

I have attached both .rc and .asm file. Saving an embedded resource is done with the function from dedndave, in my old code I have done it without allocating memory.

Best Regards,

Guenther
Title: Re: Video as a screensaver
Post by: Guenther78 on January 15, 2014, 03:25:41 AM
Hello,

the screensavers are ready now:

http://klingdesign.de/html/bildsch_schoner.html

You can choose between two videos, please click on the preferred picture. After downloading the zip-folder, extract it, mark the .scr-file, press the right mouse button and choose "install". We have tested it on a Windows XP, a Windows 7 and a Windows 8 Computer. If there are any problems, please tell me.
Thanks for the help in writing this application!

Best Regards,

Guenther