QB64.org Forum

Active Forums => Programs => Topic started by: SMcNeill on July 28, 2019, 02:23:39 pm

Title: Spell It Aloud (Help Requested)
Post by: SMcNeill on July 28, 2019, 02:23:39 pm
Code: [Select]
SoundDir$ = ".\Alphabet Sounds\"

DIM AlphaSound(65 TO 90)
FOR i = 65 TO 90
    temp$ = SoundDir$ + CHR$(i) + ".ogg"
    AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
NEXT

DO
    INPUT "Input word to spell aloud: "; word$
    IF word$ = "" THEN SYSTEM
    word$ = UCASE$(word$)
    FOR i = 1 TO LEN(word$)
        _SNDPLAY AlphaSound(ASC(word$, i))
        _DELAY 1
    NEXT
LOOP

My niece recently just gave birth to a lovely little girl (8 lbs 3 ozs), and I was thinking of a simple little program to help them learn to read and write in a few years.  What I've came up with is a very nice little concept  (at least, I think it is):

Step 1: Let the user download some free images from the internet (such as a cat or dog, or such), and then save them with that filename.
Step 2: The program should look in the folder for those image files, and then pop the picture up on the screen, and then place them on the screen for us, along with their letters.  It should then read those letters back to us, to help a child familiarize themselves with the images of those letters on the screen, and how they correspond to each other.

What we have here is just a demo of taking a word and spelling it out aloud for the user, but I plan to expand upon it later so it'll do as described above.  My question to you guys is:

1) Is there someone who wants to record their voice saying various words and share them for this project?  I've got a speech impediment which sometimes slurs some of my spoken words (which is one reason, I suppose, why I turned to writing as a means to get my thoughts and ideas across to the world), so just some simple *.ogg recordings of "cat", "dog", "frog", and so on would be appreciated.

2) Anyone have a good source for low resolution images of simple words?  I don't need a million large images to package with this little program; small ones which represent the image will work nicely -- but they need to be copywrite free/open.

3) This should work quite easily for nouns and such, but does anyone have an idea how we'd represent an ACTION like this?  How do we convey the concept of "run", "bounce", "fall"?

All-in-all, it seems like a simple enough concept to pull off for a program; just a little time consuming to gather various images to showcase our words....

Anywho, I thought I'd share the concept and see if anyone would be interested in helping me to assemble a simple little program like this.  ;)
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 28, 2019, 04:15:19 pm
As you surely found out from my writing, so with my English (written) is it no glory. And if I still had to say it ... maybe as a parody it could be a success, but that's not what you need.
 However, this idea caught my attention. Pictures would probably be enough in 256 colors. The moving things, well, I would solve the file name such as sprite-run, sprite-fall ... but here we encounter a technical problem, because the ordinary user does not download, as a programmer, the correct format sprite image, for example, 5 frames and two rows. Thus, sprite would have to be present in the program beforehand.  I thought of an improvement. Suppose the file is named "good brown dog .gif". It might be possible for the program to spell and print only the name since the last space (dog), according to the space in the name and the set level (brown dog) or at top level the full title. That's just an idea. Definitely, on pinterest I downloaded pictures to the meditation program, there are many free, another option is to download SVG and save part of the screen to compatible format.

Next idea - is on screen cat image? Press to it and play "meow" :-D This can be done with internal DATA block and included audio files...
(DATA CAT, meow.ogg, DOG, bark.ogg  ....)
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 28, 2019, 04:24:02 pm
And of course, congratulations, Uncle!!
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on July 28, 2019, 07:39:07 pm
Below is the actual working prototype of how I'd envision this little project coming together and working.

Now all I need is:

Tons of simple photos like the whopping three I've assembled so far,
And someone with a clear, easy to understand voice to speak the actual words so I can put them into another \sounds\ directory and load them so I can have the program talk to us like:

"C"
"A"
"T"
...
"CAT"
...
"C"
"A"
"T"

Speak the letters, say the word, Speak the letters again...



Once I get a good assortment of words and images, I'll probably have the program set up so you can run learning exercises with it...

Let it go through a cycle of 10 words, 3 times each (30 total images would go across the screen), and then pop an image up on the screen and ask, "Can you spell (insert image word here)?"  Let the child give it a shot, see how they do, and then score them just like in school.

Problem words can be saved to a list for future study, and passed words will go into a different list for review much later (like mid terms or final exams in schools).

All in all, I think this has the potential to be a nice little teaching tool for young children (or as a starting point for anyone who might want to learn the English language, for that matter.)

Try it out and tell me what you think of it guys.  :D
Title: Re: Spell It Aloud (Help Requested)
Post by: Pete on July 29, 2019, 01:14:36 am
Have you tried places like vectorstock.com?

https://www.vectorstock.com/royalty-free-vector/surprised-emoji-with-a-mexican-hat-vector-20777258

https://www.vectorstock.com/royalty-free-vector/cartoon-man-with-two-rollers-paints-a-brick-wall-vector-24911576

I'm pretty sure that's a MAGA hat, in that one.

Oh, you wanted a cat... OK, got it... https://www.vectorstock.com/royalty-free-vector/halloween-black-cat-vector-1350256

Kidding aside, a lot less sites have free images these days and a lot of them are going to "For personal use only." I would consider what you want it for to be just that, but if you wanted to market it at some point, well, that's a horse of a different color. Anyway, 1,000? That will take you awhile.  I believe WGET has a newly added image search function, but I'm not sure if you could use it on sites like these. If it could point to only the free for personal use images, you could download all of them, and sort them out later. I made some kind of utility for this ages ago, just searching for the 3-letter extension of image files. Sure, you could get that off of Bing, Google, DuckDuckGo, etc., but again, you would be stumbling all over copyright issues, but if you could target only free images, you'd be golden.

Good luck, and congrats on the addition to the family.

Pete
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 29, 2019, 11:14:43 am
Steve, I used your last code as a base and I'm working on it. I downloaded some animals from Google, I deleted _DELAY 1 after _SNDPLAY and replaced it with DO WHILE _SNDPLAYING (array): LOOP..., add _CONTINUE if file name contains space and _DELAY .5 if is space to speech (guinea pig image) and working on it also now.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 29, 2019, 04:46:46 pm
So, here is small upgrade. DEFLNG in begin DELETED because this do problems with new SUB GETNewWH (Get New Width and Height). Images now are not deformed. Tomorrow I will work on further improvements. All suggestions are very welcome. Tomorrow I want to make animal sounds by clicking the animal + add more photos.
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on July 30, 2019, 11:59:34 am
Petr, here's my next little upgrade to this little project:  Adding tags to images for ease of searching/referencing later.

Code: [Select]
SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "Spell It Aloud"
DEFLNG A-Z
RANDOMIZE TIMER

CONST ImageDir$ = ".\Images\"
CONST SoundDir$ = ".\Alphabet Sounds\"



DIM AlphaSound(65 TO 90)
REDIM SHARED PhotoList(100000) AS STRING
REDIM SHARED PhotoTags(100000) AS STRING
DIM SHARED f AS LONG, f1 AS LONG

'load our fonts
f = _LOADFONT("courbd.ttf", 84, "MONOSPACE")
f1 = _LOADFONT("courbd.ttf", 20, "MONOSPACE")
_FONT f
fw = _FONTWIDTH: fh = _FONTHEIGHT


'Load the alphabet sound library
FOR i = 65 TO 90
    temp$ = SoundDir$ + CHR$(i) + ".ogg"
    AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
NEXT

_FONT f
'Get a listing of the files
PhotoList$ = ImageDir$ + "*.bmp " + ImageDir$ + "*.jpg " + ImageDir$ + "*.png " + ImageDir$ + "*.gif "
SHELL _HIDE "DIR " + PhotoList$ + "/b /s /a-d >PhotoList.txt"

'Load those names into a file.
OPEN "Photolist.txt" FOR BINARY AS #1
DO UNTIL EOF(1)
    PhotoCount = PhotoCount + 1
    LINE INPUT #1, PhotoList(PhotoCount)
LOOP
REDIM _PRESERVE PhotoList(PhotoCount)
CLOSE

_DELAY 1 'Give everything a moment to initialize and get started for us.


DO
    DO UNTIL photochosen <> oldpic
        photochosen = INT(RND * PhotoCount) + 1
    LOOP
    oldpic = photochosen
    word$ = UCASE$(PhotoList(photochosen))
    word$ = MID$(word$, _INSTRREV(word$, "\") + 1)
    word$ = LEFT$(word$, INSTR(word$, ".") - 1)

    IF tempimage <> 0 THEN _FREEIMAGE tempimage 'free the old image
    tempimage = _LOADIMAGE(PhotoList(photochosen), 32) 'get the new image

    GetTags word$

    CLS
    _PUTIMAGE (50, 50)-(750, 500), tempimage 'Put the image to the screen
    ShowTags 'Display the tags up top

    'Put the letters to the screen one by one
    pw = _PRINTWIDTH(word$): StartX = (_WIDTH - pw) \ 2 'center position

    FOR i = 1 TO LEN(word$)
        a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
        _PRINTSTRING (StartX + (i - 1) * fw, 510), MID$(word$, i, 1)
        IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
        _SNDPLAY AlphaSound(a)
        WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
            _LIMIT 10 'play nice with CPU during wait
        WEND
    NEXT
    DO
        k = _KEYHIT
        _KEYCLEAR
        _LIMIT 10
        SELECT CASE k
            CASE 65, 97 'a,A
                AddTags word$
            CASE 68, 100 'd,D
                DeleteTags word$
            CASE 32 'space
                _DELAY 1
                EXIT DO
            CASE 27 'escape
                SYSTEM 'quit
        END SELECT
    LOOP
LOOP


SUB BlankTop
    LINE (0, 0)-(799, 49), &HFF000000, BF 'blank out the top info
END SUB

SUB AddTags (tfile$)
    BlankTop
    _FONT f1
    LOCATE 1, 1: PRINT "Add Tag:";
    INPUT tag$
    IF tag$ <> "" THEN
        u = UBOUND(phototags)
        FOR i = 1 TO u
            IF _STRICMP(tag$, PhotoTags(i)) = 0 THEN TagExists = -1: EXIT FOR
        NEXT
        IF NOT TagExists THEN
            REDIM _PRESERVE PhotoTags(u + 1) AS STRING
            PhotoTags(u + 1) = tag$

            file$ = ".\Images\" + tfile$ + ".txt"
            OPEN file$ FOR OUTPUT AS #1
            FOR i = 1 TO u + 1
                PRINT #1, "#";
                PRINT #1, PhotoTags(i);
                PRINT #1, " ";
            NEXT
            CLOSE
        END IF
    END IF
    ShowTags
    _FONT f
END SUB

SUB DeleteTags (tfile$)
    BlankTop
    _FONT f1
    LOCATE 1, 1: PRINT "Delete Tag:";
    INPUT tag$
    IF tag$ <> "" THEN
        u = UBOUND(phototags)
        FOR i = 1 TO u
            IF _STRICMP(tag$, PhotoTags(i)) = 0 THEN TagExists = -1: EXIT FOR
        NEXT
        IF TagExists THEN
            FOR j = i TO u - 1
                PhotoTags(j) = PhotoTags(j + 1)
            NEXT
            REDIM _PRESERVE PhotoTags(u - 1) AS STRING
            file$ = ".\Images\" + tfile$ + ".txt"
            OPEN file$ FOR OUTPUT AS #1
            FOR i = 1 TO u - 1
                PRINT #1, "#";
                PRINT #1, PhotoTags(i);
                PRINT #1, " ";
            NEXT
            CLOSE
        END IF
    END IF
    ShowTags
    _FONT f
END SUB


SUB GetTags (tfile$)
    'Load the PhotoTags
    file$ = ".\Images\" + tfile$ + ".txt"
    OPEN file$ FOR BINARY AS #1
    IF LOF(1) = 0 THEN 'if there's no tags, we can't get them.
        CLOSE
        REDIM _PRESERVE PhotoTags(0) AS STRING
        EXIT SUB
    END IF
    DO UNTIL EOF(1)
        LINE INPUT #1, junk$
        l = 1
        DO UNTIL l = 0
            l = INSTR(junk$, "#")
            IF l THEN
                junk$ = MID$(junk$, l + 1)
                l1 = INSTR(junk$, "#")
                IF l1 = 0 THEN 'nothing more, we now have the tag
                    tag$ = junk$
                    l = 0
                ELSE
                    tag$ = LEFT$(junk$, l1 - 1)
                    junk$ = MID$(junk$, l1)
                END IF
            END IF
            tag$ = _TRIM$(tag$) 'no leading/tailing spaces for ease of matching
            TagFound = 0
            FOR i = 1 TO TagCount 'Check the existing tags to see if these exist
                IF PhotoTags(i) = tag$ THEN TagFound = -1: EXIT FOR
            NEXT
            IF NOT TagFound THEN 'If not, add the new tags to the list
                TagCount = TagCount + 1
                IF TagCount > UBOUND(PhotoTags) THEN REDIM _PRESERVE PhotoTags(TagCount + 1000) AS STRING
                PhotoTags(TagCount) = tag$
            END IF
        LOOP
    LOOP
    CLOSE
    REDIM _PRESERVE PhotoTags(TagCount) AS STRING
END SUB

SUB ShowTags
    BlankTop
    _FONT f1
    PRINT UBOUND(phototags); " TAGS: "
    FOR i = 1 TO UBOUND(Phototags)
        PRINT "#"; PhotoTags(i); " ";
    NEXT

    _FONT f
END SUB

When a picture is now loaded, the program should either read the tag file, or else create a blank one for it.  You can easily add tags by hitting the A key, and delete them with the D key, before moving on to the next image.

Later, I foresee adding in a routine to allow the user to limit results via tags, so they can create "custom-style lesson plans" for children.  I think here would be a good place to grab word lists to organize by year/week to create lesson plans for children:  https://www.k12reader.com/worksheet/first-grade-master-spelling-list/view/

For example:  Sight words and -at family words
1. the
2. of
3. and
4. that
5. cat
6. mat
7. sat
8. hat

Some of those would be hard to represent with pictures alone (the, of, and, that), but the cat, hat, mat easily and readily fits the format of this little program.

By adding tags such as #Year1 #AT_Word #Week1, we can fix it so that an user could search for those things and have only them pop up for a "study guide", to help a child learn those items.

"cat" might have the tags: #Year1 #AT_Word #Week1 #Animal #Pet #Cute #Fluffy (and whatever else we want to describe it with), so later the user can enter their search tags and easily create a custom-list of photos for their child to spell and look at.  :)



You're going the route of adding sounds to the program; I thought  I'd take the steps towards making us a searchable tag-system for ease of usability.  Between the both of us, we may end up with a really nice little teaching tool out of this project.  ;)
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 30, 2019, 12:13:56 pm
Hi Steve, I've been working on it too - my way. I'm posting what I just wrote in ZIP format, i  look at what you wrote and me give it together. At the end of the source code, when you look at the last line of commented lines, you will know what I was about to do. :)

Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 30, 2019, 12:23:13 pm
:)  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 30, 2019, 12:49:45 pm
Here is mix both sources with your + my functionality:

Code: [Select]

'Steve's idea: 10 different words, each of which is repeated three times and then one is picked and the child writes image name
'(text input, I suppose, because QB64 does not have microphone support)?




SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "Spell It Aloud"
RANDOMIZE TIMER

ImageDir$ = ".\Images\"
SoundDir$ = ".\Alphabet Sounds\"


DIM SHARED AlphaSound(65 TO 90), f AS LONG, f1 AS LONG
REDIM SHARED PhotoList(100000) AS STRING
REDIM SHARED PhotoTags(100000) AS STRING
REDIM SHARED IMG10(9) AS LONG 'array fo 10 different images. Contains diferent indexes numbers for PhotoList()


'load our fonts
f = _LOADFONT("courbd.ttf", 84, "MONOSPACE")
f1 = _LOADFONT("courbd.ttf", 20, "MONOSPACE")
_FONT f
fw = _FONTWIDTH: fh = _FONTHEIGHT


'Load the alphabet sound library
FOR i = 65 TO 90
    temp$ = SoundDir$ + CHR$(i) + ".ogg"
    AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
NEXT

'Get a listing of the files
PhotoList$ = ImageDir$ + "*.bmp " + ImageDir$ + "*.jpg " + ImageDir$ + "*.png " + ImageDir$ + "*.gif "
SHELL _HIDE "DIR " + PhotoList$ + "/b /s /a-d >PhotoList.txt"

'Load those names into a file.
OPEN "Photolist.txt" FOR BINARY AS #1
DO UNTIL EOF(1)
    PhotoCount = PhotoCount + 1
    LINE INPUT #1, PhotoList(PhotoCount)
LOOP
CLOSE #1
REDIM _PRESERVE PhotoList(PhotoCount)


_DELAY 1 'Give everything a moment to initialize and get started for us.



Insert_10_Different_Images 'insert 10 different indexes numbers from PhotoList, to array IMG10() [LONG] [0..9]

