calling screens and returning

I have a search screen function which returns the string searched for, and then I get the list of matching files from the server and load them into the audio player, launch a posterscreen displaying the files and associated graphics, from which one can play the audio files. However, I don’t really understand the correct method for exiting this screen back to the search. Currently when I exit (using the up button on the remote), it goes back to the search screen, but although the search screen works, nothing happens when you hit search this time.

I think I don’t really understand how to call screens and return - the calling part I understand, but I don’t know how one goes from one function back to a previous function when executing in-line.

my app looks like this:

sub main()

DefineObjects()

AssignDefaults()

setlevel(m.default)

SetCat(m.level)

searchscreen(“tracks”)

getsearchtracks(0,20)

displayposter()

so how do I get from here:
messageloop()
back to the searchscreen() and getsearchtracks()

end sub

How are you setting your message port and listening to it via your wait? The behavior you’re describing almost sounds like you’re message port may be getting reset between screens.

Ok, heres the actual code: (almost everything is using m.variablename, so only a few functions actually use the “return variablename” approach). The message port m.port is created in DefineObjects and then assigned in AssignDefaults which assigns m.poster, m.searchscrn and m.audioplayer to use m.port.


sub main()
print "defining objects"
 DefineObjects()
print "assigning defaults"
 AssignDefaults()
print "setting default level"
 setlevel(m.default)
print "setting default categories"
	SetCat(m.level)
print "this shoud load the search screen"
searchscreen("tracks")
print "ok, now we have search string, lets get tracks"
getsearchtracks(0,20)
print "ok, now we should have tracks, lets display the results"
 displayposter()

print "ok, now wait for something to happen, anything almost"
 messageloop()
 
end sub

Sub MessageLoop()
while true
      msg = wait(0, m.port)
           if type(msg) = "roPosterScreenEvent" then
                if msg.isListItemSelected() then
                    idx = msg.GetIndex()   ' <-- gives the index of the selected poster
                    m.audioPlayer.SetNext(idx) ' <-- sets the song to play to the same index as the poster
                    m.audioPlayer.Play()   ' <-- start the song
                end if
      else if type(msg) = "roAudioPlayerEvent" then
			  if msg.getmessage() ="end of stream" or msg.getmessage()="end of playlist" then
			   print "roAudioPlayerEvent: "; msg.getmessage() ;
			   print "done playing "+m.TrackTitle
			   m.audioplayer.stop()
			   
			  end if
	 
      else if type(msg) = "roImageCanvasEvent" then 
            if (msg.isRemoteKeyPressed()) then 
                i = msg.GetIndex() 
                print "Key Pressed - " ; msg.GetIndex() 
                if (i = 2) then 
                    ' Up - Close the screen. 
 
                    m.canvas.close() 
                end if 
            else if (msg.isScreenClosed()) then 
                	print "Closed" 
                	return 
                 end if 
            end if 
           
        ' extra?  end if
        end while	
End Sub

I’m thinking I need a while loop in the main() section maybe? otherwise after exiting the msg loop, it just falls through to the end of sub main(). I’m having conceptual problems understanding the best way to do this. Essentially I’m creating various aspects of the app for testing purposes, testing each area of it, then building the next part. I’m pretty far along but seem to have missed something important near the beginning of learning the system. Some of the examples have a whole pile of “category” “leaf” stuff which I don’t even begin to understand what they are talking about, popping when they exit a screen, etc, don’t know if this is directly related to what I’m doing. Looking at the audioapp, seems much simpler, but my app will be more complex, similar to the YouTube app in layout.

  • Joel

Generally it’s helpful to think of your channel as a stack of index cards. You start with a base card (or home screen), then add and remove cards in response to the user’s actions. Pushing and popping are just fancy programmer words for adding or removing cards from the stack. Whenever you break out of a given screen’s event loop, that screen closes and the screen beneath it reappears. When the home screen closes, the channel exits back to the box’s channel screen.

It sounds like you’re using a single wait loop to handle all of your screens. There are few situation where you’d want to do that. Typically you’ll want a separate wait loop for each screen, and exit them as the screen closes. I have to run at the moment, so I can’t go into much more detail, but if someone else doesn’t beat me to it, I’ll try to post an example of how I do it later this evening.

