Remote Python JSON help needed
#1
First off. I'm a noob to python but not programming in general (VB.NET, vbscript, powershell, autoit). So please bear with me. Also please move this thread if it's posted in the incorrect location. since it really is not an addon.

I'm trying to use my raspberry pi (or any windows/linux python client) to return a list of movies and the thumbnail. What I'm looking for is a way to cycle through the found movies. I can't get past the first step of returning the data into a List or Dictionary(not sure which is better).

This is my current sample code for testing:

Code:
url = 'http://10.1.1.130:8080/jsonrpc?request={"jsonrpc":"2.0","method":"VideoLibrary.GetMovies","params":{"filter":{"field":"playcount","operator":"is","value":"0"},"limits":{"start":0,"end":75},"properties":["thumbnail","file"],"sort":{"order":"ascending","method":"label","ignorearticle":true}},"id":"libMovies"}'


import json, requests, urllib
r = requests.get(url)
r.status_code
print r
print r.status_code
print r.text
print r.encoding

this returns:
Code:
{"id":"libMovies","jsonrpc":"2.0","result":{"limits":{"end":3,"start":0,"total":3},"movies":[{"file":"/home/sysop/Videos/aliens.avi","label":"Aliens","movieid":1,"thumbnail":"image://http%3a%2f%2fimage.tmdb.org%2ft%2fp%2foriginal%2f4dw4JX6uqGPO5v5bJYusaGNSON2.jpg/"},{"file":"/home/sysop/Videos/cars.mp4","label":"Cars","movieid":2,"thumbnail":"image://http%3a%2f%2fimage.tmdb.org%2ft%2fp%2foriginal%2fwjn9AKZy98qCiixi9iWpuxiUTfh.jpg/"},{"file":"/home/sysop/Videos/planes.AVI","label":"Planes","movieid":3,"thumbnail":"image://http%3a%2f%2fimage.tmdb.org%2ft%2fp%2foriginal%2f8CkrElYZnYrIWEDGE5V2Xn4hl58.jpg/"}]}}

To me this looks like a dictionary wrapped in a dictionary and list.

I have no idea how to reference that data in a variable (list or dictionary)

Also I would like it to download the thumbnail if possible.

Any help or suggestions if i'm going about this in the right or wrong direction.

Thanks!
Reply
#2
I think you'd do something like:
Code:
rawdata = json.loads(r.content)

# Loop through results
for movie in rawdata["result"]["movies"]:
  print movie["label"]

I've never used requests before so you may want to look at this: http://stackoverflow.com/questions/63863...-in-python however I think there will be people here who know exactly what you need.
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#3
Real world example
https://github.com/XBMC-Addons/script.ar...tup.py#L69
Read/follow the forum rules.
For troubleshooting and bug reporting, read this first
Interested in seeing some YouTube videos about Kodi? Go here and subscribe
Reply
#4
(2014-02-18, 23:38)el_Paraguayo Wrote: I think you'd do something like:
Code:
rawdata = json.loads(r.content)

# Loop through results
for movie in rawdata["result"]["movies"]:
  print movie["label"]

I've never used requests before so you may want to look at this: http://stackoverflow.com/questions/63863...-in-python however I think there will be people here who know exactly what you need.

Thanks for the help!!! That was what I was looking for! This gets the data I need.

My code to get results so far:

Code:
# Loop through results
for movie in rawdata["result"]["movies"]:
  print movie["label"]
  print movie["thumbnail"]

# Assign results of limits
limits = rawdata["result"]["limits"]
print limits

totalmovies =  limits["end"]
print totalmovies

Any ideas on how the thumbnail can be downloaded to the local file system?
Reply
#5
Again, I suspect there's an easier way of doing this, but this is how I've done it before (apologies, it is old, ugly code!):
Code:
import urllib

# You may need to change this if code on different machine
xbmchost = "http://localhost:8080/"

# Your previous code here...


for movie in rawdata["result"]["movies"]:
  print movie["label"]

  # Get the image
  # Strip trailing slash off the thumbnail string
  im = movie["thumbnail"][:-1]

  # Escape the string
  im = urllib.quote_plus(im)

  # Build the link
  im = self.host + "image/" + im

  print "Image link: ", im

If you're downloading images, you probably want to use the filename that xbmc uses as you can then check whether the image has already been downloaded, rather than downloading every time.

How are you planning to show the images from your pi? I've been helping out on this and so there may be some code that can be shared.
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#6
Thanks for all the input! You really did put me in the right direction I needed.

I'm using pygame to display the images. below is the code i'm using so far. I think there is a better way to test which button is pressed but this is working fine as it is right now.

Looking for a way to play the movie when a button is pressed. I'm assuming some type of url post with JSON. Still researching that.

Code:
#
# The marquee
#
# This program uses raspberry pi buttons to cycle XBMC thumbnails
#
# It also will play the selected movie when a button is pressed

