No announcement yet.

Quaketastic Screens

  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Originally posted by MadGypsy View Post
    [*]GIF images will not animate. I used the stock flash loader which does not support gif animation.
    So we can't really view gifs, then...
    ♪ I'm skiiiiiiinnin' in the pain, just skiiiiiiinnin' in the pain ♪
    ♪ What a glorious feelin' I'm haaaaaaappy again ♪


    • #17
      More new features and polish.The original post has been updated with all information.

      new features:
      images have a smooth tween transition
      screen saver mode added - transition between library images at fullscreen (10s intervals)
      mouseout list auto hides list
      mouseover list auto shows list and fades image for list legibility
      saved images are uploaded to the library to optimize download requests
      if any images exist in the images directory a random one is displayed upon app execution
      (inherent) any png|jpg|jpeg|gif image can be placed in the images directory to be used with screen saver mode

      developer features
      all code has been completely reconsidered and a compact reusable system was created in place of the "at-least-it-works" spaghetti version that existed til this point.


      At this point I would say this app is basically a way for you to choose and save images from the quaketastic screen_shots/ directory in order to make a quick custom screen saver slideshow. Of course it also allows you to simply view/save images from that directory in a way that isn't cumbersome but, I would lean more towards the entire point being a screen saver. Once you have downloaded all the images you like, at any point you could simply start the app and press S to initiate your custom screen saver.

      this image was captured as one image is fading out and the next is fading in. The transitions are very smooth. They happen simultaneously with a strong easing.

      @So we can't really view gifs, then...

      I didn't write my gif parser in AS3 and I probably never will. The stock flash.display.Loader class does not support animation of gifs. If I find an already created animated gif parser for AS3 I'll check it out. If it doesn't suck and isn't cumbersome I'll wire it into my app.

      When this was a haxe project it didn't do animated gifs either but, that was because my content manager is way too powerful for an app like this so, instead of using it I just wrote a quickie image loader using openfl.display.Loader (which is the same damn thing as flash.display.Loader). I didn't feel like going through all the trouble it would have taken to strip my content manager down to just images and text.
      Last edited by MadGypsy; 06-20-2017, 01:39 PM.


      • #18
        @If it doesn't suck and isn't cumbersome I'll wire it into my app.

        It would be cool.

        @I didn't feel like going through all the trouble it would have taken to strip my content manager down to just images and text.

        Yeah, not worth it for only one site. If this app was intended to be universal there could be a point to that but not as it is.
        ♪ I'm skiiiiiiinnin' in the pain, just skiiiiiiinnin' in the pain ♪
        ♪ What a glorious feelin' I'm haaaaaaappy again ♪


        • #19
          I just had the most awesome idea to add to this. This is going to take me some time. Maybe I will finish today and maybe I won't cause, this is some seriously complicated shit but, when I am done it will be awesome. Seriously, this is what this needs to go from "eh's a thing" to "ooooh fancy".

          ::cracks knuckles...brews coffee::

          I literally need to start a new side project to work with this and bring it into QuaketasticScreens when it's complete. It would be too cumbersome/messy to do it any other way. Be back eventually...probably not today...but I will try.
          Last edited by MadGypsy; 06-20-2017, 11:48 AM.


          • #20
            Heh, got me teased. Wonder what your idea is...
            ♪ I'm skiiiiiiinnin' in the pain, just skiiiiiiinnin' in the pain ♪
            ♪ What a glorious feelin' I'm haaaaaaappy again ♪


            • #21
              You'll be wondering til it's done but, it WILL be done. I can reuse this idea. Yaaaay, a new API to toil over.

              :turns off internet:


              • #22
                Let me first say that what I am about to say has absolutely nothing to do with the idea that I left y'all hanging with.

                Recently somebody over at func posted some AVI's to the screen_shots directory at quaketastic. Flash does not play AVI's. There is no AVI player for flash that I could find. I have no desire to parse AVI's. All that being said, QuaketasticScreens can now play AVI's. Actually it can probably play any imaginable video format. The concept is simple and I already have it working like a charm.

                I instantiate a stock flash Video class (ie...a player). I open a stream and attach it to the video player. I call a static build of ffmpeg with these cmdline args ["-i", _path, "-b:v", "4800k", "-ar", "44100", "-ac", "2", "-f", "flv", "-"]. The last arg just means stream. I listen for progress events, read all the flv formatted bytes that are streaming from ffmpeg into a bytearray and then append those bytes to the stream. Voila'.

                or to write it in 3 lines of gisty meat and potatoes

                attach progress event to ffmpeg with proper cmdline args
                on every progress event - netStream.appendBytes(from ffmpeg stream))


                This gave me an idea though. I already have parsers for a whole lot of shit in the files/ directory of quaketastic. images/wads/bsps/zip/probably more. Why not just go the whole 9 yards and make QuaketasticScreens into QuaketasticFiles? I don't see where it would be all that complicated to create a (more or less) all-in-one viewer for the grand majority of stuff there. Since my script already ignores non-image types that means it could just as easily ORGANIZE the hot mess that is the files/ directory. I could flip through every file and directory within files/ and beyond and parse every last thing to an appropriate category.

                I'm in no rush. Over the next few weeks I will add another thing til I knock them all out. As far as BSP goes, obviously with no progs, paks or anything else generally provided it will just be a viewer. Also, I never made a progs parser in the first place so... This is a way to intimately view files. Possibly a way to quickly find files.

                Obviously, if I can get the nth frame of a video I can get every frame. If I can get every frame I can play the video... ie. this shit really works. Audio too.

                link to actual video if you haven't seen it yet. It's pretty cool. Someone over at func made a bunch of "off topic" maps and this one in particular is a western theme.

                Right now, I intend to go turn this video player into a more robust API. It is currently in a just-works-if-it-works-at-all state. There are a whole shit-load of events that I need to go listen for (like error ones) and currently the player has no controls. I'm pretty satisfied, though. It took me maybe 20 minutes to make this and I mostly just took a lot of educated guesses. I guess I'm pretty educated :p.

                It's ugly and nasty but here is the current script
                	import flash.filesystem.File;
                	import flash.utils.ByteArray;
                	import flash.desktop.NativeProcess;
                	import flash.desktop.NativeProcessStartupInfo;
                	 * ...
                	 * @author OneMadGypsy
                	public class PlayVideo 
                		private static var _ffmpeg:File;
                		private static var _video:Video;
                		private static var _path:String;
                		private static var _nConn:NetConnection;
                		private static var _nStream:NetStream;
                		private static var _nProcess:NativeProcess;
                		private static var _ready:Function;
                		public static function play(video:Video, path:String, cb:Function):void
                			_video = video; _path = path; _ready = cb;
                			_ffmpeg = File.applicationDirectory;
                			_ffmpeg.nativePath = dataDirectory() + "\\ffmpeg\\bin\\ffmpeg.exe";
                			if (NativeProcess.isSupported)
                				_nConn = new NetConnection();
                				_nConn.addEventListener(NetStatusEvent.NET_STATUS, statusHandler);
                			} else throw new Error ("NativeProcess is not supported");
                		private static function statusHandler(event:NetStatusEvent):void
                				case "NetConnection.Connect.Success": launch();
                		private static function launch():void
                			_nStream = new NetStream(_nConn);
                			_nStream.client = new CustomClient(_ready);
                			//_nStream.client = {};
                			var processes:Vector.<String> = new <String>["-i", _path, "-b:v", "4800k", "-ar", "44100", "-ac", "2", "-f", "flv", "-"];
                			var npInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
                			npInfo.executable = _ffmpeg;
                			npInfo.arguments = processes;
                			_nProcess = new NativeProcess();
                			_nProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutput);
                		private static function onOutput(event:ProgressEvent):void
                			var bytes:ByteArray = new ByteArray();
                			_nProcess.standardOutput.readBytes(bytes, 0, _nProcess.standardOutput.bytesAvailable);
                		private static function dataDirectory():String
                			var dir:String = File.applicationDirectory.resolvePath('QuakeTasticScreens.swf').nativePath;
                			dir = dir.substr(0, dir.lastIndexOf("\\"));	//chop
                			dir = dir.substr(0, dir.lastIndexOf("\\"));	//chop
                			return dir;
                class CustomClient 
                	private var _callback:Function;
                	public function CustomClient(cb:Function):void
                	{	_callback = cb;
                    public function onMetaData(info:Object):void 
                	{{}, info);
                Last edited by MadGypsy; 06-29-2017, 09:51 PM.


                • #23
                  I parsed spirits entire file directory and sub folders. My script recursively hit all these directories.

                  and captured all the stats with only one mistake

                  I fully understand that those zips contain things that would make the other numbers larger, like wads for instance. This is intended to be a count of immediate file types.
                  Last edited by MadGypsy; 06-30-2017, 01:46 AM.


                  • #24
                    I completed my FFMPEG API and now have it to where a video player can be instantiated to play basically any imaginable video file with nothing but 2 lines.

                    //args - (path [, async, save])
                    var video:VideoPlayer = new VideoPlayer("", true);

                    Now, I am going to go duplicate the same concept with 7za.exe


                    • #25
                      Well, concept duplicated (in a bare bones way) and that's great but, turning all that text into a Vector of directory listings is not going to be fun. 7za.exe is a commandline tool and therefore it really wants to spit a bunch of crap out in the cmd shell. I don't have a choice, I have to strip all that text down to file paths or there will be no way to work with the files.

                      Last edited by MadGypsy; 06-30-2017, 08:42 PM.


                      • #26

                        added a file count after "PARSED PATHS:" to quickly check my accuracy. The number is the .length property of my path Vector, and it's identical to what 7zip reports on the final line of it's output.

                        My method isn't that complicated. First I get past the first line with all the hyphens. Then I strip out everything from where the second line of hyphens begins. I then replace all "\n" with nothing and all consecutive spaces with one space.

                        once the string is formatted like that I can simply create an array with split("\r"), run a loop on that array and derive path with

                        tmp = myArray.split(" ");
                        path = tmp[tmp.length -1];
                        if(path.indexOf(".") > -1) files.push(path); //ie. skip any directory

                        in other words this was all pretty simple and works on everything I have tested it on so far (about 5 various archives of 2 types zip/7z)

                        Now with a proper list of file paths I can do all kinds of stuff. Obviously extracting the actual file is now possible but, I have other ideas that revolve more around returning more accurate search results. For instance if you searched with my current tool it will tell you there are 20 something wads. This is because most wads are buried in archives. I don't expect any of the archived wads to ever change so, now it's time to create a system that catalogues all these zips in a local database...actually I will probably catalogue the whole damn thing, archive or not. This way, my app can do fast searches based on lightweight locally stored data instead of running through archives and parsing their files every time a search is made. The system could easily parse dates straight from the server generated directory page and updating the database will be as simple as running the process that made the database in the first place BUT with a twist that it is very particular about only adding files that have a date greater than the last stored one.
                        Last edited by MadGypsy; 06-30-2017, 10:04 PM.


                        • #27

                          I'm practically a regex master at this point. I completely changed my method. No splitting, skipping, reformatting... I go straight to lines that begin with date and time and use groups to swallow each chunk of the line so the last group is the file (result[6]). I strip out \r\t\n for good measure and I could omit the \t. I just threw it in cause it is another whitespace character that doesn't belong in a filename. The only part that remains from the original is the indexOf(".") part cause it's a real simple way to say "if this doesn't have a ain't a file". I should probably be more specific and make that a regex with every single supported filetype ".(wad|bsp|png|..........)$"

                          That regex is a beast. Notice how the second file has no compressed size but my regex finds it anyway and even with the spot for compressed size being nothing but a continuation of spaces from disk size result[6] is still correct. It's because the way I wrote it result[4] swallows all of those spaces and result[5] ends up being nothing, allowing result[6] to still exist. Fun stuff. Essentially, I parse all file directories from the mess of text that 7za.exe spits out with one very smart line of code. The rest is just looping that line, doing a clean up and a double check.

                          lol (.){5} = "just get whatever for 5 spaces" ~ the ....A parts. It seems cheap but it's really smart. I never know what's going to be in those 5 spaces. I just know it's going to be 5 spaces and I don't need it.
                          Last edited by MadGypsy; 07-01-2017, 01:13 AM.


                          • #28
                            Fully polished version. I utilized the group capture of regex to grab all file data. Everything below "Directory List" is the trace of my capture.

                            My final script. Every piece of file data is captured and in the case of sizes the value is reformatted from string to int. My regex has a number of "safe-guards" that allow the original source output to flex a bit without breaking my parse. For instance if for whatever reasons spaces increased or decreased it wouldn't matter. Also, it will support dates from January 1st 01 until December 31st 999,999 .

                            Last edited by MadGypsy; 07-02-2017, 08:31 AM.


                            • #29
                              I had to get to work so, I cut my post short.

                              Doing it this way (last post) solves some problems in a much better way. For instance, I was just checking if a file had a dot and if it didn't it was a directory. That way was terrible. I knew it was terrible but it seemed sufficient. The problem is, directories can have dots in the name and there are archives on quaketastic that do. Obviously the solution was to capture the Attr section and use it as intended, so I did. Once I went as far as to capture Attr and Path it only made sense to simply get everything. My original RegEx was pretty close, I only needed to change a couple things to capture each section and while I was at it I made sure space captures were all dynamic. 7za.exe could stretch that info out as wide as it wants and my parser wouldn't care or break.

                              I love RegEx. I know some/many programmers avoid it like the plague. I understand their reasons but, those reasons don't apply to every RegEx situation. Obviously parsing an entire script via RegEx is probably a bad way to go. It can be done but, you better be really damn good at RegEx AND capable of considering every single solitary possibility regarding formatting. A case like my current one is perfect though. There is only one "type" and that is a line. The format of the line is the same every time with only 2 exceptions. A file might not have compression size and the final line that shows the folder/file count does not have a type. Simple, if no type ignore...and make the compression portion optional.

                              The alternative to RegEx here would be to go over the output one character/line at a time and write a shit load of conditions based on the results. How is that better than using a technology that does that for me and was designed for exactly this purpose?
                              Last edited by MadGypsy; 07-02-2017, 11:22 AM.