when exiting the poster screen, it goes back automatically to the search screen, buti dont think it goes back to the code that handles that screen. I guess thatis the meat of my question, when i exit the sub that builds and displays the poster screen, i dont see any way to get back to the sub displayposter() since the sub messageloop()is not called from sub displayposter() but from main(). should each successive screen be called from the sub that calls the previous screen?

“jbrave” wrote:
when exiting the poster screen, it goes back automatically to the search screen, buti dont think it goes back to the code that handles that screen. I guess thatis the meat of my question, when i exit the sub that builds and displays the poster screen, i dont see any way to get back to the sub displayposter() since the sub messageloop()is not called from sub displayposter() but from main(). should each successive screen be called from the sub that calls the previous screen?
You should be calling your messageloop() sub from each screen, and exiting that instance when you close the screen.

In a very simplified example, this is how I do my screens. Ordinarily I’d break these up into multiple source files, and make them more self contained… The main thing to notice here is that each screen has its own event/message loop that blocks the parent event loop until the screen is closed. This example uses a shared ListenForEvents() sub, but for readability (and to avoid a huge If/Then tree), you’d probably want a different one for each screen.


Sub Main()
	m.MessagePort = CreateObject( "roMessagePort" )

	poster = NewPosterScreen( "parameters like title, breadcrumb, etc" )
	' show the poster screen and let it's event loop handle it's events
	poster.Show()
	
	' at this point, the last event loop has exited, and screens have
	' closed, so we exit the app
End Sub

Function NewPosterScreen( some parameters to pass in ) As Object
	poster = {
		Screen: CreateObject( "roPosterScreen" ),
		MessagePort: m.MessagePort,
		
		Init: Poster_Init,
		Show: Poster_Show,
		ListenForEvents: ListenForEvents
	}
	poster.Init()
	Return poster
End Function

Sub Poster_Init()
	'Initialize poster screen details here
	m.Screen.SetMessagePort( m.MessagePort )
End Sub

Sub Poster_Show()
	' show the screen
	m.Screen.Show()
	' jump into local event loop
	m.ListenForEvents()
End Sub

Function NewSprinboardScreen( some parameters to pass in ) As Object
	poster = {
		Screen: CreateObject( "roSpringboardScreen" ),
		MessagePort: m.MessagePort,
		
		Init: Springboard_Init,
		Show: Springboard_Show,
		ListenForEvents: ListenForEvents
	}
	poster.Init()
	Return poster
End Function

Sub Springboard_Init()
	'Initialize poster screen details here
	m.Screen.SetMessagePort( m.MessagePort )
End Sub

Sub Springboard_Show()
	' show the screen
	m.Screen.Show()
	' jump into local event loop
	m.ListenForEvents()
End Sub

Sub ListenForEvents()
	While True
		msg = Wait( 0, m.MessagePort )
		If msg <> invalid Then
			If Type( msg ) = "roPosterScreenEvent" Then
				' handle poster screen events
				If msg.IsScreenClosed() Then
					' screen is closed, exit this instance of the
					' event loop
					Exit While
				Else If msg.IsListItemSelected() Then
					springboard = NewSpringboardScreen()
					
					' This will block until the springboard is closed
					' at which point we'll re-enter this instance of the
					' event loop
					springboard.Show()
				Else If msg.SomeOtherEvent Then
					'blahblahblah
				End If
			Else If Type( msg ) = "roSpringboardScreenEvent" Then
				If msg.IsScreenClosed() Then
					' screen is closed, exit this instance of the
					' event loop
					Exit While
				End If
			End If
		End If
	End While
End Sub

The main thing to notice here is that each screen has its own event/message loop that blocks the parent event loop until the screen is closed.

i think that answers the substance of my question, for some reason it wouldn’t gell in my brain…

thanks!

I find the “stack of cards” functionality to be the most frustrating thing about Brightscript.

Well, I think I get the stack of cards thing now, correct me if I’m wrong, but it works sort of like this:

card1
sub main()
put up poster screen
message loop listening for isitemselected
if is true and item is search, call search screen
otherwise (check for other types or exit app)
end sub

card2
sub search screen()
listen for keypresses, collect messages into a string until search button is pressed
if search is full then call displayresults() otherwise exit sub back to main
end sub

Card3
sub displayresults()
create a poster screen containng all the results from the search.
listen for messages
if listitemisselected
play that item
otherwise exit back to sub search screen
end sub

I think that is pretty simple, assuming I understood what TheEndless was saying.

  • Joel

I think you’ve got it Joel.

–Kevin