import RPi.GPIO as GPIO, time, json, requests, urllib, os, pygame

#setup url
url = 'http://10.1.1.130:8080/jsonrpc?request={"jsonrpc":"2.0","method":"VideoLibrary.GetMovies","params":{"filter":{"field":"playcount","operator":"is","value":"0"},"limits":{"start":0,"end":75},"properties":["thumbnail","file"],"sort":{"order":"ascending","method":"label","ignorearticle":true}},"id":"libMovies"}'
# grab url data
request = requests.get(url)
# load content to rawdata
rawdata = json.loads(request.content)

# Assign results of limits to find total movie count
limits = rawdata["result"]["limits"]
totalMovies = int(limits["end"])

# Assign movie variable
movieList = rawdata["result"]["movies"]

### begindebug area
print "Total movies found: " + str(totalMovies)
print "\n"
print rawdata
print "\n"
print movieList
print "\n"
#print movieList[1]["label"]
## end debug area

# use breakout board pin numbering
GPIO.setmode(GPIO.BCM)
# setup buttons
buttonLeft = 23
buttonRight = 24
buttonAction = 18
# setup channels
GPIO.setup(buttonLeft, GPIO.IN) # left
GPIO.setup(buttonRight, GPIO.IN) # right
GPIO.setup(buttonAction, GPIO.IN) # action
#read the status of pin 23
input = GPIO.input(buttonLeft)
input = GPIO.input(buttonRight)
input = GPIO.input(buttonAction)

#Assign variables
currentMovie = 1 # lets just start the process at first movie found

# startup pygame display
pygame.init()
screen = pygame.display.set_mode((0, 0))
done = False
image1 = pygame.image.load("/home/pi/temp.jpg")
clock = pygame.time.Clock()

def getThumb(movieNumber):
  tempMovie = movieNumber - 1
  print "Movie number: " + str(tempMovie) + " Name: " + movieList[tempMovie]["label"]
  #for movie in rawdata["result"]["movies"]:
  # print movie["label"]
  # Get the image
  # Strip trailing slash off the thumbnail string
  tempThumb = movieList[tempMovie]["thumbnail"]
  #print ("TempTHumb: " + str(tempThumb))
  im = tempThumb[:-1]
  # Escape the string
  im = urllib.quote_plus(im)
  # Build the link
  im = "http://10.1.1.130:8080/image/" + im
  #print "Image link: ", im
  #download the thumb
  thumbName=str(str(tempMovie) + ".jpg")
  download_thumb(im,thumbName)
  #show thumb
  image1 = pygame.image.load("/home/pi/" + thumbName)
  screen.fill((0,0,0)) # fill screen with black
  screen.blit(image1,(0,0)) #display image
  clock.tick(1)
  pygame.display.flip()

def download_thumb(url,thumbName):
    image=urllib.URLopener()
    image.retrieve(url,thumbName)  # download thumbnail at URL



#initialise a previous input variable to 0 (assume button not pressed last)
prev_input = 0
prev_input2 = 0
prev_input3 = 0
while True:
  #take a reading for left
  input = GPIO.input(buttonLeft)
  #if the last reading was low and this one high, print
  if ((not prev_input) and input):
    print("Left button pressed")
    currentMovie -= 1
    if currentMovie < 1:
      currentMovie = 1
    #print("Current Selected Movie: " + str(currentMovie))
    getThumb(currentMovie)
  #update previous input
  prev_input = input
  #slight pause to debounce
  time.sleep(0.05)

  #take a reading for right
  input2 = GPIO.input(buttonRight)
  #if the last reading was low and this one high, print
  if ((not prev_input2) and input2):
    print("Right button pressed")
    currentMovie += 1
    if currentMovie > totalMovies:
      currentMovie = totalMovies
    #print("Current Selected Movie: " + str(currentMovie))
    getThumb(currentMovie)
  #update previous input
  prev_input2 = input2
  #slight pause to debounce
  time.sleep(0.05)

  #take a reading for action
  input3 = GPIO.input(buttonAction)
  #if the last reading was low and this one high, print
  if ((not prev_input3) and input3):
    print("Action button pressed")
  #update previous input
  prev_input3 = input3
  #slight pause to debounce
  time.sleep(0.05)
Reply
#7
OK. Pygame's good - I'm familiar with it.

I actually wrote a function for getting the movie thumbnail which can saves the image locally and then check for the local file before downloading from XBMC. However, I won't have a chance to post the code until later (maybe the weekend).

You may also want to get in touch with Abshole on this forum, as he's got a pygame programme which displays his movies/music (and which he can use as a remote) - I've been helping him with it and it uses the code I mentioned above.
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#8
(2014-02-20, 11:30)el_Paraguayo Wrote: OK. Pygame's good - I'm familiar with it.

I actually wrote a function for getting the movie thumbnail which can saves the image locally and then check for the local file before downloading from XBMC. However, I won't have a chance to post the code until later (maybe the weekend).

