public void addDidlNodes(DIDLContent didl, JSONArray browse) throws JSONException {
    for (int i = 0; i < browse.length(); i++) {
      JSONObject obj = browse.getJSONObject(i);
      String url = obj.getString("browse");
      String label = obj.getString("name");
      String thumbnail = obj.optString("image");
      String type = obj.optString("type");

      Integer subCount = Integer.parseInt(obj.optString("count", "10"));

      // Hack so we can easily get container label in request for metadata.
      try {
        url += "&label=" + URLEncoder.encode(label, "UTF-8");
      } catch (UnsupportedEncodingException e) {
      }

      // TODO: Use Album/Artist containers where appropriate. Check "type" field.
      // Container folder = new StorageFolder(url,"0",label,"Me", subCount, storageUsed);
      DIDLObject.Class containerClass;
      if (type == null) type = "";

      type = type.toLowerCase();
      if (type.equals("album")) {
        containerClass = MusicAlbum.CLASS;
      } else if (type.equals("artist")) {
        containerClass = ARTIST_CLASS;
      } else if (type.equals("genre")) {
        containerClass = MusicGenre.CLASS;
      } else {
        containerClass = CONTAINER_CLASS;
      }

      Container folder = new Container(url, "0", label, "System", containerClass, subCount);
      String playlist = obj.optString("playlink");
      if (playlist != null && playlist.length() > 0) {
        MimeType mimeType = new MimeType("audio", "m3u");
        Res res = new Res();
        res.setProtocolInfo(new ProtocolInfo(mimeType));
        res.setValue(playlist);
        folder.addResource(res);

        if (thumbnail != null && thumbnail.length() > 0) {
          try {
            URI uri = new URI(thumbnail);
            ALBUM_ART_URI albumArt = new ALBUM_ART_URI(uri);
            // TODO: DLNA requires xml attribute:
            // dlna:profileID="JPEG_TN" for jpeg thumbnails.
            folder.addProperty(albumArt);
          } catch (URISyntaxException e) {
            Log.w(TAG, "Found album art but bad URI", e);
          }
        }
      }
      didl.addContainer(folder);
    }
  }
  public static MusicTrack jsonToMusicTrack(JSONObject track) {
    String genre = track.optString("genre");
    String album = track.optString("album");
    String creator = track.optString("artist"); // CREATOR; // Required
    String artistStr = track.optString("artist");
    PersonWithRole artist = new PersonWithRole(artistStr, "Performer");
    MimeType mimeType = new MimeType("audio", "mpeg");

    String trackId = track.optString("id");
    if (trackId == null || trackId.length() == 0) {
      trackId = track.optString("path");
    }
    String parentId = "0";
    String trackTitle = track.optString("name");
    String trackUrl = track.optString("download") + "&extension=file.mp3";
    String duration = "";
    String thumbnail = track.optString("image");
    // TODO: bigger image in "thumbnail" (75x75 too small)
    long bitrate = 0;
    long size = 0;
    Integer trackNumber = null;

    if (track.has("metadata")) {
      JSONObject meta = track.optJSONObject("metadata");
      if (meta.has("bitrate")) {
        try {
          double br = Double.parseDouble(meta.getString("bitrate"));
          bitrate = Math.round(br * 128);
        } catch (Exception e) {
        }
      }
      if (meta.has("size")) {
        try {
          double sz = Double.parseDouble(meta.getString("size"));
          size = Math.round(sz * 1024 * 1024);
        } catch (Exception e) {
        }
      }
      if (meta.has("length")) {
        try {
          int len = Integer.parseInt(meta.getString("length"));
          duration += (len / 60);
          len = (len % 60);
          if (len == 0) {
            duration += ":00";
          } else if (len < 10) {
            duration += ":0" + len;
          } else {
            duration += ":" + len;
          }
        } catch (Exception e) {
        }
      }
      if (meta.has("number")) {
        try {
          trackNumber = Integer.parseInt(meta.optString("number"));
        } catch (Exception e) {
        }
      }
    }

    String flagsStr = "01700000000000000000000000000000";
    String network = ProtocolInfo.WILDCARD;
    String additionalInfo =
        "DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=" + flagsStr;

    ProtocolInfo protocolInfo =
        new ProtocolInfo(Protocol.HTTP_GET, network, mimeType.toString(), additionalInfo);
    Res res = new Res(protocolInfo, null /*size*/, trackUrl);
    res.setBitrate(bitrate);
    res.setDuration(duration);

    MusicTrack musicTrack =
        new MusicTrack(trackId, parentId, trackTitle, creator, album, artist, res);

    if (trackNumber != null) {
      musicTrack.setOriginalTrackNumber(trackNumber);
    }
    if (thumbnail != null && thumbnail.length() > 0) {
      try {
        URI uri = new URI(thumbnail);
        ALBUM_ART_URI albumArt = new ALBUM_ART_URI(uri);
        musicTrack.addProperty(albumArt);
      } catch (URISyntaxException e) {
        Log.w(TAG, "Found album art but bad URI", e);
      }
    }
    if (genre != null && genre.length() > 0) {
      GENRE propGenre = new GENRE(genre);
      musicTrack.addProperty(propGenre);
    }

    return musicTrack;
  }