DO


    '    DO UNTIL photochosen <> oldpic
    '        RANDOMIZE TIMER
    '       photochosen = INT(RND * PhotoCount) + 1
    '  LOOP
    '  oldpic = photochosen

    photochosen = IMG10(index)
    index = index + 1
    IF index > 9 THEN index = INT(1 + RND * 8): Query = 1



    word$ = UCASE$(PhotoList(photochosen))
    word$ = MID$(word$, _INSTRREV(word$, "\") + 1)
    word$ = LEFT$(word$, INSTR(word$, ".") - 1)
    IF tempimage < -1 THEN _FREEIMAGE tempimage
    tempimage = _LOADIMAGE(PhotoList(photochosen), 32)

    GetTags word$
    'Put the image to the screen                                UPGRADE


    FOR Loop_it = 1 TO 3 'as you say. 3x one word + image, this 10x with different images an then query.

        CLS
        'program photo area is 700 x 450 pixels. So:
        GetNewWH 700, 450, tempimage, nW, nH


        Ws = 400 - (nW / 2)
        We = 400 + (nW / 2)
        Hs = 300 - (nH / 2) - 25
        He = 300 + (nH / 2) - 25

        _PUTIMAGE (Ws, Hs)-(We, He), tempimage
        ShowTags 'Display the tags up top


        'Put the letters to the screen one by one
        pw = _PRINTWIDTH(word$)
        StartX = (_WIDTH - pw) \ 2


        IF Query = 0 THEN 'as you need: 10x 3 words and then query to image name
            FOR i = 1 TO LEN(word$)
                a = ASC(word$, i) AND NOT 32
                _PRINTSTRING (StartX + (i - 1) * fw, 510), MID$(word$, i, 1)
                IF ASC(word$, i) = 32 THEN _DELAY .5: _CONTINUE
                IF a < 65 OR a > 90 THEN _CONTINUE
                _SNDPLAY AlphaSound(ASC(word$, i))
                DO WHILE _SNDPLAYING(AlphaSound(ASC(word$, i))): LOOP ' UPGRADE
            NEXT
        ELSE

            oldFont = _FONT
            _FONT 16
            'is time to query.....none _INPUTSTRING statement.... :)   i am so lasy!!!!!
            _PRINTSTRING (10, 510), "Insert image name: "

            DO UNTIL inpt$ = CHR$(13)
                inpt$ = INKEY$
                IF INT(TIMER) MOD 2 = 0 THEN cursor$ = "_" ELSE cursor$ = ""
                IF LEN(inpt$) THEN
                    word2$ = word2$ + UCASE$(inpt$)
                    IF inpt$ = CHR$(9) THEN word2$ = LEFT$(word2$, LEN(word2$) - 1) 'backspace
                END IF
                _PRINTSTRING (10 + (20 * 8), 510), word2$ + cursor$
            LOOP

            ok$ = "Correct!"
            okl = _PRINTWIDTH(ok$)
            word2$ = MID$(word2$, 1, LEN(word2$) - 1) 'erase CHR$(13) - ENTER from this word
            IF UCASE$(_TRIM$(word2$)) = UCASE$(_TRIM$(word$)) THEN
                _FONT oldFont
                StartX = _WIDTH / 2 - okl / 2
                _PRINTSTRING (StartX, 510), ok$
                SLEEP 2

            END IF
            Query = 0
            Insert_10_Different_Images
            _FONT oldFont
            index = 0
            _CONTINUE
        END IF '  if query condition


        WordPlay word$


        DO
            WHILE _MOUSEINPUT: WEND
            MX = _MOUSEX
            MY = _MOUSEY
            IF MX > Ws AND MX < We AND MY > Hs AND MY < He THEN
                IF _FILEEXISTS(_CWD$ + "\animal sounds\" + word$ + ".mp3") THEN
                    _MOUSESHOW "link"
                    IF _MOUSEBUTTON(1) THEN AnimalSound word$
                END IF

            ELSE
                _MOUSESHOW "default"
            END IF

            'keyboard access
            k = _KEYHIT
            _KEYCLEAR
            _LIMIT 10
            SELECT CASE k
                CASE 65, 97 'a,A
                    AddTags word$
                CASE 68, 100 'd,D
                    DeleteTags word$

                CASE 32 'space
                    '                _DELAY 1
                    SLEEP 1 '                                      Better for testing it
                    EXIT DO
                CASE 27 'escape
                    SYSTEM 'quit
            END SELECT
        LOOP
    NEXT Loop_it

LOOP


SUB AnimalSound (Word$)
    ASound$ = _CWD$ + "\animal sounds\" + Word$ + ".mp3"
    aAsound = _SNDOPEN(ASound$)
    _SNDPLAY aAsound
    DO WHILE _SNDPLAYING(aAsound)
        IF LEN(INKEY$) THEN _SNDSTOP (aAsound): EXIT DO
    LOOP
    _SNDCLOSE aAsound
    _MOUSESHOW "default"
END SUB




SUB GetNewWH (destWidth, destHeight, handle AS LONG, NewWidth, NewHeight) 'Sub return in variables NewWidth and NewHeight new image Width and image Height with the same ratio for optimal picture to set area width and height with [destWidth, destHeight]
    W = _WIDTH(handle)
    H = _HEIGHT(handle)
    Pw = W / destWidth
    Ph = H / destHeight
    IF W > H THEN P = Pw ELSE P = Ph
    NewWidth = W / P
    NewHeight = H / P
END SUB


SUB Insert_10_Different_Images 'place 10 different indexes from array PhotoList
    Max = UBOUND(photolist) 'PhotoList [1..?]
    REDIM IMG10(9) AS LONG
    pass = 0
    DIM i_nr AS INTEGER
    DO UNTIL pass = 10
        st:
        RANDOMIZE TIMER
        i_nr = 1 + RND * Max

        FOR t = 0 TO 9
            IF IMG10(t) = i_nr THEN GOTO st
        NEXT t

        FOR t = 0 TO 9
            IF IMG10(t) = 0 THEN IMG10(t) = i_nr: pass = pass + 1: EXIT FOR
        NEXT t
    LOOP
END SUB



SUB WordPlay (W AS STRING) 'will be replaced to my own mp3..... i never learn english, BUT I TRY IT.
    'path$ = _CWD$ + "\Words\" + W$ + ".mp3"
    'Word = _SNDOPEN(path$)
    '_SNDPLAY Word
    'DO WHILE _SNDPLAYING(Word): LOOP



    FOR l = 1 TO LEN(W)
        char = ASC(W, l)
        IF char = 32 THEN _DELAY .5: _CONTINUE
        _SNDPLAY AlphaSound(char)
        _DELAY .35
    NEXT l
END SUB


SUB BlankTop
    LINE (0, 0)-(799, 49), &HFF000000, BF 'blank out the top info
END SUB

SUB AddTags (tfile$)
    BlankTop
    _FONT f1
    LOCATE 1, 1: PRINT "Add Tag:";
    INPUT tag$
    IF tag$ <> "" THEN
        u = UBOUND(phototags)
        FOR i = 1 TO u
            IF _STRICMP(tag$, PhotoTags(i)) = 0 THEN TagExists = -1: EXIT FOR
        NEXT
        IF NOT TagExists THEN
            REDIM _PRESERVE PhotoTags(u + 1) AS STRING
            PhotoTags(u + 1) = tag$

            file$ = ".\Images\" + tfile$ + ".txt"
            OPEN file$ FOR OUTPUT AS #1
            FOR i = 1 TO u + 1
                PRINT #1, "#";
                PRINT #1, PhotoTags(i);
                PRINT #1, " ";
            NEXT
            CLOSE
        END IF
    END IF
    ShowTags
    _FONT f
END SUB

SUB DeleteTags (tfile$)
    BlankTop
    _FONT f1
    LOCATE 1, 1: PRINT "Delete Tag:";
    INPUT tag$
    IF tag$ <> "" THEN
        u = UBOUND(phototags)
        FOR i = 1 TO u
            IF _STRICMP(tag$, PhotoTags(i)) = 0 THEN TagExists = -1: EXIT FOR
        NEXT
        IF TagExists THEN
            FOR j = i TO u - 1
                PhotoTags(j) = PhotoTags(j + 1)
            NEXT
            REDIM _PRESERVE PhotoTags(u - 1) AS STRING
            file$ = ".\Images\" + tfile$ + ".txt"
            OPEN file$ FOR OUTPUT AS #1
            FOR i = 1 TO u - 1
                PRINT #1, "#";
                PRINT #1, PhotoTags(i);
                PRINT #1, " ";
            NEXT
            CLOSE
        END IF
    END IF
    ShowTags
    _FONT f
END SUB


SUB GetTags (tfile$)
    'Load the PhotoTags
    file$ = ".\Images\" + tfile$ + ".txt"
    OPEN file$ FOR BINARY AS #1
    IF LOF(1) = 0 THEN 'if there's no tags, we can't get them.
        CLOSE
        REDIM _PRESERVE PhotoTags(0) AS STRING
        EXIT SUB
    END IF
    DO UNTIL EOF(1)
        LINE INPUT #1, junk$
        l = 1
        DO UNTIL l = 0
            l = INSTR(junk$, "#")
            IF l THEN
                junk$ = MID$(junk$, l + 1)
                l1 = INSTR(junk$, "#")
                IF l1 = 0 THEN 'nothing more, we now have the tag
                    tag$ = junk$
                    l = 0
                ELSE
                    tag$ = LEFT$(junk$, l1 - 1)
                    junk$ = MID$(junk$, l1)
                END IF
            END IF
            tag$ = _TRIM$(tag$) 'no leading/tailing spaces for ease of matching
            TagFound = 0
            FOR i = 1 TO TagCount 'Check the existing tags to see if these exist
                IF PhotoTags(i) = tag$ THEN TagFound = -1: EXIT FOR
            NEXT
            IF NOT TagFound THEN 'If not, add the new tags to the list
                TagCount = TagCount + 1
                IF TagCount > UBOUND(PhotoTags) THEN REDIM _PRESERVE PhotoTags(TagCount + 1000) AS STRING
                PhotoTags(TagCount) = tag$
            END IF
        LOOP
    LOOP
    CLOSE
    REDIM _PRESERVE PhotoTags(TagCount) AS STRING
END SUB

SUB ShowTags
    BlankTop
    _FONT f1
    PRINT UBOUND(phototags); " TAGS: "
    FOR i = 1 TO UBOUND(Phototags)
        PRINT "#"; PhotoTags(i); " ";
    NEXT
    _FONT f
END SUB
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on July 31, 2019, 03:25:24 pm
Petr -- See what you think of these changes as to the forward expansion of this little idea:

I've started to implement a better search/tag system for the images, allowing us to quickly and easily customize the images we show for the user.  The input routines are now working, but I need to add the save/change routine for the tags on the photos themselves...

Currently my time is rather limited (my wife is in the hospital again, with severe dehydration from "oozing ulcers" causing her extreme stomach issues), so I'm not able to push this project forward at the speed which I'd like to see it go -- but I'll eventually get to the finish line!  It'll just take a little longer than anticipated...  (...like usual. :P )

Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 31, 2019, 04:21:38 pm
I am shocked. First attempt and program output is "DIE!"   -   good joke.  :)
Why in your color CONST you use unsigned long mark - this hexadecimal value is this type also without this mark

Wouldn't it be better to put the TAG search under the icon to activate it? Put a few icons on the right - to search for TAGs, to edit TAGs, to volume? It's just a suggestion. Is this the intention that only numbers can be entered when editing Photo Tags theme? I suppose he should go in there to enter the text?

If you want, I'll make those icon adjustments, and I would add some background. Tell me if you want to go the way when the TAG dialog will be right in the main window, or we'll complicate it a bit with icons (I can would do it tomorrow).



Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on July 31, 2019, 04:47:45 pm
Colors should *always* be UNSIGNED LONG values.

Here’s why:

Code: [Select]
SCREEN _NEWIMAGE(800,600,32)
CONST White = &HFFFFFFFF ‘bright white
COLOR White

PSET (0,0), White

IF POINT(0,0) = White THEN
    PRINT “It matches”
ELSE
   PRINT “You broke your program!  Try UNSIGNED LONG instead!
END IF

POINT returns FLOAT values (and I have no idea why they’re not integer), and 1234567890 (Whatever the unsigned value actually is) is *NOT* equal to -1 (the signed value).

Think of it as _BYTE value vs _UNSIGNED _BYTE:


DIM b AS _UNSIGNED _BYTE
b = 1
IF b = NOT 0 THEN.....

NOT 0 is -1.
1 is not equal to -1.
That’s a FALSE if statement.

If you keep colors unsigned, you’ll save yourself a lot of headaches in the future.


As for layout/changes, give me a day or two to finish up things and get them functional, and then we can tweak them and move them around a bit.

If you look, the editor allows for both numbers and text in the tags.  Year is a number, as is Week, but Sound and Theme are both strings.

Think of cat as:  Year 1, Week 1, “AT”, “Animal”.

Cat, hat, bat, sat, pat, fat....  all these are “AT” words and contain the same sound.

Year/Week/Sound info can all be gathered from the lists here: https://www.k12reader.com/worksheet/first-grade-master-spelling-list/view/

Theme is just whatever seems to make sense.  Animal, Person, Vehicle, etc...



And if you look at the internal folders, you’ll even find my voice recorded now for “cat.MP3” and “is how you spell.MP3”.   I’ll try and add more words as time allows, since nobody is volunteering to be a pet “mike-monkey” for the project.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 31, 2019, 05:17:24 pm
Yeah, like this. Aha! CONST not only passes the value but also the variable type! Okay then! I have a microphone, I promised, for the joke I will tell you tomorrow with my "English" and then I will send it to your email (only those files). Then you have fun, too.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on July 31, 2019, 05:33:35 pm
So, again, both sources synchronized to one:

Code: QB64: [Select]
  1. CONST AliceBlue = &HFFF0F8FF~& ' _RGB32(240,248,255)
  2. CONST Almond = &HFFEFDECD~& '_RGB32(239,222,205)
  3. CONST AntiqueBrass = &HFFCD9575~& '_RGB32(205,149,117)
  4. CONST AntiqueWhite = &HFFFAEBD7~& ' _RGB32(250,235,215)
  5. CONST Apricot = &HFFFDD9B5~& '_RGB32(253,217,181)
  6. CONST Aqua = &HFF00FFFF~& ' _RGB32(0,255,255)
  7. CONST Aquamarine = &HFF7FFFD4~& ' _RGB32(127,255,212)
  8. CONST Asparagus = &HFF87A96B~& '_RGB32(135,169,107)
  9. CONST AtomicTangerine = &HFFFFA474~& '_RGB32(255,164,116)
  10. CONST Azure = &HFFF0FFFF~& ' _RGB32(240,255,255)
  11. CONST BananaMania = &HFFFAE7B5~& '_RGB32(250,231,181)
  12. CONST Beaver = &HFF9F8170~& '_RGB32(159,129,112)
  13. CONST Beige = &HFFF5F5DC~& ' _RGB32(245,245,220)
  14. CONST Bisque = &HFFFFE4C4~& ' _RGB32(255,228,196)
  15. CONST Bittersweet = &HFFFD7C6E~& '_RGB32(253,124,110)
  16. CONST Black = &HFF000000~& ' _RGB32(0,0,0)
  17. CONST BlanchedAlmond = &HFFFFEBCD~& ' _RGB32(255,235,205)
  18. CONST BlizzardBlue = &HFFACE5EE~& '_RGB32(172,229,238)
  19. CONST Blue = &HFF0000FF~& ' _RGB32(0,0,255)
  20. CONST BlueBell = &HFFA2A2D0~& '_RGB32(162,162,208)
  21. CONST BlueGray = &HFF6699CC~& '_RGB32(102,153,204)
  22. CONST BlueGreen = &HFF0D98BA~& '_RGB32(13,152,186)
  23. CONST BlueViolet = &HFF8A2BE2~& ' _RGB32(138,43,226)
  24. CONST Blush = &HFFDE5D83~& '_RGB32(222,93,131)
  25. CONST BrickRed = &HFFCB4154~& '_RGB32(203,65,84)
  26. CONST Brown = &HFFA52A2A~& ' _RGB32(165,42,42)
  27. CONST BurlyWood = &HFFDEB887~& ' _RGB32(222,184,135)
  28. CONST BurntOrange = &HFFFF7F49~& '_RGB32(255,127,73)
  29. CONST BurntSienna = &HFFEA7E5D~& '_RGB32(234,126,93)
  30. CONST CadetBlue = &HFF5F9EA0~& ' _RGB32(95,158,160)
  31. CONST Canary = &HFFFFFF99~& '_RGB32(255,255,153)
  32. CONST CaribbeanGreen = &HFF1CD3A2~& '_RGB32(28,211,162)
  33. CONST CarnationPink = &HFFFFAACC~& '_RGB32(255,170,204)
  34. CONST Cerise = &HFFDD4492~& '_RGB32(221,68,146)
  35. CONST Cerulean = &HFF1DACD6~& '_RGB32(29,172,214)
  36. CONST ChartReuse = &HFF7FFF00~& ' _RGB32(127,255,0)
  37. CONST Chestnut = &HFFBC5D58~& '_RGB32(188,93,88)
  38. CONST Chocolate = &HFFD2691E~& ' _RGB32(210,105,30)
  39. CONST Copper = &HFFDD9475~& '_RGB32(221,148,117)
  40. CONST Coral = &HFFFF7F50~& ' _RGB32(255,127,80)
  41. CONST Cornflower = &HFF9ACEEB~& '_RGB32(154,206,235)
  42. CONST CornflowerBlue = &HFF6495ED~& ' _RGB32(100,149,237)
  43. CONST Cornsilk = &HFFFFF8DC~& ' _RGB32(255,248,220)
  44. CONST CottonCandy = &HFFFFBCD9~& '_RGB32(255,188,217)
  45. CONST CrayolaAquamarine = &HFF78DBE2~& '_RGB32(120,219,226)
  46. CONST CrayolaBlue = &HFF1F75FE~& '_RGB32(31,117,254)
  47. CONST CrayolaBlueViolet = &HFF7366BD~& '_RGB32(115,102,189)
  48. CONST CrayolaBrown = &HFFB4674D~& '_RGB32(180,103,77)
  49. CONST CrayolaCadetBlue = &HFFB0B7C6~& '_RGB32(176,183,198)
  50. CONST CrayolaForestGreen = &HFF6DAE81~& '_RGB32(109,174,129)
  51. CONST CrayolaGold = &HFFE7C697~& '_RGB32(231,198,151)
  52. CONST CrayolaGoldenrod = &HFFFCD975~& '_RGB32(252,217,117)
  53. CONST CrayolaGray = &HFF95918C~& '_RGB32(149,145,140)
  54. CONST CrayolaGreen = &HFF1CAC78~& '_RGB32(28,172,120)
  55. CONST CrayolaGreenYellow = &HFFF0E891~& '_RGB32(240,232,145)
  56. CONST CrayolaIndigo = &HFF5D76CB~& '_RGB32(93,118,203)
  57. CONST CrayolaLavender = &HFFFCB4D5~& '_RGB32(252,180,213)
  58. CONST CrayolaMagenta = &HFFF664AF~& '_RGB32(246,100,175)
  59. CONST CrayolaMaroon = &HFFC8385A~& '_RGB32(200,56,90)
  60. CONST CrayolaMidnightBlue = &HFF1A4876~& '_RGB32(26,72,118)
  61. CONST CrayolaOrange = &HFFFF7538~& '_RGB32(255,117,56)
  62. CONST CrayolaOrangeRed = &HFFFF2B2B~& '_RGB32(255,43,43)
  63. CONST CrayolaOrchid = &HFFE6A8D7~& '_RGB32(230,168,215)
  64. CONST CrayolaPlum = &HFF8E4585~& '_RGB32(142,69,133)
  65. CONST CrayolaRed = &HFFEE204D~& '_RGB32(238,32,77)
  66. CONST CrayolaSalmon = &HFFFF9BAA~& '_RGB32(255,155,170)
  67. CONST CrayolaSeaGreen = &HFF9FE2BF~& '_RGB32(159,226,191)
  68. CONST CrayolaSilver = &HFFCDC5C2~& '_RGB32(205,197,194)
  69. CONST CrayolaSkyBlue = &HFF80DAEB~& '_RGB32(128,218,235)
  70. CONST CrayolaSpringGreen = &HFFECEABE~& '_RGB32(236,234,190)
  71. CONST CrayolaTann = &HFFFAA76C~& '_RGB32(250,167,108)
  72. CONST CrayolaThistle = &HFFEBC7DF~& '_RGB32(235,199,223)
  73. CONST CrayolaViolet = &HFF926EAE~& '_RGB32(146,110,174)
  74. CONST CrayolaYellow = &HFFFCE883~& '_RGB32(252,232,131)
  75. CONST CrayolaYellowGreen = &HFFC5E384~& '_RGB32(197,227,132)
  76. CONST Crimson = &HFFDC143C~& ' _RGB32(220,20,60)
  77. CONST Cyan = &HFF00FFFF~& ' _RGB32(0,255,255)
  78. CONST Dandelion = &HFFFDDB6D~& '_RGB32(253,219,109)
  79. CONST DarkBlue = &HFF00008B~& ' _RGB32(0,0,139)
  80. CONST DarkCyan = &HFF008B8B~& ' _RGB32(0,139,139)
  81. CONST DarkGoldenRod = &HFFB8860B~& ' _RGB32(184,134,11)
  82. CONST DarkGray = &HFFA9A9A9~& ' _RGB32(169,169,169)
  83. CONST DarkGreen = &HFF006400~& ' _RGB32(0,100,0)
  84. CONST DarkKhaki = &HFFBDB76B~& ' _RGB32(189,183,107)
  85. CONST DarkMagenta = &HFF8B008B~& ' _RGB32(139,0,139)
  86. CONST DarkOliveGreen = &HFF556B2F~& ' _RGB32(85,107,47)
  87. CONST DarkOrange = &HFFFF8C00~& ' _RGB32(255,140,0)
  88. CONST DarkOrchid = &HFF9932CC~& ' _RGB32(153,50,204)
  89. CONST DarkRed = &HFF8B0000~& ' _RGB32(139,0,0)
  90. CONST DarkSalmon = &HFFE9967A~& ' _RGB32(233,150,122)
  91. CONST DarkSeaGreen = &HFF8FBC8F~& ' _RGB32(143,188,143)
  92. CONST DarkSlateBlue = &HFF483D8B~& ' _RGB32(72,61,139)
  93. CONST DarkSlateGray = &HFF2F4F4F~& ' _RGB32(47,79,79)
  94. CONST DarkTurquoise = &HFF00CED1~& ' _RGB32(0,206,209)
  95. CONST DarkViolet = &HFF9400D3~& ' _RGB32(148,0,211)
  96. CONST DeepPink = &HFFFF1493~& ' _RGB32(255,20,147)
  97. CONST DeepSkyBlue = &HFF00BFFF~& ' _RGB32(0,191,255)
  98. CONST Denim = &HFF2B6CC4~& '_RGB32(43,108,196)
  99. CONST DesertSand = &HFFEFCDB8~& '_RGB32(239,205,184)
  100. CONST DimGray = &HFF696969~& ' _RGB32(105,105,105)
  101. CONST DodgerBlue = &HFF1E90FF~& ' _RGB32(30,144,255)
  102. CONST Eggplant = &HFF6E5160~& '_RGB32(110,81,96)
  103. CONST ElectricLime = &HFFCEFF1D~& '_RGB32(206,255,29)
  104. CONST Fern = &HFF71BC78~& '_RGB32(113,188,120)
  105. CONST FireBrick = &HFFB22222~& ' _RGB32(178,34,34)
  106. CONST Floralwhite = &HFFFFFAF0~& ' _RGB32(255,250,240)
  107. CONST ForestGreen = &HFF228B22~& ' _RGB32(34,139,34)
  108. CONST Fuchsia = &HFFC364C5~& '_RGB32(195,100,197)
  109. CONST FuzzyWuzzy = &HFFCC6666~& '_RGB32(204,102,102)
  110. CONST Gainsboro = &HFFDCDCDC~& ' _RGB32(220,220,220)
  111. CONST GhostWhite = &HFFF8F8FF~& ' _RGB32(248,248,255)
  112. CONST Gold = &HFFFFD700~& ' _RGB32(255,215,0)
  113. CONST GoldenRod = &HFFDAA520~& ' _RGB32(218,165,32)
  114. CONST GrannySmithApple = &HFFA8E4A0~& '_RGB32(168,228,160)
  115. CONST Gray = &HFF808080~& ' _RGB32(128,128,128)
  116. CONST Green = &HFF008000~& ' _RGB32(0,128,0)
  117. CONST GreenBlue = &HFF1164B4~& '_RGB32(17,100,180)
  118. CONST GreenYellow = &HFFADFF2F~& ' _RGB32(173,255,47)
  119. CONST HoneyDew = &HFFF0FFF0~& ' _RGB32(240,255,240)
  120. CONST HotMagenta = &HFFFF1DCE~& '_RGB32(255,29,206)
  121. CONST HotPink = &HFFFF69B4~& ' _RGB32(255,105,180)
  122. CONST Inchworm = &HFFB2EC5D~& '_RGB32(178,236,93)
  123. CONST IndianRed = &HFFCD5C5C~& ' _RGB32(205,92,92)
  124. CONST Indigo = &HFF4B0082~& ' _RGB32(75,0,130)
  125. CONST Ivory = &HFFFFFFF0~& ' _RGB32(255,255,240)
  126. CONST JazzberryJam = &HFFCA3767~& '_RGB32(202,55,103)
  127. CONST JungleGreen = &HFF3BB08F~& '_RGB32(59,176,143)
  128. CONST Khaki = &HFFF0E68C~& ' _RGB32(240,230,140)
  129. CONST LaserLemon = &HFFFEFE22~& '_RGB32(254,254,34)
  130. CONST Lavender = &HFFE6E6FA~& ' _RGB32(230,230,250)
  131. CONST LavenderBlush = &HFFFFF0F5~& ' _RGB32(255,240,245)
  132. CONST LawnGreen = &HFF7CFC00~& ' _RGB32(124,252,0)
  133. CONST LemonChiffon = &HFFFFFACD~& ' _RGB32(255,250,205)
  134. CONST LemonYellow = &HFFFFF44F~& '_RGB32(255,244,79)
  135. CONST LightBlue = &HFFADD8E6~& ' _RGB32(173,216,230)
  136. CONST LightCoral = &HFFF08080~& ' _RGB32(240,128,128)
  137. CONST LightCyan = &HFFE0FFFF~& ' _RGB32(224,255,255)
  138. CONST LightGoldenRodYellow = &HFFFAFAD2~& ' _RGB32(250,250,210)
  139. CONST LightGray = &HFFD3D3D3~& ' _RGB32(211,211,211)
  140. CONST LightGreen = &HFF90EE90~& ' _RGB32(144,238,144)
  141. CONST LightPink = &HFFFFB6C1~& ' _RGB32(255,182,193)
  142. CONST LightSalmon = &HFFFFA07A~& ' _RGB32(255,160,122)
  143. CONST LightSeaGreen = &HFF20B2AA~& ' _RGB32(32,178,170)
  144. CONST LightSkyBlue = &HFF87CEFA~& ' _RGB32(135,206,250)
  145. CONST LightSlateGray = &HFF778899~& ' _RGB32(119,136,153)
  146. CONST LightSteelBlue = &HFFB0C4DE~& ' _RGB32(176,196,222)
  147. CONST LightYellow = &HFFFFFFE0~& ' _RGB32(255,255,224)
  148. CONST Lime = &HFF00FF00~& ' _RGB32(0,255,0)
  149. CONST LimeGreen = &HFF32CD32~& ' _RGB32(50,205,50)
  150. CONST Linen = &HFFFAF0E6~& ' _RGB32(250,240,230)
  151. CONST MacaroniAndCheese = &HFFFFBD88~& '_RGB32(255,189,136)
  152. CONST Magenta = &HFFFF00FF~& ' _RGB32(255,0,255)
  153. CONST MagicMint = &HFFAAF0D1~& '_RGB32(170,240,209)
  154. CONST Mahogany = &HFFCD4A4C~& '_RGB32(205,74,76)
  155. CONST Maize = &HFFEDD19C~& '_RGB32(237,209,156)
  156. CONST Manatee = &HFF979AAA~& '_RGB32(151,154,170)
  157. CONST MangoTango = &HFFFF8243~& '_RGB32(255,130,67)
  158. CONST Maroon = &HFF800000~& ' _RGB32(128,0,0)
  159. CONST Mauvelous = &HFFEF98AA~& '_RGB32(239,152,170)
  160. CONST MediumAquamarine = &HFF66CDAA~& ' _RGB32(102,205,170)
  161. CONST MediumBlue = &HFF0000CD~& ' _RGB32(0,0,205)
  162. CONST MediumOrchid = &HFFBA55D3~& ' _RGB32(186,85,211)
  163. CONST MediumPurple = &HFF9370DB~& ' _RGB32(147,112,219)
  164. CONST MediumSeaGreen = &HFF3CB371~& ' _RGB32(60,179,113)
  165. CONST MediumSlateBlue = &HFF7B68EE~& ' _RGB32(123,104,238)
  166. CONST MediumSpringGreen = &HFF00FA9A~& ' _RGB32(0,250,154)
  167. CONST MediumTurquoise = &HFF48D1CC~& ' _RGB32(72,209,204)
  168. CONST MediumVioletRed = &HFFC71585~& ' _RGB32(199,21,133)
  169. CONST Melon = &HFFFDBCB4~& '_RGB32(253,188,180)
  170. CONST MidnightBlue = &HFF191970~& ' _RGB32(25,25,112)
  171. CONST MintCream = &HFFF5FFFA~& ' _RGB32(245,255,250)
  172. CONST MistyRose = &HFFFFE4E1~& ' _RGB32(255,228,225)
  173. CONST Moccasin = &HFFFFE4B5~& ' _RGB32(255,228,181)
  174. CONST MountainMeadow = &HFF30BA8F~& '_RGB32(48,186,143)
  175. CONST Mulberry = &HFFC54B8C~& '_RGB32(197,75,140)
  176. CONST NavajoWhite = &HFFFFDEAD~& ' _RGB32(255,222,173)
  177. CONST Navy = &HFF000080~& ' _RGB32(0,0,128)
  178. CONST NavyBlue = &HFF1974D2~& '_RGB32(25,116,210)
  179. CONST NeonCarrot = &HFFFFA343~& '_RGB32(255,163,67)
  180. CONST OldLace = &HFFFDF5E6~& ' _RGB32(253,245,230)
  181. CONST Olive = &HFF808000~& ' _RGB32(128,128,0)
  182. CONST OliveDrab = &HFF6B8E23~& ' _RGB32(107,142,35)
  183. CONST OliveGreen = &HFFBAB86C~& '_RGB32(186,184,108)
  184. CONST Orange = &HFFFFA500~& ' _RGB32(255,165,0)
  185. CONST OrangeRed = &HFFFF4500~& ' _RGB32(255,69,0)
  186. CONST OrangeYellow = &HFFF8D568~& '_RGB32(248,213,104)
  187. CONST Orchid = &HFFDA70D6~& ' _RGB32(218,112,214)
  188. CONST OuterSpace = &HFF414A4C~& '_RGB32(65,74,76)
  189. CONST OutrageousOrange = &HFFFF6E4A~& '_RGB32(255,110,74)
  190. CONST PacificBlue = &HFF1CA9C9~& '_RGB32(28,169,201)
  191. CONST PaleGoldenRod = &HFFEEE8AA~& ' _RGB32(238,232,170)
  192. CONST PaleGreen = &HFF98FB98~& ' _RGB32(152,251,152)
  193. CONST PaleTurquoise = &HFFAFEEEE~& ' _RGB32(175,238,238)
  194. CONST PaleVioletRed = &HFFDB7093~& ' _RGB32(219,112,147)
  195. CONST PapayaWhip = &HFFFFEFD5~& ' _RGB32(255,239,213)
  196. CONST Peach = &HFFFFCFAB~& '_RGB32(255,207,171)
  197. CONST PeachPuff = &HFFFFDAB9~& ' _RGB32(255,218,185)
  198. CONST Periwinkle = &HFFC5D0E6~& '_RGB32(197,208,230)
  199. CONST Peru = &HFFCD853F~& ' _RGB32(205,133,63)
  200. CONST PiggyPink = &HFFFDDDE6~& '_RGB32(253,221,230)
  201. CONST PineGreen = &HFF158078~& '_RGB32(21,128,120)
  202. CONST Pink = &HFFFFC0CB~& ' _RGB32(255,192,203)
  203. CONST PinkFlamingo = &HFFFC74FD~& '_RGB32(252,116,253)
  204. CONST PinkSherbet = &HFFF78FA7~& '_RGB32(247,143,167)
  205. CONST Plum = &HFFDDA0DD~& ' _RGB32(221,160,221)
  206. CONST PowderBlue = &HFFB0E0E6~& ' _RGB32(176,224,230)
  207. CONST Purple = &HFF800080~& ' _RGB32(128,0,128)
  208. CONST PurpleHeart = &HFF7442C8~& '_RGB32(116,66,200)
  209. CONST PurpleMountainsMajesty = &HFF9D81BA~& '_RGB32(157,129,186)
  210. CONST PurplePizzazz = &HFFFE4EDA~& '_RGB32(254,78,218)
  211. CONST RadicalRed = &HFFFF496C~& '_RGB32(255,73,108)
  212. CONST RawSienna = &HFFD68A59~& '_RGB32(214,138,89)
  213. CONST RawUmber = &HFF714B23~& '_RGB32(113,75,35)
  214. CONST RazzleDazzleRose = &HFFFF48D0~& '_RGB32(255,72,208)
  215. CONST Razzmatazz = &HFFE3256B~& '_RGB32(227,37,107)
  216. CONST Red = &HFFFF0000~& ' _RGB32(255,0,0)
  217. CONST RedOrange = &HFFFF5349~& '_RGB32(255,83,73)
  218. CONST RedViolet = &HFFC0448F~& '_RGB32(192,68,143)
  219. CONST RobinsEggBlue = &HFF1FCECB~& '_RGB32(31,206,203)
  220. CONST RosyBrown = &HFFBC8F8F~& ' _RGB32(188,143,143)
  221. CONST RoyalBlue = &HFF4169E1~& ' _RGB32(65,105,225)
  222. CONST RoyalPurple = &HFF7851A9~& '_RGB32(120,81,169)
  223. CONST SaddleBrown = &HFF8B4513~& ' _RGB32(139,69,19)
  224. CONST Salmon = &HFFFA8072~& ' _RGB32(250,128,114)
  225. CONST SandyBrown = &HFFF4A460~& ' _RGB32(244,164,96)
  226. CONST Scarlet = &HFFFC2847~& '_RGB32(252,40,71)
  227. CONST ScreaminGreen = &HFF76FF7A~& '_RGB32(118,255,122)
  228. CONST SeaGreen = &HFF2E8B57~& ' _RGB32(46,139,87)
  229. CONST SeaShell = &HFFFFF5EE~& ' _RGB32(255,245,238)
  230. CONST Sepia = &HFFA5694F~& '_RGB32(165,105,79)
  231. CONST Shadow = &HFF8A795D~& '_RGB32(138,121,93)
  232. CONST Shamrock = &HFF45CEA2~& '_RGB32(69,206,162)
  233. CONST ShockingPink = &HFFFB7EFD~& '_RGB32(251,126,253)
  234. CONST Sienna = &HFFA0522D~& ' _RGB32(160,82,45)
  235. CONST Silver = &HFFC0C0C0~& ' _RGB32(192,192,192)
  236. CONST SkyBlue = &HFF87CEEB~& ' _RGB32(135,206,235)
  237. CONST SlateBlue = &HFF6A5ACD~& ' _RGB32(106,90,205)
  238. CONST SlateGray = &HFF708090~& ' _RGB32(112,128,144)
  239. CONST Snow = &HFFFFFAFA~& ' _RGB32(255,250,250)
  240. CONST SpringGreen = &HFF00FF7F~& ' _RGB32(0,255,127)
  241. CONST SteelBlue = &HFF4682B4~& ' _RGB32(70,130,180)
  242. CONST Sunglow = &HFFFFCF48~& '_RGB32(255,207,72)
  243. CONST SunsetOrange = &HFFFD5E53~& '_RGB32(253,94,83)
  244. CONST Tann = &HFFD2B48C~& ' _RGB32(210,180,140)
  245. CONST Teal = &HFF008080~& ' _RGB32(0,128,128)
  246. CONST TealBlue = &HFF18A7B5~& '_RGB32(24,167,181)
  247. CONST Thistle = &HFFD8BFD8~& ' _RGB32(216,191,216)
  248. CONST TickleMePink = &HFFFC89AC~& '_RGB32(252,137,172)
  249. CONST Timberwolf = &HFFDBD7D2~& '_RGB32(219,215,210)
  250. CONST Tomato = &HFFFF6347~& ' _RGB32(255,99,71)
  251. CONST TropicalRainForest = &HFF17806D~& '_RGB32(23,128,109)
  252. CONST Tumbleweed = &HFFDEAA88~& '_RGB32(222,170,136)
  253. CONST Turquoise = &HFF40E0D0~& ' _RGB32(64,224,208)
  254. CONST TurquoiseBlue = &HFF77DDE7~& '_RGB32(119,221,231)
  255. CONST UnmellowYellow = &HFFFFFF66~& '_RGB32(255,255,102)
  256. CONST Violet = &HFFEE82EE~& ' _RGB32(238,130,238)
  257. CONST VioletBlue = &HFF324AB2~& '_RGB32(50,74,178)
  258. CONST VioletRed = &HFFF75394~& '_RGB32(247,83,148)
  259. CONST VividTangerine = &HFFFFA089~& '_RGB32(255,160,137)
  260. CONST VividViolet = &HFF8F509D~& '_RGB32(143,80,157)
  261. CONST Wheat = &HFFF5DEB3~& ' _RGB32(245,222,179)
  262. CONST White = &HFFFFFFFF~& ' _RGB32(255,255,255)
  263. CONST Whitesmoke = &HFFF5F5F5~& ' _RGB32(245,245,245)
  264. CONST WildBlueYonder = &HFFA2ADD0~& '_RGB32(162,173,208)
  265. CONST WildStrawberry = &HFFFF43A4~& '_RGB32(255,67,164)
  266. CONST WildWatermelon = &HFFFC6C85~& '_RGB32(252,108,133)
  267. CONST Wisteria = &HFFCDA4DE~& '_RGB32(205,164,222)
  268. CONST Yellow = &HFFFFFF00~& ' _RGB32(255,255,0)
  269. CONST YellowGreen = &HFF9ACD32~& ' _RGB32(154,205,50)
  270. CONST YellowOrange = &HFFFFAE42~& '_RGB32(255,174,66)
  271.  
  272.  
  273. TYPE TagType
  274.     Year AS INTEGER
  275.     Week AS INTEGER
  276.     Theme AS STRING
  277.  
  278.  
  279. SCREEN _NEWIMAGE(800, 600, 32)
  280. _TITLE "Spell It Aloud"
  281.  
  282. ImageDir$ = ".\Images\"
  283. SoundDir$ = ".\Alphabet Sounds\"
  284. CONST TagDir$ = ".\Image Tags\"
  285. DIM SHARED PhotoTag AS TagType
  286. DIM SHARED LimitTag AS TagType
  287.  
  288. DIM SHARED AlphaSound(65 TO 90), f AS LONG, f1 AS LONG
  289. REDIM SHARED PhotoList(100000) AS STRING
  290. REDIM SHARED IMG10(9) AS LONG 'array fo 10 different images. Contains diferent indexes numbers for PhotoList()
  291.  
  292.  
  293. 'load our fonts
  294. f = _LOADFONT("courbd.ttf", 84, "MONOSPACE")
  295. f1 = _LOADFONT("courbd.ttf", 48, "MONOSPACE")
  296.  
  297.  
  298. 'Load the alphabet sound library
  299. FOR i = 65 TO 90
  300.     temp$ = SoundDir$ + CHR$(i) + ".ogg"
  301.     AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  302.  
  303.  
  304. _DELAY 1 'Give everything a moment to initialize and get started for us.
  305. ChangeSearchTags
  306. Insert_10_Different_Images 'insert 10 different indexes numbers from PhotoList, to array IMG10() [LONG] [0..9]
  307.  
  308.  
  309.     '    DO UNTIL photochosen <> oldpic
  310.     '        RANDOMIZE TIMER
  311.     '       photochosen = INT(RND * PhotoCount) + 1
  312.     '  LOOP
  313.     '  oldpic = photochosen
  314.  
  315.     photochosen = IMG10(index)
  316.     index = index + 1
  317.     IF index > 9 THEN index = INT(1 + RND * 8): Query = 1
  318.  
  319.     fullpath$ = PhotoList(photochosen)
  320.     word$ = UCASE$(PhotoList(photochosen))
  321.     word$ = MID$(word$, _INSTRREV(word$, "\") + 1)
  322.     word$ = LEFT$(word$, INSTR(word$, ".") - 1)
  323.     IF tempimage < -1 THEN _FREEIMAGE tempimage
  324.     tempimage = _LOADIMAGE(PhotoList(photochosen), 32)
  325.  
  326.  
  327.     'Put the image to the screen                                UPGRADE
  328.  
  329.  
  330.     FOR Loop_it = 1 TO 1 'as you say. 3x one word + image, this 10x with different images an then query.
  331.  
  332.         CLS
  333.         _FONT f1
  334.         CenterText 0, 0, 800, 50, "Spell It Aloud"
  335.         _FONT f
  336.  
  337.  
  338.  
  339.  
  340.         'program photo area is 700 x 450 pixels. So:
  341.         GetNewWH 500, 450, tempimage, nW, nH
  342.  
  343.  
  344.         Ws = 300 - (nW / 2)
  345.         We = 300 + (nW / 2)
  346.         Hs = 300 - (nH / 2) - 25
  347.         He = 300 + (nH / 2) - 25
  348.  
  349.         _PUTIMAGE (Ws, Hs)-(We, He), tempimage
  350.  
  351.         DisplayTags 575, 150, "Search Tags", LimitTag
  352.         DisplayTags 575, 300, "Photo Tags", PhotoTag
  353.  
  354.  
  355.  
  356.         'Put the letters to the screen one by one
  357.         pw = _PRINTWIDTH(word$)
  358.         StartX = (600 - pw) \ 2
  359.  
  360.  
  361.         IF Query = 0 THEN 'as you need: 10x 3 words and then query to image name
  362.             FOR i = 1 TO LEN(word$)
  363.                 a = ASC(word$, i) AND NOT 32
  364.                 _PRINTSTRING (StartX + (i - 1) * fw, 510), MID$(word$, i, 1)
  365.                 IF ASC(word$, i) = 32 THEN _DELAY .5: _CONTINUE
  366.                 IF a < 65 OR a > 90 THEN _CONTINUE
  367.                 _SNDPLAY AlphaSound(ASC(word$, i))
  368.                 DO WHILE _SNDPLAYING(AlphaSound(ASC(word$, i))): LOOP ' UPGRADE
  369.             NEXT
  370.         ELSE
  371.  
  372.             oldFont = _FONT
  373.             _FONT 16
  374.             'is time to query.....none _INPUTSTRING statement.... :)   i am so lasy!!!!!
  375.             _PRINTSTRING (10, 510), "Insert image name: "
  376.  
  377.             DO UNTIL inpt$ = CHR$(13)
  378.                 inpt$ = INKEY$
  379.                 IF INT(TIMER) MOD 2 = 0 THEN cursor$ = "_" ELSE cursor$ = ""
  380.                 IF LEN(inpt$) THEN
  381.                     word2$ = word2$ + UCASE$(inpt$)
  382.                     IF inpt$ = CHR$(9) THEN word2$ = LEFT$(word2$, LEN(word2$) - 1) 'backspace
  383.                 END IF
  384.                 _PRINTSTRING (10 + (20 * 8), 510), word2$ + cursor$
  385.             LOOP
  386.  
  387.             ok$ = "Correct!"
  388.             okl = _PRINTWIDTH(ok$)
  389.             word2$ = MID$(word2$, 1, LEN(word2$) - 1) 'erase CHR$(13) - ENTER from this word
  390.             IF UCASE$(_TRIM$(word2$)) = UCASE$(_TRIM$(word$)) THEN
  391.                 _FONT oldFont
  392.                 StartX = _WIDTH / 2 - okl / 2
  393.                 _PRINTSTRING (StartX, 510), ok$
  394.                 SLEEP 2
  395.  
  396.             END IF
  397.             Query = 0
  398.             Insert_10_Different_Images
  399.             _FONT oldFont
  400.             index = 0
  401.             _CONTINUE
  402.         END IF '  if query condition
  403.  
  404.  
  405.         WordPlay word$
  406.  
  407.  
  408.         DO
  409.             WHILE _MOUSEINPUT: WEND
  410.             MX = _MOUSEX
  411.             MY = _MOUSEY
  412.             MB = _MOUSEBUTTON(1)
  413.             IF MX > Ws AND MX < We AND MY > Hs AND MY < He THEN
  414.                 IF _FILEEXISTS(_CWD$ + "\animal sounds\" + word$ + ".mp3") THEN
  415.                     _MOUSESHOW "link"
  416.                     IF MB THEN AnimalSound word$
  417.                 END IF
  418.  
  419.             ELSE
  420.                 _MOUSESHOW "default"
  421.             END IF
  422.  
  423.             'keyboard access
  424.             k = _KEYHIT
  425.  
  426.             _KEYCLEAR
  427.             _LIMIT 10
  428.             SELECT CASE k
  429.                 CASE 32 'space
  430.                     '                _DELAY 1
  431.                     SLEEP 1 '                                      Better for testing it
  432.                     EXIT DO
  433.                 CASE 27 'escape
  434.                     SYSTEM 'quit
  435.             END SELECT
  436.         LOOP
  437.     NEXT Loop_it
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446. SUB AnimalSound (Word$)
  447.     ASound$ = _CWD$ + "\animal sounds\" + Word$ + ".mp3"
  448.     aAsound = _SNDOPEN(ASound$)
  449.     _SNDPLAY aAsound
  450.     DO WHILE _SNDPLAYING(aAsound)
  451.         IF LEN(INKEY$) THEN _SNDSTOP (aAsound): EXIT DO
  452.     LOOP
  453.     _SNDCLOSE aAsound
  454.     _MOUSESHOW "default"
  455.  
  456.  
  457.  
  458.  
  459. SUB GetNewWH (destWidth, destHeight, handle AS LONG, NewWidth, NewHeight) 'Sub return in variables NewWidth and NewHeight new image Width and image Height with the same ratio for optimal picture to set area width and height with [destWidth, destHeight]
  460.     W = _WIDTH(handle)
  461.     H = _HEIGHT(handle)
  462.     Pw = W / destWidth
  463.     Ph = H / destHeight
  464.     IF W > H THEN P = Pw ELSE P = Ph
  465.     NewWidth = W / P
  466.     NewHeight = H / P
  467.  
  468.  
  469. SUB Insert_10_Different_Images 'place 10 different indexes from array PhotoList
  470.     Max = UBOUND(photolist) 'PhotoList [1..?]
  471.     REDIM IMG10(9) AS LONG
  472.     pass = 0
  473.     DIM i_nr AS INTEGER
  474.     DO UNTIL pass = 10
  475.         st:
  476.         RANDOMIZE TIMER
  477.         i_nr = 1 + RND * Max
  478.  
  479.         FOR t = 0 TO 9
  480.             IF IMG10(t) = i_nr THEN GOTO st
  481.         NEXT t
  482.  
  483.         FOR t = 0 TO 9
  484.             IF IMG10(t) = 0 THEN IMG10(t) = i_nr: pass = pass + 1: EXIT FOR
  485.         NEXT t
  486.     LOOP
  487.  
  488.  
  489.  
  490. SUB WordPlay (W AS STRING) 'will be replaced to my own mp3..... i never learn english, BUT I TRY IT.
  491.     'path$ = _CWD$ + "\Words\" + W$ + ".mp3"
  492.     'Word = _SNDOPEN(path$)
  493.     '_SNDPLAY Word
  494.     'DO WHILE _SNDPLAYING(Word): LOOP
  495.  
  496.  
  497.  
  498.     FOR l = 1 TO LEN(W)
  499.         char = ASC(W, l)
  500.         IF char = 32 THEN _DELAY .5: _CONTINUE
  501.         _SNDPLAY AlphaSound(char)
  502.         _DELAY .35
  503.     NEXT l
  504.  
  505.  
  506. SUB ChangeSearchTags
  507.     'Get a listing of the files
  508.     PhotoList$ = ImageDir$ + "*.bmp " + ImageDir$ + "*.jpg " + ImageDir$ + "*.png " + ImageDir$ + "*.gif "
  509.     SHELL _HIDE "DIR " + PhotoList$ + "/b /s /a-d >PhotoList.txt"
  510.  
  511.     REDIM _PRESERVE PhotoList(100000)
  512.  
  513.     'Load those names into a file.
  514.     OPEN "Photolist.txt" FOR BINARY AS #1
  515.     PhotoCount = 0
  516.     DO UNTIL EOF(1)
  517.         LINE INPUT #1, fullpath$
  518.         word$ = MID$(fullpath$, _INSTRREV(fullpath$, "\") + 1)
  519.         word$ = LEFT$(word$, INSTR(word$, ".") - 1)
  520.  
  521.         '        IF LimitTag.Year = 0 AND LimitTag.Week = 0 AND _TRIM$(LimitTag.Sound) = "" AND _TRIM$(LimitTag.Theme) = "" THEN
  522.  
  523.         file$ = TagDir$ + word$ + ".txt"
  524.         IF _FILEEXISTS(file$) THEN
  525.             OPEN file$ FOR INPUT AS #2
  526.             INPUT #2, PhotoTag.Year
  527.             INPUT #2, PhotoTag.Week
  528.             INPUT #2, PhotoTag.Sound
  529.             INPUT #2, PhotoTag.Theme
  530.         ELSE
  531.             OPEN file$ FOR OUTPUT AS #2
  532.             PRINT #2, 0
  533.             PRINT #2, 0
  534.             PRINT #2, ""
  535.             PRINT #2, ""
  536.         END IF
  537.         CLOSE #2
  538.         good = -1
  539.         IF LimitTag.Year <> 0 AND LimitTag.Year <> PhotoTag.Year THEN good = 0
  540.         IF LimitTag.Week <> 0 AND LimitTag.Week <> PhotoTag.Week THEN good = 0
  541.  
  542.         IF LimitTag.Sound <> "" AND LimitTag.Sound <> PhotoTag.Sound THEN good = 0
  543.         IF LimitTag.Theme <> "" AND LimitTag.Theme <> PhotoTag.Theme THEN good = 0
  544.         IF good THEN
  545.             PhotoCount = PhotoCount + 1
  546.             PhotoList(PhotoCount) = fullpath$
  547.         END IF
  548.     LOOP
  549.  
  550.     REDIM _PRESERVE PhotoList(PhotoCount)
  551.     CLOSE
  552.  
  553. FUNCTION ChangeValue$ (x, y, word$, limit)
  554.     s = SaveState
  555.     _FONT 16
  556.     temp$ = CHR$(179)
  557.     _KEYCLEAR
  558.     DO
  559.         Box x, y, 100, 20, 1, Black, Gold
  560.         CenterText x, y, x + 100, y + 20, temp$
  561.         k = _KEYHIT
  562.         SELECT CASE k
  563.             CASE 8
  564.                 word$ = LEFT$(word$, LEN(word$) - 1)
  565.             CASE 13
  566.                 EXIT DO
  567.             CASE 48 TO 57 'We'll always accept numeric input
  568.                 word$ = word$ + CHR$(k)
  569.             CASE 65 TO 90, 97 TO 122 'A-Z (a-z) only when we're dealing with a string
  570.                 IF NOT limit THEN word$ = word$ + CHR$(k)
  571.         END SELECT
  572.         temp$ = word$ + CHR$(179)
  573.         _LIMIT 10
  574.     LOOP
  575.     ChangeValue$ = word$
  576.     RestoreState s
  577.  
  578. SUB DisplayTags (x, y, Title AS STRING, DisplayTag AS TagType)
  579.     s = SaveState
  580.     _FONT 16
  581.     w = 200: h = 106
  582.     Box x, y, w, h, 2, BlueGray, Gold
  583.     COLOR Gold, 0
  584.     CenterText x, y + 2, x + 200, y + 20, Title
  585.     LINE (x + 1, y + 19)-STEP(w - 2, 0), Gold
  586.     COLOR White, 0
  587.     xs = x + 24: ys = y + 24 'x/y start after the box offset
  588.     _PRINTSTRING (xs, ys), "Year :"
  589.     _PRINTSTRING (xs, ys + 20), "Week :"
  590.     _PRINTSTRING (xs, ys + 40), "Sound:"
  591.     _PRINTSTRING (xs, ys + 60), "Theme:"
  592.     bxs = xs + 50: bys = ys - 2 'x/y start for the display boxes
  593.     FOR i = 0 TO 3
  594.         Box bxs, bys + i * 20, 100, 20, 1, Black, Gold
  595.     NEXT
  596.     CenterValue bxs, bys, bxs + 100, bys + 20, DisplayTag.Year
  597.     CenterValue bxs, bys + 20, bxs + 100, bys + 40, DisplayTag.Week
  598.     CenterText bxs, bys + 40, bxs + 100, bys + 60, DisplayTag.Sound
  599.     CenterText bxs, bys + 60, bxs + 100, bys + 80, DisplayTag.Theme
  600.     RestoreState s
  601.  
  602. SUB Box (x, y, wide, high, thick, Kolor AS _UNSIGNED LONG, Trim AS _UNSIGNED LONG)
  603.     LINE (x, y)-STEP(wide, high), Kolor, BF
  604.     FOR i = 0 TO thick - 1
  605.         LINE (x + i, y + i)-STEP(wide - 2 * i, high - 2 * i), Trim, B
  606.     NEXT
  607.  
  608.  
  609. SUB CenterText (x1, y1, x2, y2, text$)
  610.     text$ = _TRIM$(text$)
  611.     xmax = x2 - x1: ymax = y2 - y1
  612.     textlength = _PRINTWIDTH(text$)
  613.     xpos = (xmax - textlength) / 2
  614.     ypos = (ymax - _FONTHEIGHT) / 2
  615.     _PRINTSTRING (x1 + xpos, y1 + ypos), text$
  616.  
  617. SUB CenterValue (x1, y1, x2, y2, value AS LONG)
  618.     text$ = _TRIM$(STR$(value))
  619.     CenterText x1, y1, x2, y2, text$
  620.  
  621. FUNCTION SaveState
  622.     TYPE SaveStateType
  623.         InUse AS INTEGER
  624.         DC AS INTEGER
  625.         BG AS INTEGER
  626.         F AS INTEGER
  627.         D AS INTEGER
  628.         S AS INTEGER
  629.         Disp AS INTEGER
  630.         CurX AS INTEGER
  631.         CurY AS INTEGER
  632.     END TYPE
  633.     DIM SS AS SaveStateType, Temp AS SaveStateType
  634.     SHARED NSS AS LONG 'Number of Saved States
  635.     SHARED SaveMem AS _MEM
  636.     IF NOT _MEMEXISTS(SaveMem) THEN
  637.         SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
  638.         $CHECKING:OFF
  639.         _MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
  640.         $CHECKING:ON
  641.     END IF
  642.  
  643.     'Data to Save
  644.     SS.InUse = -1
  645.     SS.F = _FONT
  646.     SS.DC = _DEFAULTCOLOR
  647.     SS.BG = _BACKGROUNDCOLOR
  648.     SS.D = _DEST
  649.     SS.S = _SOURCE
  650.     SS.Disp = _AUTODISPLAY
  651.     SS.CurX = POS(0)
  652.     SS.CurY = CSRLIN
  653.     FOR i = 1 TO NSS
  654.         o = (i - 1) * LEN(SS)
  655.         _MEMGET SaveMem, SaveMem.OFFSET + o, Temp
  656.         IF Temp.InUse = 0 THEN
  657.             _MEMPUT SaveMem, SaveMem.OFFSET + o, SS
  658.             SaveState = i
  659.             EXIT FUNCTION
  660.         END IF
  661.     NEXT
  662.    _MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
  663.     NSS = NSS + 1
  664.     SaveState = NSS
  665.  
  666. SUB RestoreState (WhichOne AS LONG)
  667.     DIM SS AS SaveStateType
  668.     SHARED NSS AS LONG 'Number of Saved States
  669.     SHARED SaveMem AS _MEM
  670.     _MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  671.     IF SS.InUse THEN
  672.         SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
  673.         $CHECKING:OFF
  674.         _MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  675.         $CHECKING:ON
  676.         _FONT SS.F
  677.         COLOR SS.DC, SS.BG
  678.         _DEST SS.D
  679.         _SOURCE SS.S
  680.         IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
  681.         LOCATE SS.CurY, SS.CurX
  682.     END IF
  683.  

 [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on July 31, 2019, 08:48:30 pm
And now it all starts to pull together nicely.

The little search areas now search and no longer tell you to die if they don't make a match.
You can click and update search or photo tags with a simple click of the mouse.
If the word "cat" comes up, you'll now get to hear my voice talking to you!  Aren't you lucky!!



So what's next?

A replay button would be nice, so the user could hear the word again if they want.
A next button so we don't have to use the spacebar, unless we just want to.
A mouse click to exit the input routines when changing the search/photo tags.  It's amazing how naturally that feels to me, and how much I notice not being able to do it.
An option to REVIEW, where we can replay the current choices X number of times to review them.
An option to QUIZ, where we then take the quiz on the current options and see if we can actually spell them.

And after that??

I dunno!  At that point, I think just grabbing photos, sounds, and organizing them so we'd have a large assortment for learning would be all that we'd have left to gather!
Title: Re: Spell It Aloud (Help Requested)
Post by: bplus on July 31, 2019, 09:29:22 pm
WT????

Steve's code with comment in CONST line does not work but this does!
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. CONST White = &HFFFFFFFF
  3.  
  4. COLOR White
  5.  
  6. PSET (0, 0), White
  7.  
  8. IF POINT(0, 0) = White THEN
  9.     PRINT "it matches"
  10.     PRINT "You broke your program!" '  Try UNSIGNED LONG instead!
  11.  
  12.  
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 01, 2019, 01:48:45 am
Just very fast input:


The same correct output as BPlus:

Code: QB64: [Select]
  1. CONST whiteA = &HFFFFFFFF
  2. CONST whiteB = &HFFFFFFFF~&
  3.  
  4. SCREEN _NEWIMAGE(1024, 768, 32)
  5. PSET (1, 1), whiteA
  6. IF POINT(1, 1) = whiteA THEN PRINT "Color WhiteA match"
  7. IF POINT(1, 1) = whiteB THEN PRINT "Color WhiteB match"
  8.  
  9. PRINT whiteA, whiteB, POINT(1, 1)
  10.  
  11.  


+ found CRITICAL IDE bug. For killing IDE write  this line:

CONST whiteA = &HFFFFFFFF\

it is a typo - killer for IDE.

see us later

Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 01, 2019, 02:49:09 pm
I still do on it, but today not so fast...


  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 01, 2019, 03:26:29 pm
Upgraded your ChangeValue$ for mouse - click - quit possibility. Problem is, that this click muss be on place limited by conditions on row 436..to 470.

Code: QB64: [Select]
  1. FUNCTION ChangeValue$ (x, y, word$, limit)
  2.     s = SaveState
  3.     _FONT 16
  4.     temp$ = CHR$(179)
  5.     _KEYCLEAR
  6.     DO UNTIL _MOUSEBUTTON(1) = 0 'wait until is mouse buffer empty
  7.         WHILE _MOUSEINPUT: WEND
  8.     LOOP
  9.     DO
  10.         WHILE _MOUSEINPUT: WEND '  again read mouse events
  11.         IF _MOUSEBUTTON(1) THEN EXIT DO 'and if is click, do the same as enter
  12.  
  13.         Box x, y, 100, 20, 1, Black, Gold
  14.         CenterText x, y, x + 100, y + 20, temp$
  15.         k = _KEYHIT
  16.         SELECT CASE k
  17.             CASE 8
  18.                 word$ = LEFT$(word$, LEN(word$) - 1)
  19.             CASE 13
  20.                 EXIT DO
  21.             CASE 48 TO 57 'We'll always accept numeric input
  22.                 word$ = word$ + CHR$(k)
  23.             CASE 65 TO 90, 97 TO 122 'A-Z (a-z) only when we're dealing with a string
  24.                 IF NOT limit THEN word$ = word$ + CHR$(k)
  25.         END SELECT
  26.         temp$ = word$ + CHR$(179)
  27.         _LIMIT 10
  28.     LOOP
  29.     ChangeValue$ = word$
  30.     RestoreState s
  31.  
  32.  


off topic - Steve, yesterday you had the funny report Die! in program  and today we solved killed IDEs after CONST. Maybe ghosts work ...  :)
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 01, 2019, 03:53:32 pm
I still do on it, but today not so fast...

I've gotten side-tracked as well, and haven't been working on it as I'd intended.  Today I've been digging around and playing in QB64's internals itself, corrrecting the IDE killing glitch and adding in a $COLOR32 metacommand (for my personal pleasure,  even if it's not for anybody else's).  You can see my post on it here: https://www.qb64.org/forum/index.php?topic=1556.0

I'll try and look at your changes and work on this again tomorrow, if time allows.  My wife thinks she should be released from the hospital later tonight, or early in the morning, and my free time is going to disappear while helping her get settled home once more.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 01, 2019, 04:10:19 pm
Okay, I will add a bit now and when it comes, I will add it here.

Of course, health and family are always in the first place. I wish you full health for you both.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 01, 2019, 05:23:13 pm
So here is next develop version with icons (buttons). Tomorrow i try solving buttons reaction time (sometimes is loooong). Add new folder "Config" contains background image and icon image. Functional buttons:
next image, replay word, set volume, quit. Buttons for quiz and for test are not programmed.


Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 01, 2019, 05:28:52 pm
So here is next develop version with icons (buttons). Tomorrow i try solving buttons reaction time (sometimes is loooong). Add new folder "Config" contains background image and icon image. Functional buttons:
next image, replay word, set volume, quit. Buttons for quiz and for test are not programmed.

I’m thinking the best way to handle all the input would be to swap over to an ON TIMER event.  Then we can have an escape variable to stop the SDNPLAY loops and keep the program responsive at all times.  I’ll see about doing the swap over later tonight.  ;D
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 01, 2019, 05:44:14 pm
:) Well, it will be absolutely brutal. The ON timer easily jumps in the middle of the loop in the program, because all he cares about is the set time. When you look at the program at line 480, I re-declared the keyhit variable as desirable numeric output. Now I tried it directly and it's a little faster. I think the problem will be in the sounds, apparently there are long silent spots, so there is no empty buffer and therefore the delay. That's just an estimate.
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 02, 2019, 06:38:15 pm
The ON TIMER changes seem to be working as intended now.

At this point, we can now STOP the speech in the middle of a word ("cat" is a very good test word for stopping, as it's the only one which actually says the word itself and then repeats the spelling for you a second time), and we can now PLAY a word as many times as we want.

At this point, the next order of business is to actually build the REVIEW buttons (we already create the list of acceptable images which fit our search parameters), so we can set the number of times we want to review our words/images in a setting...

I picture this to be as simple as a setting with a value from 1 to 5 (a quick set of click buttons should quickly set the value), after which we generate a study list of Number of Pictures * Times to Review.

So let's say we have a list of 3 words which meet our match criteria:  "HAT, CAT, BAT"
And then we want to study them 2 times...

We just shuffle that list twice and put it into a new list:  "CAT, BAT, HAT, BAT, HAT, CAT"

This new list will be our "study list", and the LAST and NEXT buttons will give us manual control to move forward and backward in the list as we wish...



After the review list (and movement buttons) are added, all that's left is to create the TEST button so a child can then test themselves and see how well they do with the words when the images show up for them.

And after that... It's more or less a done product.  :D
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 05:12:59 am
This easy and very stupid code show, what i mean, if i say, that ON TIMER get out in middle in the loop:

Code: QB64: [Select]
  1. ON TIMER(1) GOSUB timerdone
  2.     FOR f = 1 TO 500000
  3.     NEXT f
  4.  
  5. timerdone: PRINT "For next loop value is:"; f
  6.  
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 03, 2019, 05:19:18 am
Code: QB64: [Select]
  1. $COLOR32
  2.  
  3. TYPE TagType
  4.     Year AS INTEGER
  5.     Week AS INTEGER
  6.     Theme AS STRING
  7.  
  8. SCREEN _NEWIMAGE(800, 600, 32)
  9. _TITLE "Spell It Aloud"
  10.  
  11. CONST ImageDir$ = ".\Images\"
  12. CONST SoundDir$ = ".\Alphabet Sounds\"
  13. CONST TagDir$ = ".\Image Tags\"
  14. CONST WordSoundDir$ = ".\Word Sounds\"
  15.  
  16. DIM SHARED PhotoTag AS TagType
  17. DIM SHARED LimitTag AS TagType
  18.  
  19. DIM SHARED AlphaSound(65 TO 90)
  20. REDIM SHARED PhotoList(100000) AS STRING
  21. DIM SHARED PhotoCount AS LONG
  22. DIM SHARED IsHowYouSpell AS LONG
  23. DIM SHARED ControlVariable1 AS LONG
  24. DIM SHARED ShowNext AS LONG
  25.  
  26.  
  27. 'load our fonts
  28. f = _LOADFONT("courbd.ttf", 84, "MONOSPACE")
  29. f1 = _LOADFONT("courbd.ttf", 48, "MONOSPACE")
  30.  
  31.  
  32. 'Load the alphabet sound library
  33. FOR i = 65 TO 90
  34.     temp$ = SoundDir$ + CHR$(i) + ".ogg"
  35.     AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  36. temp$ = WordSoundDir$ + "is how you spell.ogg"
  37. IsHowYouSpell = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  38.  
  39.  
  40. _DELAY 1 'Give everything a moment to initialize and get started for us.
  41. ChangeSearchTags
  42.  
  43. Timer1 = _FREETIMER
  44.  
  45. ON TIMER(Timer1, .05) UserInput
  46. TIMER(Timer1) ON
  47.  
  48.     IF ShowNext THEN
  49.         IF ShowNext = -1 THEN
  50.             PhotoCount = UBOUND(PhotoList)
  51.             SELECT CASE PhotoCount
  52.                 CASE 0: PhotoChosen = 0: oldpic = 0 'no matches
  53.                 CASE 1: PhotoChosen = 1: oldpic = 1 'Only one possible match
  54.                 CASE ELSE 'multiple photos match the search criteria
  55.                     DO UNTIL PhotoChosen <> oldpic
  56.                         PhotoChosen = INT(RND * PhotoCount) + 1
  57.                     LOOP
  58.                     oldpic = PhotoChosen
  59.             END SELECT
  60.         END IF
  61.  
  62.         playagain:
  63.         IF PhotoChosen THEN
  64.             fullpath$ = PhotoList(PhotoChosen)
  65.             word$ = MID$(fullpath$, _INSTRREV(fullpath$, "\") + 1)
  66.             word$ = LEFT$(word$, INSTR(word$, ".") - 1)
  67.  
  68.             IF tempimage <> 0 THEN _FREEIMAGE tempimage 'free the old image
  69.             tempimage = _LOADIMAGE(PhotoList(PhotoChosen), 32) 'get the new image
  70.  
  71.             CLS
  72.             _FONT f1: CenterText 0, 0, 800, 50, "Spell It Aloud": _FONT f
  73.  
  74.             'program photo area is 500 x 450 pixels. So:
  75.             GetNewWH 500, 450, tempimage, nW, nH
  76.             _PUTIMAGE (300 - (nW / 2), 300 - (nH / 2) - 25)-STEP(nW, nH), tempimage
  77.  
  78.             LoadPhotoTags word$
  79.             DisplayTags 575, 150, "Search Tags (" + _TRIM$(STR$(PhotoCount)) + ")", LimitTag
  80.             DisplayTags 575, 300, "Photo Tags", PhotoTag
  81.             PlayLetters word$
  82.         ELSE
  83.             DrawNoMatches
  84.         END IF
  85.         IF oldpic = PhotoChosen THEN ShowNext = 0
  86.         IF ShowNext = -2 THEN ShowNext = 0: GOTO playagain
  87.     END IF
  88.     _LIMIT 10
  89.  
  90. SUB UserInput
  91.     STATIC oldmouse
  92.     MB = 0
  93.         IF _MOUSEBUTTON(1) THEN MB = -1: EXIT WHILE
  94.     WEND
  95.     Mx = _MOUSEX: My = _MOUSEY
  96.     IF oldmouse = 0 AND MB THEN 'it's a click
  97.         IF Mx >= 650 AND Mx <= 750 THEN 'the mouse is in the correct X area for input
  98.             SELECT CASE My
  99.                 CASE 171 TO 190
  100.                     temp$ = ChangeValue(650, 171, STR$(LimitTag.Year), -1)
  101.                     LimitTag.Year = VAL(temp$)
  102.                     ChangeSearchTags
  103.                 CASE 191 TO 210
  104.                     temp$ = ChangeValue(650, 191, STR$(LimitTag.Week), -1)
  105.                     LimitTag.Week = VAL(temp$)
  106.                     ChangeSearchTags
  107.                 CASE 211 TO 230
  108.                     temp$ = ChangeValue(650, 211, LimitTag.Sound, 0)
  109.                     LimitTag.Sound = temp$
  110.                     ChangeSearchTags
  111.                 CASE 231 TO 250
  112.                     temp$ = ChangeValue(650, 231, LimitTag.Theme, 0)
  113.                     LimitTag.Theme = temp$
  114.                     ChangeSearchTags
  115.                 CASE 324 TO 340
  116.                     PhotoTag.Year = VAL(ChangeValue(650, 324, STR$(PhotoTag.Year), -1))
  117.                     ChangePhotoTags word$
  118.                 CASE 341 TO 360
  119.                     PhotoTag.Week = VAL(ChangeValue(650, 341, STR$(PhotoTag.Week), -1))
  120.                     ChangePhotoTags word$
  121.                 CASE 361 TO 380
  122.                     PhotoTag.Sound = ChangeValue(650, 361, PhotoTag.Sound, 0)
  123.                     ChangePhotoTags word$
  124.                 CASE 381 TO 400
  125.                     PhotoTag.Theme = ChangeValue(650, 381, PhotoTag.Theme, 0)
  126.                     ChangePhotoTags word$
  127.             END SELECT
  128.         END IF
  129.         IF _MOUSEY > 450 AND _MOUSEY < 470 THEN 'it's the right Y pos for the top control buttons
  130.             SELECT CASE _MOUSEX
  131.                 CASE 575 TO 640 'Last
  132.                 CASE 641 TO 705 'Play
  133.                     ShowNext = -2
  134.                 CASE 706 TO 770 'Next
  135.                     ShowNext = -1
  136.             END SELECT
  137.         ELSEIF _MOUSEY > 471 AND _MOUSEY < 491 THEN 'it's the right Y pos for the top control buttons
  138.             SELECT CASE _MOUSEX
  139.                 CASE 575 TO 640 'Vol
  140.                 CASE 641 TO 705 'Stop
  141.                     ControlVariable1 = -1 'Stop Command for playing the word
  142.                 CASE 706 TO 770 'Quit
  143.                     SYSTEM
  144.             END SELECT
  145.         END IF
  146.     END IF
  147.  
  148.  
  149.     IF MB THEN oldmouse = -1 ELSE oldmouse = 0
  150.     ControlVariable = 0
  151.  
  152.  
  153.     k = _KEYHIT
  154.     SELECT CASE k
  155.         CASE 32 'space for next picture
  156.             ShowNext = -1
  157.         CASE 27 'escape
  158.             SYSTEM 'quit
  159.     END SELECT
  160.     DrawCommandBoxes
  161.  
  162. SUB DrawCommandBoxes
  163.     s = SaveState
  164.     _FONT 16
  165.     COLOR Black, 0
  166.     BoxTitle 575, 450, 640, 470, 2, BlueGray, Gold, "LAST"
  167.     BoxTitle 641, 450, 705, 470, 2, BlueGray, Gold, "PLAY"
  168.     BoxTitle 706, 450, 770, 470, 2, BlueGray, Gold, "NEXT"
  169.     BoxTitle 575, 471, 640, 490, 2, BlueGray, Gold, "VOL"
  170.     COLOR Maroon
  171.     BoxTitle 641, 471, 705, 490, 2, BlueGray, Gold, "STOP"
  172.     COLOR Yellow
  173.     BoxTitle 706, 471, 770, 490, 2, BlueGray, Gold, "QUIT"
  174.  
  175.     RestoreState s
  176.  
  177. SUB BoxTitle (x1, y1, x2, y2, thick, fg AS _UNSIGNED LONG, bg AS _UNSIGNED LONG, title$)
  178.     Box x1, y1, x2 - x1 + 1, y2 - y1 + 1, thick, fg, bg
  179.     CenterText x1, y1 + thick, x2, y2 + thick, title$
  180.  
  181. SUB DrawNoMatches
  182.     S = SaveState
  183.     CLS
  184.     _FONT f1
  185.     Box 50, 50, 500, 500, 5, Silver, Gold
  186.     CenterText 0, 0, 800, 50, "Spell It Aloud"
  187.     FOR i = 1 TO 10 STEP .5
  188.         CIRCLE (300, 300), 200 - i, BrickRed
  189.         LINE (300 + SIN(_D2R(-45)) * 198 + i, 300 + COS(_D2R(-45)) * 198 + i)-(300 + SIN(_D2R(135)) * 198 + i, 300 + COS(_D2R(135)) * 198 + i), BrickRed
  190.     NEXT
  191.     COLOR Yellow, 0
  192.     CenterText 50, 50, 550, 550, "No Matches"
  193.     PhotoTag.Year = 0
  194.     PhotoTag.Week = 0
  195.     PhotoTag.Sound = ""
  196.     PhotoTag.Theme = ""
  197.     RestoreState S
  198.     DisplayTags 575, 150, "Search Tags (" + _TRIM$(STR$(PhotoCount)) + ")", LimitTag
  199.     DisplayTags 575, 300, "Photo Tags", PhotoTag
  200.     ShowNext = -1
  201.  
  202.  
  203.  
  204. SUB PlayLetters (word$)
  205.     'Put the letters to the screen one by one
  206.     ControlVariable1 = 0
  207.     pw = _PRINTWIDTH(word$): StartX = (600 - pw) \ 2 'center position
  208.  
  209.     FOR i = 1 TO LEN(word$)
  210.         a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
  211.         _PRINTSTRING (StartX + (i - 1) * _FONTWIDTH, 510), CHR$(a)
  212.         IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
  213.         _SNDPLAY AlphaSound(a)
  214.         WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
  215.             _LIMIT 10 'play nice with CPU during wait
  216.             IF ControlVariable1 THEN _SNDSTOP (AlphaSound(a))
  217.         WEND
  218.     NEXT
  219.     IF ContolVariable1 = 0 THEN
  220.         temp$ = WordSoundDir$ + word$ + ".ogg"
  221.         IF _FILEEXISTS(temp$) THEN
  222.             _SNDVOL IsHowYouSpell, .5
  223.             _SNDPLAY IsHowYouSpell
  224.             WHILE _SNDPLAYING(IsHowYouSpell) 'wait for sound to finish before playing again
  225.                 _LIMIT 10 'play nice with CPU during wait
  226.                 IF ControlVariable1 THEN _SNDSTOP (IsHowYouSpell)
  227.             WEND
  228.  
  229.             temp = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  230.             _SNDPLAY temp
  231.             WHILE _SNDPLAYING(temp) 'wait for sound to finish before playing again
  232.                 _LIMIT 10 'play nice with CPU during wait
  233.                 IF ControlVariable1 THEN _SNDSTOP (temp)
  234.             WEND
  235.             _SNDCLOSE temp
  236.             _DELAY 1
  237.  
  238.             FOR i = 1 TO LEN(word$)
  239.                 a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
  240.                 _PRINTSTRING (StartX + (i - 1) * _FONTWIDTH, 510), CHR$(a)
  241.                 IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
  242.                 _SNDPLAY AlphaSound(a)
  243.                 WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
  244.                     _LIMIT 10 'play nice with CPU during wait
  245.                     IF ControlVariable1 THEN _SNDSTOP (AlphaSound(a))
  246.                 WEND
  247.             NEXT
  248.         END IF
  249.     END IF
  250.  
  251.  
  252. SUB ChangePhotoTags (word$)
  253.     'Get a listing of the files
  254.     file$ = TagDir$ + word$ + ".txt"
  255.     OPEN file$ FOR OUTPUT AS #1
  256.     PRINT #1, PhotoTag.Year
  257.     PRINT #1, PhotoTag.Week
  258.     PRINT #1, PhotoTag.Sound
  259.     PRINT #1, PhotoTag.Theme
  260.     CLOSE
  261.  
  262. SUB LoadPhotoTags (word$)
  263.     file$ = TagDir$ + word$ + ".txt"
  264.     IF _FILEEXISTS(file$) THEN
  265.         OPEN file$ FOR INPUT AS #1
  266.         INPUT #1, PhotoTag.Year
  267.         INPUT #1, PhotoTag.Week
  268.         INPUT #1, PhotoTag.Sound
  269.         INPUT #1, PhotoTag.Theme
  270.         CLOSE
  271.     ELSE
  272.         PhotoTag.Year = 0
  273.         PhotoTag.Week = 0
  274.         PhotoTag.Sound = ""
  275.         PhotoTag.Theme = ""
  276.         IF word$ <> "" THEN ChangePhotoTags word$
  277.     END IF
  278.  
  279.  
  280. SUB ChangeSearchTags
  281.     TIMER(Timer1) OFF
  282.     'Get a listing of the files
  283.     PhotoList$ = ImageDir$ + "*.bmp " + ImageDir$ + "*.jpg " + ImageDir$ + "*.png " + ImageDir$ + "*.gif "
  284.     SHELL _HIDE "DIR " + PhotoList$ + "/b /s /a-d >PhotoList.txt"
  285.  
  286.     REDIM _PRESERVE PhotoList(100000)
  287.     'Load those names into a file.
  288.     OPEN "Photolist.txt" FOR BINARY AS #1
  289.     PhotoCount = 0
  290.     DO UNTIL EOF(1)
  291.         LINE INPUT #1, fullpath$
  292.         word$ = MID$(fullpath$, _INSTRREV(fullpath$, "\") + 1)
  293.         word$ = LEFT$(word$, INSTR(word$, ".") - 1)
  294.  
  295.         file$ = TagDir$ + word$ + ".txt"
  296.         IF _FILEEXISTS(file$) THEN
  297.             OPEN file$ FOR INPUT AS #2
  298.             INPUT #2, PhotoTag.Year
  299.             INPUT #2, PhotoTag.Week
  300.             INPUT #2, PhotoTag.Sound
  301.             INPUT #2, PhotoTag.Theme
  302.         ELSE
  303.             OPEN file$ FOR OUTPUT AS #2
  304.             PRINT #2, 0
  305.             PRINT #2, 0
  306.             PRINT #2, ""
  307.             PRINT #2, ""
  308.         END IF
  309.         CLOSE #2
  310.         good = -1
  311.         IF LimitTag.Year <> 0 AND LimitTag.Year <> PhotoTag.Year THEN good = 0
  312.         IF LimitTag.Week <> 0 AND LimitTag.Week <> PhotoTag.Week THEN good = 0
  313.  
  314.         IF LimitTag.Sound <> "" AND LimitTag.Sound <> PhotoTag.Sound THEN good = 0
  315.         IF LimitTag.Theme <> "" AND LimitTag.Theme <> PhotoTag.Theme THEN good = 0
  316.         IF good THEN
  317.             PhotoCount = PhotoCount + 1
  318.             PhotoList(PhotoCount) = fullpath$
  319.         END IF
  320.     LOOP
  321.     REDIM _PRESERVE PhotoList(PhotoCount)
  322.     CLOSE
  323.     ShowNext = -1
  324.  
  325.  
  326. FUNCTION ChangeValue$ (x, y, word$, limit)
  327.     TIMER(Timer1) OFF
  328.     S = SaveState
  329.     _FONT 16
  330.     temp$ = CHR$(179)
  331.     _KEYCLEAR
  332.     DO
  333.         Box x, y, 100, 20, 1, Black, Gold
  334.         CenterText x, y, x + 100, y + 20, temp$
  335.         k = _KEYHIT
  336.         SELECT CASE k
  337.             CASE 8
  338.                 word$ = LEFT$(word$, LEN(word$) - 1)
  339.             CASE 13
  340.                 EXIT DO
  341.             CASE 48 TO 57 'We'll always accept numeric input
  342.                 word$ = word$ + CHR$(k)
  343.             CASE 65 TO 90, 97 TO 122 'A-Z (a-z) only when we're dealing with a string
  344.                 IF NOT limit THEN word$ = word$ + CHR$(k)
  345.         END SELECT
  346.         temp$ = word$ + CHR$(179)
  347.         _LIMIT 10
  348.     LOOP
  349.     ChangeValue$ = word$
  350.     RestoreState S
  351.     DisplayTags 575, 150, "Search Tags (" + _TRIM$(STR$(PhotoCount)) + ")", LimitTag
  352.     DisplayTags 575, 300, "Photo Tags", PhotoTag
  353.  
  354.     TIMER(Timer1) ON
  355.  
  356. SUB DisplayTags (x, y, Title AS STRING, DisplayTag AS TagType)
  357.     S = SaveState
  358.     _FONT 16
  359.     w = 200: h = 106
  360.     Box x, y, w, h, 2, BlueGray, Gold
  361.     COLOR Gold, 0
  362.     CenterText x, y + 2, x + 200, y + 20, Title
  363.     LINE (x + 1, y + 19)-STEP(w - 2, 0), Gold
  364.     COLOR White, 0
  365.     xs = x + 24: ys = y + 24 'x/y start after the box offset
  366.     _PRINTSTRING (xs, ys), "Year :"
  367.     _PRINTSTRING (xs, ys + 20), "Week :"
  368.     _PRINTSTRING (xs, ys + 40), "Sound:"
  369.     _PRINTSTRING (xs, ys + 60), "Theme:"
  370.     bxs = xs + 50: bys = ys - 2 'x/y start for the display boxes
  371.     FOR i = 0 TO 3
  372.         Box bxs, bys + i * 20, 100, 20, 1, Black, Gold
  373.     NEXT
  374.     CenterValue bxs, bys, bxs + 100, bys + 20, DisplayTag.Year
  375.     CenterValue bxs, bys + 20, bxs + 100, bys + 40, DisplayTag.Week
  376.     CenterText bxs, bys + 40, bxs + 100, bys + 60, DisplayTag.Sound
  377.     CenterText bxs, bys + 60, bxs + 100, bys + 80, DisplayTag.Theme
  378.     RestoreState S
  379.  
  380. SUB Box (x, y, wide, high, thick, Kolor AS _UNSIGNED LONG, Trim AS _UNSIGNED LONG)
  381.     LINE (x, y)-STEP(wide, high), Kolor, BF
  382.     FOR i = 0 TO thick - 1
  383.         LINE (x + i, y + i)-STEP(wide - 2 * i, high - 2 * i), Trim, B
  384.     NEXT
  385.  
  386.  
  387. SUB CenterText (x1, y1, x2, y2, text$)
  388.     text$ = _TRIM$(text$)
  389.     xmax = x2 - x1: ymax = y2 - y1
  390.     textlength = _PRINTWIDTH(text$)
  391.     xpos = (xmax - textlength) / 2
  392.     ypos = (ymax - _FONTHEIGHT) / 2
  393.     _PRINTSTRING (x1 + xpos, y1 + ypos), text$
  394.  
  395. SUB CenterValue (x1, y1, x2, y2, value AS LONG)
  396.     text$ = _TRIM$(STR$(value))
  397.     CenterText x1, y1, x2, y2, text$
  398.  
  399. FUNCTION SaveState
  400.     TYPE SaveStateType
  401.         InUse AS INTEGER
  402.         DC AS INTEGER
  403.         BG AS INTEGER
  404.         F AS INTEGER
  405.         D AS INTEGER
  406.         S AS INTEGER
  407.         Disp AS INTEGER
  408.         CurX AS INTEGER
  409.         CurY AS INTEGER
  410.     END TYPE
  411.     DIM SS AS SaveStateType, Temp AS SaveStateType
  412.     SHARED NSS AS LONG 'Number of Saved States
  413.     SHARED SaveMem AS _MEM
  414.     IF NOT _MEMEXISTS(SaveMem) THEN
  415.         SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
  416.         $CHECKING:OFF
  417.         _MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
  418.         $CHECKING:ON
  419.     END IF
  420.  
  421.     'Data to Save
  422.     SS.InUse = -1
  423.     SS.F = _FONT
  424.     SS.DC = _DEFAULTCOLOR
  425.     SS.BG = _BACKGROUNDCOLOR
  426.     SS.D = _DEST
  427.     SS.S = _SOURCE
  428.     SS.Disp = _AUTODISPLAY
  429.     SS.CurX = POS(0)
  430.     SS.CurY = CSRLIN
  431.     FOR i = 1 TO NSS
  432.         o = (i - 1) * LEN(SS)
  433.         _MEMGET SaveMem, SaveMem.OFFSET + o, Temp
  434.         IF Temp.InUse = 0 THEN
  435.             _MEMPUT SaveMem, SaveMem.OFFSET + o, SS
  436.             SaveState = i
  437.             EXIT FUNCTION
  438.         END IF
  439.     NEXT
  440.     _MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
  441.     NSS = NSS + 1
  442.     SaveState = NSS
  443.  
  444. SUB RestoreState (WhichOne AS LONG)
  445.     DIM SS AS SaveStateType
  446.     SHARED NSS AS LONG 'Number of Saved States
  447.     SHARED SaveMem AS _MEM
  448.     _MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  449.     IF SS.InUse THEN
  450.         SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
  451.         $CHECKING:OFF
  452.         _MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  453.         $CHECKING:ON
  454.         _FONT SS.F
  455.         COLOR SS.DC, SS.BG
  456.         _DEST SS.D
  457.         _SOURCE SS.S
  458.         IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
  459.         LOCATE SS.CurY, SS.CurX
  460.     END IF
  461.  
  462. SUB GetNewWH (destWidth, destHeight, handle AS LONG, NewWidth, NewHeight) 'Sub return in variables NewWidth and NewHeight new image Width and image Height with the same ratio for optimal picture to set area width and height with [destWidth, destHeight]
  463.     W = _WIDTH(handle)
  464.     H = _HEIGHT(handle)
  465.     Pw = W / destWidth
  466.     Ph = H / destHeight
  467.     IF W > H THEN P = Pw ELSE P = Ph
  468.     NewWidth = W / P
  469.     NewHeight = H / P
  470.  

Sorry!  I apparently forgot to post the code block earlier.  /blush
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 05:26:00 am
By chance, Steve, thank you, now I know I'm not alone who forgets! :)
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 03, 2019, 05:35:34 am
This easy and very stupid code show, what i mean, if i say, that ON TIMER get out in middle in the loop:

Code: QB64: [Select]
  1. ON TIMER(1) GOSUB timerdone
  2.     FOR f = 1 TO 500000
  3.     NEXT f
  4.  
  5. timerdone: PRINT "For next loop value is:"; f
  6.  

Sometimes, you want to be able to pop in and out of the middle of a loop.

Code: [Select]
DIM f AS LONG
ON TIMER(.1) GOSUB timerdone
TIMER ON
DO
    c = (c + 1) MOD 16
    COLOR c
    PRINT "COLOR "; c,
    _LIMIT 10 'no need to use a lot of CPU; we're going to handle things VIA the timed routine
LOOP

timerdone:
IF NOT paused THEN
    f = f + 1
    PRINT "For next loop value is:"; f
END IF
k = _KEYHIT
IF k = 32 THEN GOSUB pausetimer

RETURN

pausetimer:
paused = NOT paused
RETURN

The above is a very simple demo of how things might interact so that we do one thing (the main process), while still using ON TIMER as a means to handle control of other processes.

In the Spell It code I posted above, the SUB UserInput reads mouse/keystrokes via an ON TIMER routine, and by utilizing its ability to jump out of the middle of loops/subs, we can use it as a ready means to set control flags so we can stop the sound playing at any point in the process.

Code: [Select]
        _SNDPLAY AlphaSound(a)
        WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
            _LIMIT 10 'play nice with CPU during wait
            IF ControlVariable1 THEN _SNDSTOP (AlphaSound(a))
        WEND

ControlVariable1 can be set in the ON TIMER routine, and when set, we stop the sound and simply wait for the next process to be initiated by the user.  (play, next, quit, ect...)
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 05:51:45 am
 Steve.... i am very curious. How is this possible?

I am on the end in your source code in new compiled IDE with support for your new metacommand $color and give this screen.... Line 579 not exists, maximal row value in source code is 501...



if i comment your new metacommand, i find next bug - you use none LOF(1) control in SUB ChangeSearchTags, so, if is user idiot, so as me, and copy your Spell source code to new installation dir without needed subdirectories, so it generate Input past end of file on row 309 :)


image with your source code so, as it, with missing subdirectories for Spell program:

 
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 05:55:21 am
Thank you for your ON Timer example!
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 03, 2019, 06:08:18 am
Steve.... i am very curious. How is this possible?

It's actually a glitch which I didn't notice in the last BAS file I posted earlier.

If you open QB64.bas (which you downloaded from earlier), do a quick search for $COLOR32.  At line 2981, you'll see where there's:

Code: [Select]
        IF a3u$ = "$COLOR32" THEN
            ColorHack = -1

This is where QB64 is now parsing the metacommand for $COLOR32.  What it's doing is very simple -- it's actually just injecting those lines into your code (much like a native $INCLUDE statement would), and adding them to your available CONST list...

The glitch is rather simple:  I didn't bother to parse those statements and add the values manually to the CONST list (it's a bunch of different TYPE values which we use to track them), since QB64 already parses and deals with them for us, as it reads our code.  The glitch is that each time it processes them, it adds to the linecount for them -- all 200+ times!

Fix is really simple:

Add a line for:             oldlinenumber = linenumber to the start of that IF block, and then             linenumber = oldlinenumber to the end of that IF block (right before the GOTO which continues processing the rest of our code.

So that error you're getting isn't past the end of the file; your internal line counter is just off, until that one little glitch is corrected.

(There's always something simple like this, which is overlooked when making changes, which is why we have a development build for people to test these things, and a stable build so they don't have to worry about them.)  ;D
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 06:27:48 am
So rewrited, QB64 recompiled, re-tested and now it is ok. Please add to your Speel program to row 307 something as this:

Code: QB64: [Select]
  1.   IF LOF(1) = 0 THEN PRINT "Missing program directories!": SLEEP 3: SYSTEM
  2.  


We are going to have lunch, I will work with it again later.
Title: Re: Spell It Aloud (Help Requested)
Post by: FellippeHeitor on August 03, 2019, 09:41:23 am
It's actually a glitch which I didn't notice in the last BAS file I posted earlier.

If you open QB64.bas (which you downloaded from earlier), do a quick search for $COLOR32.  At line 2981, you'll see where there's:

Code: [Select]
        IF a3u$ = "$COLOR32" THEN
            ColorHack = -1

This is where QB64 is now parsing the metacommand for $COLOR32.  What it's doing is very simple -- it's actually just injecting those lines into your code (much like a native $INCLUDE statement would), and adding them to your available CONST list...

The glitch is rather simple:  I didn't bother to parse those statements and add the values manually to the CONST list (it's a bunch of different TYPE values which we use to track them), since QB64 already parses and deals with them for us, as it reads our code.  The glitch is that each time it processes them, it adds to the linecount for them -- all 200+ times!

Fix is really simple:

Add a line for:             oldlinenumber = linenumber to the start of that IF block, and then             linenumber = oldlinenumber to the end of that IF block (right before the GOTO which continues processing the rest of our code.

So that error you're getting isn't past the end of the file; your internal line counter is just off, until that one little glitch is corrected.

(There's always something simple like this, which is overlooked when making changes, which is why we have a development build for people to test these things, and a stable build so they don't have to worry about them.)  ;D

Might also be a good idea to only inject the CONST declarations if ColorHack = 0.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 10:24:06 am
Steve, this is another suggestion to change your function so that the input can be end by next click anywhere you want. (so you can not using enter only)

Code: QB64: [Select]
  1. FUNCTION ChangeValue$ (x, y, word$, limit)
  2.     TIMER(Timer1) OFF
  3.     S = SaveState
  4.     _FONT 16
  5.     temp$ = CHR$(179)
  6.     _KEYCLEAR
  7.     DO UNTIL state = 2
  8.         Box x, y, 100, 20, 1, Black, Gold
  9.         CenterText x, y, x + 100, y + 20, temp$
  10.         WHILE _MOUSEINPUT: WEND
  11.         IF _MOUSEBUTTON(1) THEN
  12.             state = state + 1
  13.             DO UNTIL _MOUSEBUTTON(1) = 0
  14.                 WHILE _MOUSEINPUT: WEND
  15.             LOOP
  16.         END IF
  17.  
  18.         k = _KEYHIT
  19.         SELECT CASE k
  20.             CASE 8
  21.                 word$ = LEFT$(word$, LEN(word$) - 1)
  22.             CASE 13
  23.                 EXIT DO
  24.             CASE 48 TO 57 'We'll always accept numeric input
  25.                 word$ = word$ + CHR$(k)
  26.             CASE 65 TO 90, 97 TO 122 'A-Z (a-z) only when we're dealing with a string
  27.                 IF NOT limit THEN word$ = word$ + CHR$(k)
  28.         END SELECT
  29.         temp$ = word$ + CHR$(179)
  30.         _LIMIT 10
  31.     LOOP
  32.     ChangeValue$ = word$
  33.     RestoreState S
  34.     DisplayTags 575, 150, "Search Tags (" + _TRIM$(STR$(PhotoCount)) + ")", LimitTag
  35.     DisplayTags 575, 300, "Photo Tags", PhotoTag
  36.  
  37.     TIMER(Timer1) ON
  38.  

I must upgrading my version in own way, because in your new source is too many news.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 03, 2019, 11:16:05 am
Steve, I removed DELAY 1 on SUB PlayLetters and added mouse input control  when is playback, and I have the same speed  without TIMER. Is the intention that the first and third blocks in PlayLetters for playback are the same?
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 04, 2019, 01:06:51 am
Here's a different version for you, Petr, without the ON TIMER routines to handle input:

Code: QB64: [Select]
  1. $COLOR32
  2.  
  3. TYPE TagType
  4.     Year AS INTEGER
  5.     Week AS INTEGER
  6.     Theme AS STRING
  7.  
  8. SCREEN _NEWIMAGE(800, 600, 32)
  9. _TITLE "Spell It Aloud"
  10.  
  11. CONST ImageDir$ = ".\Images\"
  12. CONST SoundDir$ = ".\Alphabet Sounds\"
  13. CONST TagDir$ = ".\Image Tags\"
  14. CONST WordSoundDir$ = ".\Word Sounds\"
  15.  
  16. DIM SHARED PhotoTag AS TagType
  17. DIM SHARED LimitTag AS TagType
  18.  
  19. DIM SHARED AlphaSound(65 TO 90)
  20. REDIM SHARED PhotoList(100000) AS STRING
  21. REDIM SHARED WordList(0) AS LONG
  22. DIM SHARED PhotoCount AS LONG
  23. DIM SHARED PhotoChosen AS LONG
  24. DIM SHARED IsHowYouSpell AS LONG
  25. DIM SHARED ControlVariable1 AS LONG
  26. DIM SHARED ShowNext AS LONG
  27.  
  28.  
  29. 'load our fonts
  30. f = _LOADFONT("courbd.ttf", 84, "MONOSPACE")
  31. f1 = _LOADFONT("courbd.ttf", 48, "MONOSPACE")
  32.  
  33.  
  34. 'Load the alphabet sound library
  35. FOR i = 65 TO 90
  36.     temp$ = SoundDir$ + CHR$(i) + ".ogg"
  37.     AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  38. temp$ = WordSoundDir$ + "is how you spell.ogg"
  39. IsHowYouSpell = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  40.  
  41.  
  42. _DELAY 1 'Give everything a moment to initialize and get started for us.
  43. WordList(0) = 3 'three times repeating the list, as default
  44. ChangeSearchTags
  45. ShowNext = -1
  46.  
  47.     ControlVariable = 0
  48.     MB = mouseclick
  49.     Mx = _MOUSEX: My = _MOUSEY
  50.     IF MB THEN
  51.         IF Mx >= 650 AND Mx <= 750 THEN 'the mouse is in the correct X area for input
  52.             SELECT CASE My
  53.                 CASE 171 TO 190
  54.                     temp$ = ChangeValue(650, 171, STR$(LimitTag.Year), -1)
  55.                     LimitTag.Year = VAL(temp$)
  56.                     ChangeSearchTags
  57.                     ShowNext = -1
  58.                 CASE 191 TO 210
  59.                     temp$ = ChangeValue(650, 191, STR$(LimitTag.Week), -1)
  60.                     LimitTag.Week = VAL(temp$)
  61.                     ChangeSearchTags
  62.                     ShowNext = -1
  63.                 CASE 211 TO 230
  64.                     temp$ = ChangeValue(650, 211, LimitTag.Sound, 0)
  65.                     LimitTag.Sound = temp$
  66.                     ChangeSearchTags
  67.                     ShowNext = -1
  68.                 CASE 231 TO 250
  69.                     temp$ = ChangeValue(650, 231, LimitTag.Theme, 0)
  70.                     LimitTag.Theme = temp$
  71.                     ChangeSearchTags
  72.                     ShowNext = -1
  73.                 CASE 324 TO 340
  74.                     PhotoTag.Year = VAL(ChangeValue(650, 324, STR$(PhotoTag.Year), -1))
  75.                     ChangePhotoTags word$
  76.                     ShowNext = -1: ControlVariable1 = -1
  77.                 CASE 341 TO 360
  78.                     PhotoTag.Week = VAL(ChangeValue(650, 341, STR$(PhotoTag.Week), -1))
  79.                     ChangePhotoTags word$
  80.                     ShowNext = -1: ControlVariable1 = -1
  81.                 CASE 361 TO 380
  82.                     PhotoTag.Sound = ChangeValue(650, 361, PhotoTag.Sound, 0)
  83.                     ChangePhotoTags word$
  84.                     ShowNext = -1: ControlVariable1 = -1
  85.                 CASE 381 TO 400
  86.                     PhotoTag.Theme = ChangeValue(650, 381, PhotoTag.Theme, 0)
  87.                     ChangePhotoTags word$
  88.                     ShowNext = -1: ControlVariable1 = -1
  89.             END SELECT
  90.         END IF
  91.         IF _MOUSEY > 450 AND _MOUSEY < 470 THEN 'it's the right Y pos for the top control buttons
  92.             SELECT CASE _MOUSEX
  93.                 CASE 575 TO 640 'Last
  94.                     PhotoChosen = PhotoChosen - 1
  95.                     IF PhotoChosen < 1 THEN PhotoChosen = UBOUND(WordList)
  96.                     ShowNext = -1
  97.                 CASE 641 TO 705 'Play
  98.                     ShowNext = -1
  99.                 CASE 706 TO 770 'Next
  100.                     PhotoChosen = PhotoChosen + 1
  101.                     IF PhotoChosen > UBOUND(WordList) THEN PhotoChosen = 1
  102.                     ShowNext = -1
  103.             END SELECT
  104.         ELSEIF _MOUSEY > 471 AND _MOUSEY < 491 THEN 'it's the right Y pos for the 2nd row of control buttons
  105.             SELECT CASE _MOUSEX
  106.                 CASE 575 TO 640 'Vol not yet implemented
  107.                 CASE 641 TO 705 'Stop now handled via the sound sub
  108.                 CASE 706 TO 770: SYSTEM 'Quit
  109.             END SELECT
  110.         END IF
  111.     END IF
  112.  
  113.     k = _KEYHIT
  114.     SELECT CASE k
  115.         CASE 32 'space for next picture
  116.             PhotoChosen = PhotoChosen + 1
  117.             IF PhotoChosen > WordList(0) THEN PhotoChosen = 1
  118.             ShowNext = -1
  119.         CASE 27 'escape
  120.             SYSTEM 'quit
  121.     END SELECT
  122.  
  123.     IF ShowNext THEN
  124.         ShowNext = 0
  125.         IF PhotoChosen THEN
  126.             temp$ = PhotoList(WordList(PhotoChosen))
  127.             word$ = MID$(temp$, _INSTRREV(temp$, "\") + 1)
  128.             word$ = LEFT$(word$, INSTR(word$, ".") - 1)
  129.  
  130.             IF tempimage <> 0 THEN _FREEIMAGE tempimage 'free the old image
  131.             tempimage = _LOADIMAGE(temp$, 32) 'get the new image
  132.  
  133.             CLS
  134.             _FONT f1: CenterText 0, 0, 800, 50, "Spell It Aloud": _FONT f
  135.  
  136.             'program photo area is 500 x 450 pixels. So:
  137.             GetNewWH 500, 450, tempimage, nW, nH
  138.             _PUTIMAGE (300 - (nW / 2), 300 - (nH / 2) - 25)-STEP(nW, nH), tempimage
  139.  
  140.             LoadPhotoTags word$
  141.             temp$ = "Search Tags (" + _TRIM$(STR$(PhotoChosen)) + " of " + _TRIM$(STR$(UBOUND(WordList))) + ")"
  142.             DisplayTags 575, 150, temp$, LimitTag
  143.             DisplayTags 575, 300, "Photo Tags", PhotoTag
  144.             DrawCommandBoxes
  145.             IF ControlVariable1 = 0 THEN PlayLetters word$
  146.         ELSE
  147.             DrawNoMatches
  148.         END IF
  149.         ControlVariable1 = 0
  150.     END IF
  151.     _LIMIT 10
  152.     _DISPLAY
  153.  
  154. SUB DrawCommandBoxes
  155.     s = SaveState
  156.     _FONT 16
  157.     COLOR Black, 0
  158.     BoxTitle 575, 450, 640, 470, 2, BlueGray, Gold, "LAST"
  159.     BoxTitle 641, 450, 705, 470, 2, BlueGray, Gold, "PLAY"
  160.     BoxTitle 706, 450, 770, 470, 2, BlueGray, Gold, "NEXT"
  161.     BoxTitle 575, 471, 640, 490, 2, BlueGray, Gold, "VOL"
  162.     COLOR Maroon
  163.     BoxTitle 641, 471, 705, 490, 2, BlueGray, Gold, "STOP"
  164.     COLOR Yellow
  165.     BoxTitle 706, 471, 770, 490, 2, BlueGray, Gold, "QUIT"
  166.  
  167.     RestoreState s
  168.  
  169. SUB BoxTitle (x1, y1, x2, y2, thick, fg AS _UNSIGNED LONG, bg AS _UNSIGNED LONG, title$)
  170.     Box x1, y1, x2 - x1 + 1, y2 - y1 + 1, thick, fg, bg
  171.     CenterText x1, y1 + thick, x2, y2 + thick, title$
  172.  
  173. SUB DrawNoMatches
  174.     S = SaveState
  175.     CLS
  176.     _FONT f1
  177.     Box 50, 50, 500, 500, 5, Silver, Gold
  178.     CenterText 0, 0, 800, 50, "Spell It Aloud"
  179.     FOR i = 1 TO 10 STEP .5
  180.         CIRCLE (300, 300), 200 - i, BrickRed
  181.         LINE (300 + SIN(_D2R(-45)) * 198 + i, 300 + COS(_D2R(-45)) * 198 + i)-(300 + SIN(_D2R(135)) * 198 + i, 300 + COS(_D2R(135)) * 198 + i), BrickRed
  182.     NEXT
  183.     COLOR Yellow, 0
  184.     CenterText 50, 50, 550, 550, "No Matches"
  185.     PhotoTag.Year = 0
  186.     PhotoTag.Week = 0
  187.     PhotoTag.Sound = ""
  188.     PhotoTag.Theme = ""
  189.     DisplayTags 575, 150, "Search Tags (0)", LimitTag
  190.     DisplayTags 575, 300, "Photo Tags", PhotoTag
  191.     RestoreState S
  192.  
  193.  
  194.  
  195. SUB PlayLetters (word$)
  196.     'Put the letters to the screen one by one
  197.     ControlVariable1 = 0
  198.     pw = _PRINTWIDTH(word$): StartX = (600 - pw) \ 2 'center position
  199.  
  200.     FOR i = 1 TO LEN(word$)
  201.         a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
  202.         _PRINTSTRING (StartX + (i - 1) * _FONTWIDTH, 510), CHR$(a)
  203.         _DISPLAY
  204.         IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
  205.         _SNDPLAY AlphaSound(a)
  206.         WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
  207.             _LIMIT 10 'play nice with CPU during wait
  208.             GOSUB checkstop
  209.             IF ControlVariable1 THEN _SNDSTOP (AlphaSound(a))
  210.         WEND
  211.     NEXT
  212.     IF ContolVariable1 = 0 THEN
  213.         temp$ = WordSoundDir$ + word$ + ".ogg"
  214.         IF _FILEEXISTS(temp$) THEN
  215.             _SNDVOL IsHowYouSpell, .5
  216.             _SNDPLAY IsHowYouSpell
  217.             WHILE _SNDPLAYING(IsHowYouSpell) 'wait for sound to finish before playing again
  218.                 _LIMIT 10 'play nice with CPU during wait
  219.                 GOSUB checkstop
  220.                 IF ControlVariable1 THEN _SNDSTOP (IsHowYouSpell): EXIT SUB
  221.             WEND
  222.  
  223.             temp = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
  224.             _SNDPLAY temp
  225.             WHILE _SNDPLAYING(temp) 'wait for sound to finish before playing again
  226.                 _LIMIT 10 'play nice with CPU during wait
  227.                 GOSUB checkstop
  228.                 IF ControlVariable1 THEN _SNDCLOSE temp: EXIT SUB
  229.             WEND
  230.             _SNDCLOSE temp
  231.  
  232.             FOR i = 1 TO LEN(word$)
  233.                 a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
  234.                 _PRINTSTRING (StartX + (i - 1) * _FONTWIDTH, 510), CHR$(a)
  235.                 IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
  236.                 _SNDPLAY AlphaSound(a)
  237.                 WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
  238.                     _LIMIT 10 'play nice with CPU during wait
  239.                     GOSUB checkstop
  240.                     IF ControlVariable1 THEN EXIT SUB
  241.                 WEND
  242.             NEXT
  243.         END IF
  244.     END IF
  245.  
  246.     EXIT SUB
  247.  
  248.     checkstop:
  249.         IF _MOUSEY > 451 AND _MOUSEY < 491 THEN
  250.             IF _MOUSEX > 575 AND _MOUSEX < 770 THEN 'stop
  251.                 ControlVariable1 = -1 'Stop Command for playing the word
  252.             END IF
  253.         END IF
  254.     END IF
  255.     RETURN
  256.  
  257.  
  258. SUB ChangePhotoTags (word$)
  259.     'Get a listing of the files
  260.     file$ = TagDir$ + word$ + ".txt"
  261.     OPEN file$ FOR OUTPUT AS #1
  262.     PRINT #1, PhotoTag.Year
  263.     PRINT #1, PhotoTag.Week
  264.     PRINT #1, PhotoTag.Sound
  265.     PRINT #1, PhotoTag.Theme
  266.     CLOSE
  267.  
  268. SUB LoadPhotoTags (word$)
  269.     file$ = TagDir$ + word$ + ".txt"
  270.     IF _FILEEXISTS(file$) THEN
  271.         OPEN file$ FOR INPUT AS #1
  272.         INPUT #1, PhotoTag.Year
  273.         INPUT #1, PhotoTag.Week
  274.         INPUT #1, PhotoTag.Sound
  275.         INPUT #1, PhotoTag.Theme
  276.         CLOSE
  277.     ELSE
  278.         PhotoTag.Year = 0
  279.         PhotoTag.Week = 0
  280.         PhotoTag.Sound = ""
  281.         PhotoTag.Theme = ""
  282.         IF word$ <> "" THEN ChangePhotoTags word$
  283.     END IF
  284.  
  285.  
  286. SUB ChangeSearchTags
  287.     'Get a listing of the files
  288.     PhotoList$ = ImageDir$ + "*.bmp " + ImageDir$ + "*.jpg " + ImageDir$ + "*.png " + ImageDir$ + "*.gif "
  289.     SHELL _HIDE "DIR " + PhotoList$ + "/b /s /a-d >PhotoList.txt"
  290.  
  291.     REDIM _PRESERVE PhotoList(100000)
  292.     'Load those names into a file.
  293.     OPEN "Photolist.txt" FOR BINARY AS #1
  294.     PhotoCount = 0
  295.     DO UNTIL EOF(1)
  296.         LINE INPUT #1, fullpath$
  297.         word$ = MID$(fullpath$, _INSTRREV(fullpath$, "\") + 1)
  298.         word$ = LEFT$(word$, INSTR(word$, ".") - 1)
  299.  
  300.         file$ = TagDir$ + word$ + ".txt"
  301.         IF _FILEEXISTS(file$) THEN
  302.             OPEN file$ FOR INPUT AS #2
  303.             INPUT #2, PhotoTag.Year
  304.             INPUT #2, PhotoTag.Week
  305.             INPUT #2, PhotoTag.Sound
  306.             INPUT #2, PhotoTag.Theme
  307.         ELSE
  308.             OPEN file$ FOR OUTPUT AS #2
  309.             PRINT #2, 0
  310.             PRINT #2, 0
  311.             PRINT #2, ""
  312.             PRINT #2, ""
  313.         END IF
  314.         CLOSE #2
  315.         good = -1
  316.         IF LimitTag.Year <> 0 AND LimitTag.Year <> PhotoTag.Year THEN good = 0
  317.         IF LimitTag.Week <> 0 AND LimitTag.Week <> PhotoTag.Week THEN good = 0
  318.  
  319.         IF LimitTag.Sound <> "" AND LimitTag.Sound <> PhotoTag.Sound THEN good = 0
  320.         IF LimitTag.Theme <> "" AND LimitTag.Theme <> PhotoTag.Theme THEN good = 0
  321.         IF good THEN
  322.             PhotoCount = PhotoCount + 1
  323.             PhotoList(PhotoCount) = fullpath$
  324.         END IF
  325.     LOOP
  326.     REDIM _PRESERVE PhotoList(PhotoCount)
  327.     CLOSE
  328.     MakeList
  329.  
  330. SUB MakeList
  331.     RepeatCount = WordList(0)
  332.     REDIM WordList(PhotoCount * RepeatCount) AS LONG
  333.     WordList(0) = RepeatCount
  334.     IF UBOUND(wordlist) > 0 THEN
  335.         PhotoChosen = 1
  336.     ELSE
  337.         PhotoChosen = 0
  338.         EXIT SUB
  339.     END IF
  340.     DIM TempList(PhotoCount) AS LONG
  341.     FOR i = 1 TO PhotoCount
  342.         TempList(i) = i
  343.     NEXT
  344.     FOR i = 1 TO RepeatCount
  345.         FOR j = 1 TO PhotoCount
  346.             r = INT(RND * PhotoCount) + 1
  347.             SWAP TempList(j), TempList(r)
  348.         NEXT
  349.         FOR j = 1 TO PhotoCount
  350.             Count = Count + 1
  351.             WordList(Count) = TempList(j)
  352.         NEXT
  353.     NEXT
  354.  
  355. FUNCTION ChangeValue$ (x, y, tword$, limit)
  356.     S = SaveState
  357.     _FONT 16
  358.     temp$ = CHR$(179)
  359.     _KEYCLEAR
  360.     DO
  361.         Box x, y, 100, 20, 1, Black, Gold
  362.         CenterText x, y, x + 100, y + 20, temp$
  363.         k = _KEYHIT
  364.         SELECT CASE k
  365.             CASE 8
  366.                 tword$ = LEFT$(tword$, LEN(tword$) - 1)
  367.             CASE 13
  368.                 EXIT DO
  369.             CASE 48 TO 57 'We'll always accept numeric input
  370.                 tword$ = tword$ + CHR$(k)
  371.             CASE 65 TO 90, 97 TO 122 'A-Z (a-z) only when we're dealing with a string
  372.                 IF NOT limit THEN tword$ = tword$ + CHR$(k)
  373.         END SELECT
  374.         temp$ = tword$ + CHR$(179)
  375.         _LIMIT 10
  376.         DisplayTags 575, 150, "Search Tags (" + _TRIM$(STR$(PhotoCount)) + ")", LimitTag
  377.         DisplayTags 575, 300, "Photo Tags", PhotoTag
  378.     LOOP
  379.     ChangeValue$ = tword$
  380.     RestoreState S
  381.  
  382. SUB DisplayTags (x, y, Title AS STRING, DisplayTag AS TagType)
  383.     S = SaveState
  384.     _FONT 16
  385.     W = 200: h = 106
  386.     Box x, y, W, h, 2, BlueGray, Gold
  387.     COLOR Gold, 0
  388.     CenterText x, y + 2, x + 200, y + 20, Title
  389.     LINE (x + 1, y + 19)-STEP(W - 2, 0), Gold
  390.     COLOR White, 0
  391.     xs = x + 24: ys = y + 24 'x/y start after the box offset
  392.     _PRINTSTRING (xs, ys), "Year :"
  393.     _PRINTSTRING (xs, ys + 20), "Week :"
  394.     _PRINTSTRING (xs, ys + 40), "Sound:"
  395.     _PRINTSTRING (xs, ys + 60), "Theme:"
  396.     bxs = xs + 50: bys = ys - 2 'x/y start for the display boxes
  397.     FOR i = 0 TO 3
  398.         Box bxs, bys + i * 20, 100, 20, 1, Black, Gold
  399.     NEXT
  400.     CenterValue bxs, bys, bxs + 100, bys + 20, DisplayTag.Year
  401.     CenterValue bxs, bys + 20, bxs + 100, bys + 40, DisplayTag.Week
  402.     CenterText bxs, bys + 40, bxs + 100, bys + 60, DisplayTag.Sound
  403.     CenterText bxs, bys + 60, bxs + 100, bys + 80, DisplayTag.Theme
  404.     RestoreState S
  405.  
  406. SUB Box (x, y, wide, high, thick, Kolor AS _UNSIGNED LONG, Trim AS _UNSIGNED LONG)
  407.     LINE (x, y)-STEP(wide, high), Kolor, BF
  408.     FOR i = 0 TO thick - 1
  409.         LINE (x + i, y + i)-STEP(wide - 2 * i, high - 2 * i), Trim, B
  410.     NEXT
  411.  
  412.  
  413. SUB CenterText (x1, y1, x2, y2, text$)
  414.     text$ = _TRIM$(text$)
  415.     xmax = x2 - x1: ymax = y2 - y1
  416.     textlength = _PRINTWIDTH(text$)
  417.     xpos = (xmax - textlength) / 2
  418.     ypos = (ymax - _FONTHEIGHT) / 2
  419.     _PRINTSTRING (x1 + xpos, y1 + ypos), text$
  420.  
  421. SUB CenterValue (x1, y1, x2, y2, value AS LONG)
  422.     text$ = _TRIM$(STR$(value))
  423.     CenterText x1, y1, x2, y2, text$
  424.  
  425. FUNCTION SaveState
  426.     TYPE SaveStateType
  427.         InUse AS INTEGER
  428.         DC AS INTEGER
  429.         BG AS INTEGER
  430.         F AS INTEGER
  431.         D AS INTEGER
  432.         S AS INTEGER
  433.         Disp AS INTEGER
  434.         CurX AS INTEGER
  435.         CurY AS INTEGER
  436.     END TYPE
  437.     DIM SS AS SaveStateType, Temp AS SaveStateType
  438.     SHARED NSS AS LONG 'Number of Saved States
  439.     SHARED SaveMem AS _MEM
  440.     IF NOT _MEMEXISTS(SaveMem) THEN
  441.         SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
  442.         $CHECKING:OFF
  443.         _MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
  444.         $CHECKING:ON
  445.     END IF
  446.  
  447.     'Data to Save
  448.     SS.InUse = -1
  449.     SS.F = _FONT
  450.     SS.DC = _DEFAULTCOLOR
  451.     SS.BG = _BACKGROUNDCOLOR
  452.     SS.D = _DEST
  453.     SS.S = _SOURCE
  454.     SS.Disp = _AUTODISPLAY
  455.     SS.CurX = POS(0)
  456.     SS.CurY = CSRLIN
  457.     FOR i = 1 TO NSS
  458.         o = (i - 1) * LEN(SS)
  459.         _MEMGET SaveMem, SaveMem.OFFSET + o, Temp
  460.         IF Temp.InUse = 0 THEN
  461.             _MEMPUT SaveMem, SaveMem.OFFSET + o, SS
  462.             SaveState = i
  463.             EXIT FUNCTION
  464.         END IF
  465.     NEXT
  466.     _MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
  467.     NSS = NSS + 1
  468.     SaveState = NSS
  469.  
  470. SUB RestoreState (WhichOne AS LONG)
  471.     DIM SS AS SaveStateType
  472.     SHARED NSS AS LONG 'Number of Saved States
  473.     SHARED SaveMem AS _MEM
  474.     _MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  475.     IF SS.InUse THEN
  476.         SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
  477.         $CHECKING:OFF
  478.         _MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  479.         $CHECKING:ON
  480.         _FONT SS.F
  481.         COLOR SS.DC, SS.BG
  482.         _DEST SS.D
  483.         _SOURCE SS.S
  484.         IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
  485.         LOCATE SS.CurY, SS.CurX
  486.     END IF
  487.  
  488. SUB GetNewWH (destWidth, destHeight, handle AS LONG, NewWidth, NewHeight) 'Sub return in variables NewWidth and NewHeight new image Width and image Height with the same ratio for optimal picture to set area width and height with [destWidth, destHeight]
  489.     W = _WIDTH(handle)
  490.     H = _HEIGHT(handle)
  491.     Pw = W / destWidth
  492.     Ph = H / destHeight
  493.     IF W > H THEN P = Pw ELSE P = Ph
  494.     NewWidth = W / P
  495.     NewHeight = H / P
  496.  
  497. FUNCTION mouseclick%
  498.     DO WHILE _MOUSEINPUT 'check mouse status
  499.         lb% = _MOUSEBUTTON(1)
  500.     LOOP
  501.  
  502.     DO WHILE lb% 'check for leftbutton release
  503.         i% = _MOUSEINPUT
  504.         lb% = _MOUSEBUTTON(1)
  505.         mouseclick% = -1
  506.     LOOP
  507.  

It's now making the review lists (I still need to quick code in the buttons to change how many times we review our words, as of now, they're stuck at 3 times each), and I think I've sorted out the glitches so that we no longer require the ON TIMER method of handling things.  All GOTO statements are now removed as well, since many folks find them completely distasteful, and all that's left at this point is to:

1) Add the 5 quick select buttons for the numbers of times to review the material chosen.
2) To add in the quiz routine at the end of the review process.

And then it's just add pictures and words, and tag them so they can be reviewed as wanted.
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 04, 2019, 07:27:14 am
Hi Steve. I tried with my "English" to say those few words .... the result is - useless. Check your email (@QB64.ORG), have fun and delete it. I never learned English (I learned German, because I live near the German border) and my English pronunciation is disastrous. But - again - I tried it, unlike English-speaking colleagues here on the forum. English speaking gentlemen programmers could think about each other :-D

Yeah, I have a provocative day today. Steve, because I don't have enough imagination, I ask you to elaborate on the idea. Five buttons. Good. Specifically, what to this 5 buttons have to do. Thanks for your patience.
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 04, 2019, 12:16:09 pm
Steve, because I don't have enough imagination, I ask you to elaborate on the idea. Five buttons. Good. Specifically, what to this 5 buttons have to do. Thanks for your patience.

They're now in there.  All that's left now is for the QUIZ portion of the program!  ;D

Code: [Select]
$COLOR:32

TYPE TagType
    Year AS INTEGER
    Week AS INTEGER
    Sound AS STRING
    Theme AS STRING
END TYPE

SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "Spell It Aloud"
RANDOMIZE TIMER

$IF WIN THEN
    temp$ = MID$(_CWD$, _INSTRREV(_CWD$, "\") + 1)
$ELSE
    temp$ = MID$(_CWD$, _INSTRREV(_CWD$, "/") + 1)
$END IF

IF temp$ <> "Spell It Aloud" THEN
    PRINT "ERROR -- Program not in proper directory."
    PRINT "Stopping execution..."
    PRINT
    PRINT "Please don't be a dufus, and fix it!"
END IF

CONST ImageDir$ = ".\Images\"
CONST SoundDir$ = ".\Alphabet Sounds\"
CONST TagDir$ = ".\Image Tags\"
CONST WordSoundDir$ = ".\Word Sounds\"


DIM SHARED PhotoTag AS TagType
DIM SHARED LimitTag AS TagType

DIM SHARED AlphaSound(65 TO 90)
REDIM SHARED PhotoList(100000) AS STRING
REDIM SHARED WordList(0) AS LONG
DIM SHARED PhotoCount AS LONG
DIM SHARED PhotoChosen AS LONG
DIM SHARED f AS LONG, f1 AS LONG
DIM SHARED IsHowYouSpell AS LONG
DIM SHARED ControlVariable1 AS LONG
DIM SHARED ShowNext AS LONG


'load our fonts
f = _LOADFONT("courbd.ttf", 84, "MONOSPACE")
f1 = _LOADFONT("courbd.ttf", 48, "MONOSPACE")
_FONT f
fw = _FONTWIDTH: fh = _FONTHEIGHT


'Load the alphabet sound library
FOR i = 65 TO 90
    temp$ = SoundDir$ + CHR$(i) + ".ogg"
    AlphaSound(i) = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
NEXT
temp$ = WordSoundDir$ + "is how you spell.ogg"
IsHowYouSpell = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")

_FONT f

_DELAY 1 'Give everything a moment to initialize and get started for us.
WordList(0) = 3 'three times repeating the list, as default
ChangeSearchTags
ShowNext = -1

DO
    ControlVariable = 0
    WHILE _MOUSEINPUT: WEND

    MB = _MOUSEBUTTON(1)
    Mx = _MOUSEX: My = _MOUSEY
    IF MB AND NOT oldmouse THEN
        IF Mx >= 650 AND Mx <= 750 THEN 'the mouse is in the correct X area for input
            SELECT CASE My
                CASE 171 TO 190
                    temp$ = ChangeValue(650, 171, STR$(LimitTag.Year), -1)
                    LimitTag.Year = VAL(temp$)
                    ChangeSearchTags
                    ShowNext = -1
                CASE 191 TO 210
                    temp$ = ChangeValue(650, 191, STR$(LimitTag.Week), -1)
                    LimitTag.Week = VAL(temp$)
                    ChangeSearchTags
                    ShowNext = -1
                CASE 211 TO 230
                    temp$ = ChangeValue(650, 211, LimitTag.Sound, 0)
                    LimitTag.Sound = temp$
                    ChangeSearchTags
                    ShowNext = -1
                CASE 231 TO 250
                    temp$ = ChangeValue(650, 231, LimitTag.Theme, 0)
                    LimitTag.Theme = temp$
                    ChangeSearchTags
                    ShowNext = -1
                CASE 324 TO 340
                    PhotoTag.Year = VAL(ChangeValue(650, 324, STR$(PhotoTag.Year), -1))
                    ChangePhotoTags word$
                    ShowNext = -1: ControlVariable1 = -1
                CASE 341 TO 360
                    PhotoTag.Week = VAL(ChangeValue(650, 341, STR$(PhotoTag.Week), -1))
                    ChangePhotoTags word$
                    ShowNext = -1: ControlVariable1 = -1
                CASE 361 TO 380
                    PhotoTag.Sound = ChangeValue(650, 361, PhotoTag.Sound, 0)
                    ChangePhotoTags word$
                    ShowNext = -1: ControlVariable1 = -1
                CASE 381 TO 400
                    PhotoTag.Theme = ChangeValue(650, 381, PhotoTag.Theme, 0)
                    ChangePhotoTags word$
                    ShowNext = -1: ControlVariable1 = -1
            END SELECT
        END IF
        IF _MOUSEY > 450 AND _MOUSEY < 470 THEN 'it's the right Y pos for the top control buttons
            SELECT CASE _MOUSEX
                CASE 575 TO 640 'Last
                    PhotoChosen = PhotoChosen - 1
                    IF PhotoChosen < 1 THEN PhotoChosen = 1
                    ShowNext = -1
                CASE 641 TO 705 'Play
                    ShowNext = -1
                CASE 706 TO 770 'Next
                    PhotoChosen = PhotoChosen + 1
                    IF PhotoChosen > UBOUND(WordList) THEN PhotoChosen = 1
                    ShowNext = -1
            END SELECT
        ELSEIF _MOUSEY > 471 AND _MOUSEY < 491 THEN 'it's the right Y pos for the 2nd row of control buttons
            SELECT CASE _MOUSEX
                CASE 575 TO 640 'Vol not yet implemented
                CASE 641 TO 705 'Stop now handled via the sound sub
                CASE 706 TO 770: SYSTEM 'Quit
            END SELECT
        ELSEIF _MOUSEY > 495 AND _MOUSEY < 515 THEN 'it's in the review column
            oldR = WordList(0)
            R = (_MOUSEX - 641) / 26
            IF R <> oldR THEN
                IF R > 0 AND R < 5 THEN WordList(0) = INT(R + 1)
                MakeList
                ShowNext = -1
            END IF
        END IF
    END IF

    k = _KEYHIT
    SELECT CASE k
        CASE 32 'space for next picture
            PhotoChosen = PhotoChosen + 1
            IF PhotoChosen > WordList(0) THEN PhotoChosen = 1
            ShowNext = -1
        CASE 27 'escape
            SYSTEM 'quit
    END SELECT

    IF ShowNext THEN
        ShowNext = 0
        IF PhotoChosen THEN
            temp$ = PhotoList(WordList(PhotoChosen))
            word$ = MID$(temp$, _INSTRREV(temp$, "\") + 1)
            word$ = LEFT$(word$, INSTR(word$, ".") - 1)

            IF tempimage <> 0 THEN _FREEIMAGE tempimage 'free the old image
            tempimage = _LOADIMAGE(temp$, 32) 'get the new image

            CLS
            _FONT f1: CenterText 0, 0, 800, 50, "Spell It Aloud": _FONT f

            'program photo area is 500 x 450 pixels. So:
            GetNewWH 500, 450, tempimage, nW, nH
            _PUTIMAGE (300 - (nW / 2), 300 - (nH / 2) - 25)-STEP(nW, nH), tempimage

            LoadPhotoTags word$
            temp$ = "Search Tags (" + _TRIM$(STR$(PhotoChosen)) + " of " + _TRIM$(STR$(UBOUND(wordlist))) + ")"
            DisplayTags 575, 150, temp$, LimitTag
            DisplayTags 575, 300, "Photo Tags", PhotoTag
            DrawCommandBoxes
            IF ControlVariable1 = 0 THEN PlayLetters word$
        ELSE
            DrawNoMatches
        END IF
        ControlVariable1 = 0
    END IF
    _LIMIT 10
    _DISPLAY
    oldmouse = MB
LOOP

SUB DrawCommandBoxes
    s = SaveState
    _FONT 16
    COLOR Black, 0
    BoxTitle 575, 450, 640, 470, 2, BlueGray, Gold, "LAST"
    BoxTitle 641, 450, 705, 470, 2, BlueGray, Gold, "PLAY"
    BoxTitle 706, 450, 770, 470, 2, BlueGray, Gold, "NEXT"
    BoxTitle 575, 471, 640, 490, 2, BlueGray, Gold, "VOL"
    COLOR Maroon
    BoxTitle 641, 471, 705, 490, 2, BlueGray, Gold, "STOP"
    COLOR Yellow
    BoxTitle 706, 471, 770, 490, 2, BlueGray, Gold, "QUIT"
    COLOR Black
    BoxTitle 575, 495, 640, 515, 2, BlueGray, Gold, "REVIEW:"
    R = WordList(0) '3
    FOR i = 1 TO 5
        IF i <> R THEN
            COLOR LightGray
            BoxTitle 641 + (i - 1) * 26, 495, 641 + i * 26, 515, 1, Black, Gold, STR$(i)
        ELSE
            COLOR White
            BoxTitle 641 + (i - 1) * 26, 495, 641 + i * 26, 515, 1, BlueGray, Gold, STR$(i)
        END IF
    NEXT
    RestoreState s
END SUB

SUB BoxTitle (x1, y1, x2, y2, thick, fg AS _UNSIGNED LONG, bg AS _UNSIGNED LONG, title$)
    Box x1, y1, x2 - x1 + 1, y2 - y1 + 1, thick, fg, bg
    CenterText x1, y1 + thick, x2, y2 + thick, title$
END SUB

SUB DrawNoMatches
    S = SaveState
    CLS
    _FONT f1
    Box 50, 50, 500, 500, 5, Silver, Gold
    CenterText 0, 0, 800, 50, "Spell It Aloud"
    FOR i = 1 TO 10 STEP .5
        CIRCLE (300, 300), 200 - i, BrickRed
        LINE (300 + SIN(_D2R(-45)) * 198 + i, 300 + COS(_D2R(-45)) * 198 + i)-(300 + SIN(_D2R(135)) * 198 + i, 300 + COS(_D2R(135)) * 198 + i), BrickRed
    NEXT
    COLOR Yellow, 0
    CenterText 50, 50, 550, 550, "No Matches"
    PhotoTag.Year = 0
    PhotoTag.Week = 0
    PhotoTag.Sound = ""
    PhotoTag.Theme = ""
    DisplayTags 575, 150, "Search Tags (0)", LimitTag
    DisplayTags 575, 300, "Photo Tags", PhotoTag
    RestoreState S
END SUB



SUB PlayLetters (word$)
    'Put the letters to the screen one by one
    ControlVariable1 = 0
    pw = _PRINTWIDTH(word$): StartX = (600 - pw) \ 2 'center position

    FOR i = 1 TO LEN(word$)
        a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
        _PRINTSTRING (StartX + (i - 1) * _FONTWIDTH, 510), CHR$(a)
        _DISPLAY
        IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
        _SNDPLAY AlphaSound(a)
        WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
            _LIMIT 10 'play nice with CPU during wait
            GOSUB checkstop
            IF ControlVariable1 THEN _SNDSTOP (AlphaSound(a))
        WEND
    NEXT
    IF ContolVariable1 = 0 THEN
        temp$ = WordSoundDir$ + word$ + ".ogg"
        IF _FILEEXISTS(temp$) THEN
            _SNDVOL IsHowYouSpell, .5
            _SNDPLAY IsHowYouSpell
            WHILE _SNDPLAYING(IsHowYouSpell) 'wait for sound to finish before playing again
                _LIMIT 10 'play nice with CPU during wait
                GOSUB checkstop
                IF ControlVariable1 THEN _SNDSTOP (IsHowYouSpell): EXIT SUB
            WEND

            temp = _SNDOPEN(temp$, "VOL,SYNC,LEN,PAUSE")
            _SNDPLAY temp
            WHILE _SNDPLAYING(temp) 'wait for sound to finish before playing again
                _LIMIT 10 'play nice with CPU during wait
                GOSUB checkstop
                IF ControlVariable1 THEN _SNDCLOSE temp: EXIT SUB
            WEND
            _SNDCLOSE temp

            FOR i = 1 TO LEN(word$)
                a = ASC(word$, i) AND NOT 32 'play lowercase letters as uppercase sounds
                _PRINTSTRING (StartX + (i - 1) * _FONTWIDTH, 510), CHR$(a)
                IF a < 65 OR a > 90 THEN _CONTINUE 'ignore non-letters in the file name
                _SNDPLAY AlphaSound(a)
                WHILE _SNDPLAYING(AlphaSound(a)) 'wait for sound to finish before playing again
                    _LIMIT 10 'play nice with CPU during wait
                    GOSUB checkstop
                    IF ControlVariable1 THEN EXIT SUB
                WEND
            NEXT
        END IF
    END IF

    EXIT SUB

    checkstop:
    WHILE _MOUSEINPUT: WEND
    IF _MOUSEBUTTON(1) THEN
        IF _MOUSEY > 451 AND _MOUSEY < 491 THEN
            IF _MOUSEX > 575 AND _MOUSEX < 770 THEN 'stop
                ControlVariable1 = -1 'Stop Command for playing the word
            END IF
        END IF
    END IF
    RETURN
END SUB


SUB ChangePhotoTags (word$)
    'Get a listing of the files
    file$ = TagDir$ + word$ + ".txt"
    OPEN file$ FOR OUTPUT AS #1
    PRINT #1, PhotoTag.Year
    PRINT #1, PhotoTag.Week
    PRINT #1, PhotoTag.Sound
    PRINT #1, PhotoTag.Theme
    CLOSE
END SUB

SUB LoadPhotoTags (word$)
    file$ = TagDir$ + word$ + ".txt"
    IF _FILEEXISTS(file$) THEN
        OPEN file$ FOR INPUT AS #1
        INPUT #1, PhotoTag.Year
        INPUT #1, PhotoTag.Week
        INPUT #1, PhotoTag.Sound
        INPUT #1, PhotoTag.Theme
        CLOSE
    ELSE
        PhotoTag.Year = 0
        PhotoTag.Week = 0
        PhotoTag.Sound = ""
        PhotoTag.Theme = ""
        IF word$ <> "" THEN ChangePhotoTags word$
    END IF
END SUB


SUB ChangeSearchTags
    'Get a listing of the files
    PhotoList$ = ImageDir$ + "*.bmp " + ImageDir$ + "*.jpg " + ImageDir$ + "*.png " + ImageDir$ + "*.gif "
    SHELL _HIDE "DIR " + PhotoList$ + "/b /s /a-d >PhotoList.txt"

    REDIM _PRESERVE PhotoList(100000)
    'Load those names into a file.
    OPEN "Photolist.txt" FOR BINARY AS #1
    PhotoCount = 0
    DO UNTIL EOF(1)
        LINE INPUT #1, fullpath$
        word$ = MID$(fullpath$, _INSTRREV(fullpath$, "\") + 1)
        word$ = LEFT$(word$, INSTR(word$, ".") - 1)

        file$ = TagDir$ + word$ + ".txt"
        IF _FILEEXISTS(file$) THEN
            OPEN file$ FOR INPUT AS #2
            INPUT #2, PhotoTag.Year
            INPUT #2, PhotoTag.Week
            INPUT #2, PhotoTag.Sound
            INPUT #2, PhotoTag.Theme
        ELSE
            OPEN file$ FOR OUTPUT AS #2
            PRINT #2, 0
            PRINT #2, 0
            PRINT #2, ""
            PRINT #2, ""
        END IF
        CLOSE #2
        good = -1
        IF LimitTag.Year <> 0 AND LimitTag.Year <> PhotoTag.Year THEN good = 0
        IF LimitTag.Week <> 0 AND LimitTag.Week <> PhotoTag.Week THEN good = 0

        IF LimitTag.Sound <> "" AND LimitTag.Sound <> PhotoTag.Sound THEN good = 0
        IF LimitTag.Theme <> "" AND LimitTag.Theme <> PhotoTag.Theme THEN good = 0
        IF good THEN
            PhotoCount = PhotoCount + 1
            PhotoList(PhotoCount) = fullpath$
        END IF
    LOOP
    REDIM _PRESERVE PhotoList(PhotoCount)
    CLOSE
    MakeList
END SUB

SUB MakeList
    RepeatCount = WordList(0)
    REDIM WordList(PhotoCount * RepeatCount) AS LONG
    WordList(0) = RepeatCount
    IF UBOUND(wordlist) > 0 THEN
        PhotoChosen = 1
    ELSE
        PhotoChosen = 0
        EXIT SUB
    END IF
    DIM TempList(PhotoCount) AS LONG
    FOR i = 1 TO PhotoCount
        TempList(i) = i
    NEXT
    FOR i = 1 TO RepeatCount
        FOR j = 1 TO PhotoCount
            r = INT(RND * PhotoCount) + 1
            SWAP TempList(j), TempList(r)
        NEXT
        FOR j = 1 TO PhotoCount
            Count = Count + 1
            WordList(Count) = TempList(j)
        NEXT
    NEXT
END SUB

FUNCTION ChangeValue$ (x, y, tword$, limit)
    S = SaveState
    _FONT 16
    temp$ = CHR$(179)
    _KEYCLEAR
    _AUTODISPLAY
    DO
        Box x, y, 100, 20, 1, Black, Gold
        CenterText x, y, x + 100, y + 20, temp$
        k = _KEYHIT
        SELECT CASE k
            CASE 8
                tword$ = LEFT$(tword$, LEN(tword$) - 1)
            CASE 13
                EXIT DO
            CASE 48 TO 57 'We'll always accept numeric input
                tword$ = tword$ + CHR$(k)
            CASE 65 TO 90, 97 TO 122 'A-Z (a-z) only when we're dealing with a string
                IF NOT limit THEN tword$ = tword$ + CHR$(k)
        END SELECT
        temp$ = tword$ + CHR$(179)
        _LIMIT 10
        DisplayTags 575, 150, "Search Tags (" + _TRIM$(STR$(PhotoCount)) + ")", LimitTag
        DisplayTags 575, 300, "Photo Tags", PhotoTag
    LOOP
    ChangeValue$ = tword$
    RestoreState S
END SUB

SUB DisplayTags (x, y, Title AS STRING, DisplayTag AS TagType)
    S = SaveState
    _FONT 16
    W = 200: h = 106
    Box x, y, W, h, 2, BlueGray, Gold
    COLOR Gold, 0
    CenterText x, y + 2, x + 200, y + 20, Title
    LINE (x + 1, y + 19)-STEP(W - 2, 0), Gold
    COLOR White, 0
    xs = x + 24: ys = y + 24 'x/y start after the box offset
    _PRINTSTRING (xs, ys), "Year :"
    _PRINTSTRING (xs, ys + 20), "Week :"
    _PRINTSTRING (xs, ys + 40), "Sound:"
    _PRINTSTRING (xs, ys + 60), "Theme:"
    bxs = xs + 50: bys = ys - 2 'x/y start for the display boxes
    FOR i = 0 TO 3
        Box bxs, bys + i * 20, 100, 20, 1, Black, Gold
    NEXT
    CenterValue bxs, bys, bxs + 100, bys + 20, DisplayTag.Year
    CenterValue bxs, bys + 20, bxs + 100, bys + 40, DisplayTag.Week
    CenterText bxs, bys + 40, bxs + 100, bys + 60, DisplayTag.Sound
    CenterText bxs, bys + 60, bxs + 100, bys + 80, DisplayTag.Theme
    RestoreState S
END SUB

SUB Box (x, y, wide, high, thick, Kolor AS _UNSIGNED LONG, Trim AS _UNSIGNED LONG)
    LINE (x, y)-STEP(wide, high), Kolor, BF
    FOR i = 0 TO thick - 1
        LINE (x + i, y + i)-STEP(wide - 2 * i, high - 2 * i), Trim, B
    NEXT
END SUB


SUB CenterText (x1, y1, x2, y2, text$)
    text$ = _TRIM$(text$)
    xmax = x2 - x1: ymax = y2 - y1
    textlength = _PRINTWIDTH(text$)
    xpos = (xmax - textlength) / 2
    ypos = (ymax - _FONTHEIGHT) / 2
    _PRINTSTRING (x1 + xpos, y1 + ypos), text$
END SUB

SUB CenterValue (x1, y1, x2, y2, value AS LONG)
    text$ = _TRIM$(STR$(value))
    CenterText x1, y1, x2, y2, text$
END SUB

FUNCTION SaveState
    TYPE SaveStateType
        InUse AS INTEGER
        DC AS INTEGER
        BG AS INTEGER
        F AS INTEGER
        D AS INTEGER
        S AS INTEGER
        Disp AS INTEGER
        CurX AS INTEGER
        CurY AS INTEGER
    END TYPE
    DIM SS AS SaveStateType, Temp AS SaveStateType
    SHARED NSS AS LONG 'Number of Saved States
    SHARED SaveMem AS _MEM
    IF NOT _MEMEXISTS(SaveMem) THEN
        SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
        $CHECKING:OFF
        _MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
        $CHECKING:ON
    END IF

    'Data to Save
    SS.InUse = -1
    SS.F = _FONT
    SS.DC = _DEFAULTCOLOR
    SS.BG = _BACKGROUNDCOLOR
    SS.D = _DEST
    SS.S = _SOURCE
    SS.Disp = _AUTODISPLAY
    SS.CurX = POS(0)
    SS.CurY = CSRLIN
    $CHECKING:OFF
    FOR i = 1 TO NSS
        o = (i - 1) * LEN(SS)
        _MEMGET SaveMem, SaveMem.OFFSET + o, Temp
        IF Temp.InUse = 0 THEN
            _MEMPUT SaveMem, SaveMem.OFFSET + o, SS
            SaveState = i
            EXIT FUNCTION
        END IF
    NEXT
    _MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
    $CHECKING:ON
    NSS = NSS + 1
    SaveState = NSS
END SUB

SUB RestoreState (WhichOne AS LONG)
    DIM SS AS SaveStateType
    SHARED NSS AS LONG 'Number of Saved States
    SHARED SaveMem AS _MEM
    _MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
    $CHECKING:ON
    IF SS.InUse THEN
        SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
        $CHECKING:OFF
        _MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
        $CHECKING:ON
        _FONT SS.F
        COLOR SS.DC, SS.BG
        _DEST SS.D
        _SOURCE SS.S
        IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
        LOCATE SS.CurY, SS.CurX
    END IF
END SUB

SUB GetNewWH (destWidth, destHeight, handle AS LONG, NewWidth, NewHeight) 'Sub return in variables NewWidth and NewHeight new image Width and image Height with the same ratio for optimal picture to set area width and height with [destWidth, destHeight]
    W = _WIDTH(handle)
    H = _HEIGHT(handle)
    Pw = W / destWidth
    Ph = H / destHeight
    IF W > H THEN P = Pw ELSE P = Ph
    NewWidth = W / P
    NewHeight = H / P
END SUB

What the review buttons does is choose how many times we review the material at hand, before we finish and take our (not yet implemented) quiz.

For example, we narrow down our list of words to "Petr, Pete, Peter".

If the Review number is one, our review list might be:  "Pete, Petr, Peter"
If the Review number is two, our review list might be:  "Pete, Petr, Peter, Petr, Peter, Pete".

It's just the number of times (from 1 to 5) which we want to set to review the material, before taking a test on it. 



Not related to this, but related to QB64 development:

If you notice, the syntax on $COLOR32 has changed a little in my version; it's now $COLOR:32.  (See that : in there?)

This is because $COLOR now has 2 modes which we can get names from -- $COLOR:32 for 32-bit color names, and $COLOR:0 for screen 0 color names. 

It's a slight change, but it makes my current version of QB64 slightly incompatible with yours, at the moment.

When this little project is finished, I'll probably just put the CONST values in an $INCLUDE file for now, so that it'll be usable for everyone -- those that keep up with the latest development builds, and those who prefer the stable 1.3 version instead.  ;)
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 04, 2019, 01:57:56 pm
Yeah, so there is a nice buzz at the beginning, with the wrong directory, but SOMEONE who entered it also for Linux no longer added support for Linux when loading the contents of the directory (ls for Linux, DIR for Windows) :-D
So i am tryed it and have query. If selecting 3 images, in Photo tags saving for this 3 photos the same flags to theme and then select review - let say to 3x. Then if i press space or next button, are this 3 photos playing (if i set this theme to search tag). So after then, when are this selected images all played, in current version starting again, but final version then start quiz. Its so correct?
Title: Re: Spell It Aloud (Help Requested)
Post by: SMcNeill on August 04, 2019, 06:44:54 pm
Here's a prototype of the finished product.  ;)

Things still needed:

It needs some layout work to center things better to make the screen prettier.
A prettier QUIZ results page, with pauses in case the user has a quiz with more words than can appear on a single display page.
Hard/Easy mode to be implemented for the spelling quiz --
      At the moment, all we're having is the HARD mode implemented.  (Enter the word, with no help whatsoever.)
      For easy mode, I picture it to limit word input to the proper number of letters, and to display a placeholder on the screen for the letters.  Such as for "cat", the screen will offer a prompt of three stars ("***") as placeholders to help indicate how many letters belong in the word. 

But, more or less, our little spelling training program is workable the way it already exists!  ;D
Title: Re: Spell It Aloud (Help Requested)
Post by: Petr on August 05, 2019, 11:28:14 am
Nice Work, Steve. There is one very small bug - try to search tags writing "animals", not "Animals", then is none match. LCASE$ can reapir it.  Next - :) - in begin - if is program not in correct directory, yet continue.

This is big and nice work, Steve.
Title: Re: Spell It Aloud (Help Requested)
Post by: SW on August 05, 2019, 01:18:42 pm
congratz, Steve!

I mind its good to add multi lingual support by adding ".\en\Alphabet Sounds\" and "".\en\Word Sounds\". So you can add other pronounces(languages) for same images.