You may also want to get in touch with Abshole on this forum, as he's got a pygame programme which displays his movies/music (and which he can use as a remote) - I've been helping him with it and it uses the code I mentioned above.

Thanks for all the insight again. I must say you have been very helpful. It's great to see a community forum where people will try and help each other out.

The project I am working on is for my home theater. I am mounting a smaller 27 inch TV to the wall in a frame by the entrance of the theater in my basement. It will have a 'NOW SHOWING' light above it (in the frame). It will have some simple arcade buttons on the bottom for anyone in my family to use. The buttons will be left, right, play. Since for now it will only show new movies added it won't be a bunch of images. This is why I changed my code to download all the thumbs when it starts up. I have changed the my config to rotate the PI by 90 degrees.

I have more challenges:

1) need to write code for play button
2) the thumb is not full screen. Need to find out how to display image in full screen
3) When the image displays it also shows a mouse cursor. need to get that hidden.
4) if I can figure a way to play the trailer that would be great but then the screen is rotated so may not look right.
Reply
#9
(2014-02-20, 17:33)jay2068 Wrote: I have more challenges:

1) need to write code for play button
2) the thumb is not full screen. Need to find out how to display image in full screen
3) When the image displays it also shows a mouse cursor. need to get that hidden.
4) if I can figure a way to play the trailer that would be great but then the screen is rotated so may not look right.
1) Yup - that's doable - got some code for that!
2) Yup - ditto
3) use this:
Code:
pygame.mouse.set_visible(False)
4) May be more tricky - don't know if pygame can stream videos, if not something like omxplayer on the pi may be able to do it.[/code]
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#10
ok got the mouse gone. thanks!

messing with /boot/config.txt with hdmi_mode and hdmi_group but can't get it to fit right. Should i be using this to adjust resolution or use pygame?

I may rethink the trailer playing. As I possibly could just have a button that is for play and one for trailer play. it will play it on the main TV as it's only 10 feet away.

working away...
Reply
#11
(2014-02-20, 20:56)jay2068 Wrote: ok got the mouse gone. thanks!

messing with /boot/config.txt with hdmi_mode and hdmi_group but can't get it to fit right. Should i be using this to adjust resolution or use pygame?

I may rethink the trailer playing. As I possibly could just have a button that is for play and one for trailer play. it will play it on the main TV as it's only 10 feet away.

working away...

Can't help much on hdmi set up. Is the problem that you're losing the edges? if so, have a look at this: http://www.raspberrypi.org/phpBB3/viewto...f=6&t=5786

I'd certainly aim to get the pi set up for the monitor first, and then just get pygame to fill the screen.

Also, when you say play trailer? where do you want the trailer to play? If it's on the main theatre screen, it's easy enough to get XBMC to play that. If you mean on the Pi, then my comments above are probably still right!
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#12
the correct settings for the /boot/config.txt on my raspberry pi are:

framebuffer_width=480
framebuffer_height=720
display_rotate=1

this allowed me to rotate the screen and adjust the size to the common thumbnail size of 720x480
Reply
#13
ok well I have the action button sort of working. It plays the first movie in my first folder. I have three folders setup in my videos (children, Hollywood and new movies) the following code seems to play the movies in the first folder children and not from the collection of all movies. I'm assuming it's in the JSON url to tell it what collection to look in. Any ideas?

Code:
def playMovie(movieToPlay):
   url = "http://" + ip + ":" + port + '/jsonrpc?request='
   payload = {"jsonrpc":"2.0","method":"player.open","params":{"item":{"movieid":movieToPlay}}}
   headers = {'content-type': 'application/json'}
   response = requests.post(url, data=json.dumps(payload), headers=headers)

Also I would like to change my url to select a specific library folder. This is looking like I just need the correct syntax for the JSON url.
Reply
#14
What movieid are you passing?
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#15
(2014-02-20, 22:23)jay2068 Wrote: ok well I have the action button sort of working. It plays the first movie in my first folder. I have three folders setup in my videos (children, Hollywood and new movies) the following code seems to play the movies in the first folder children and not from the collection of all movies. I'm assuming it's in the JSON url to tell it what collection to look in. Any ideas?

Code:
def playMovie(movieToPlay):
   url = "http://" + ip + ":" + port + '/jsonrpc?request='
   payload = {"jsonrpc":"2.0","method":"player.open","params":{"item":{"movieid":movieToPlay}}}
   headers = {'content-type': 'application/json'}
   response = requests.post(url, data=json.dumps(payload), headers=headers)

Also I would like to change my url to select a specific library folder. This is looking like I just need the correct syntax for the JSON url.

As for restricting the folder, you need to add a filter to the "params" section of your request: e.g.
Code:
"filter": {"field": "path", "operator": "contains", "value": "/path/to/your/movie/folder"}

Passing the right movieid should play the right film - it's not dependent on the path,
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply

Logout Mark Read Team Forum Stats Members Help
Remote Python JSON help needed0