@Override
  public void displayTracks(String spotifyID, String artistName) {

    if (mTwoPane) {

      Bundle b = new Bundle();
      b.putString(Utils.SPOTIFY_ID, spotifyID);
      b.putString(Utils.ARTIST_NAME, artistName);

      mArtistName = artistName;

      mTrackFragment = new TrackFragment();
      mTrackFragment.setArguments(b);

      getSupportFragmentManager()
          .beginTransaction()
          .replace(R.id.track_fragment_container, mTrackFragment, TRACK_FRAGMENT_TAG)
          .commit();

    } else {

      Intent trackIntent = new Intent(MainActivity.this, TrackActivity.class);
      trackIntent.putExtra(Utils.ARTIST_NAME, artistName);
      trackIntent.putExtra(Utils.SPOTIFY_ID, spotifyID);
      trackIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      startActivity(trackIntent);
    }
  } // displayTracks
Ejemplo n.º 2
0
  private static void parseSaiz(
      TrackEncryptionBox encryptionBox, ParsableByteArray saiz, TrackFragment out)
      throws ParserException {
    int vectorSize = encryptionBox.initializationVectorSize;
    saiz.setPosition(Atom.HEADER_SIZE);
    int fullAtom = saiz.readInt();
    int flags = Atom.parseFullAtomFlags(fullAtom);
    if ((flags & 0x01) == 1) {
      saiz.skipBytes(8);
    }
    int defaultSampleInfoSize = saiz.readUnsignedByte();

    int sampleCount = saiz.readUnsignedIntToInt();
    if (sampleCount != out.length) {
      throw new ParserException("Length mismatch: " + sampleCount + ", " + out.length);
    }

    int totalSize = 0;
    if (defaultSampleInfoSize == 0) {
      boolean[] sampleHasSubsampleEncryptionTable = out.sampleHasSubsampleEncryptionTable;
      for (int i = 0; i < sampleCount; i++) {
        int sampleInfoSize = saiz.readUnsignedByte();
        totalSize += sampleInfoSize;
        sampleHasSubsampleEncryptionTable[i] = sampleInfoSize > vectorSize;
      }
    } else {
      boolean subsampleEncryption = defaultSampleInfoSize > vectorSize;
      totalSize += defaultSampleInfoSize * sampleCount;
      Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
    }
    out.initEncryptionData(totalSize);
  }
Ejemplo n.º 3
0
 private void readEncryptionData(ExtractorInput input) throws IOException, InterruptedException {
   int bytesToSkip = (int) (fragmentRun.auxiliaryDataPosition - input.getPosition());
   checkState(bytesToSkip >= 0, "Offset to encryption data was negative.");
   input.skipFully(bytesToSkip);
   fragmentRun.fillEncryptionData(input);
   parserState = STATE_READING_SAMPLE_START;
 }
Ejemplo n.º 4
0
  private static void parseSenc(ParsableByteArray senc, int offset, TrackFragment out)
      throws ParserException {
    senc.setPosition(Atom.HEADER_SIZE + offset);
    int fullAtom = senc.readInt();
    int flags = Atom.parseFullAtomFlags(fullAtom);

    if ((flags & 0x01 /* override_track_encryption_box_parameters */) != 0) {
      // TODO: Implement this.
      throw new ParserException("Overriding TrackEncryptionBox parameters is unsupported.");
    }

    boolean subsampleEncryption = (flags & 0x02 /* use_subsample_encryption */) != 0;
    int sampleCount = senc.readUnsignedIntToInt();
    if (sampleCount != out.length) {
      throw new ParserException("Length mismatch: " + sampleCount + ", " + out.length);
    }

    Arrays.fill(out.sampleHasSubsampleEncryptionTable, 0, sampleCount, subsampleEncryption);
    out.initEncryptionData(senc.bytesLeft());
    out.fillEncryptionData(senc);
  }
Ejemplo n.º 5
0
  /**
   * Parses a tfhd atom (defined in 14496-12).
   *
   * @param extendsDefaults Default sample values from the trex atom.
   * @param tfhd The tfhd atom to parse.
   * @param out The track fragment to populate with data from the tfhd atom.
   */
  private static void parseTfhd(
      DefaultSampleValues extendsDefaults, ParsableByteArray tfhd, TrackFragment out) {
    tfhd.setPosition(Atom.HEADER_SIZE);
    int fullAtom = tfhd.readInt();
    int flags = Atom.parseFullAtomFlags(fullAtom);

    tfhd.skipBytes(4); // trackId
    if ((flags & 0x01 /* base_data_offset_present */) != 0) {
      long baseDataPosition = tfhd.readUnsignedLongToLong();
      out.dataPosition = baseDataPosition;
      out.auxiliaryDataPosition = baseDataPosition;
    }

    int defaultSampleDescriptionIndex =
        ((flags & 0x02 /* default_sample_description_index_present */) != 0)
            ? tfhd.readUnsignedIntToInt() - 1
            : extendsDefaults.sampleDescriptionIndex;
    int defaultSampleDuration =
        ((flags & 0x08 /* default_sample_duration_present */) != 0)
            ? tfhd.readUnsignedIntToInt()
            : extendsDefaults.duration;
    int defaultSampleSize =
        ((flags & 0x10 /* default_sample_size_present */) != 0)
            ? tfhd.readUnsignedIntToInt()
            : extendsDefaults.size;
    int defaultSampleFlags =
        ((flags & 0x20 /* default_sample_flags_present */) != 0)
            ? tfhd.readUnsignedIntToInt()
            : extendsDefaults.flags;
    out.header =
        new DefaultSampleValues(
            defaultSampleDescriptionIndex,
            defaultSampleDuration,
            defaultSampleSize,
            defaultSampleFlags);
  }
Ejemplo n.º 6
0
  @Nullable
  @Override
  public View onCreateView(
      LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View view = inflater.inflate(R.layout.fragment_schedule, container, false);

    scheduleView = (RecyclerView) view.findViewById(R.id.schedule);
    swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);

    mActivity = getActivity();
    scheduleView.setLayoutManager(new LinearLayoutManager(mActivity));
    scheduleView.setItemAnimator(new DefaultItemAnimator());

    swipeRefreshLayout.setEnabled(false);
    swipeRefreshLayout.post(
        new Runnable() {
          @Override
          public void run() {
            swipeRefreshLayout.setRefreshing(true);
          }
        });

    Call<List<Room>> roomCall = COSCUPClient.get().room();
    roomCall.enqueue(
        new Callback<List<Room>>() {
          @Override
          public void onResponse(Call<List<Room>> call, Response<List<Room>> response) {
            if (response.isSuccessful()) {
              List<Room> rooms = response.body();
              HashMap<String, String> roomMap = new HashMap();
              for (Room room : rooms) {
                roomMap.put(room.getRoom(), room.getName());
              }
              getType(roomMap);
            } else {
              loadOfflineScedule();
            }
          }

          @Override
          public void onFailure(Call<List<Room>> call, Throwable t) {
            loadOfflineScedule();
          }
        });

    return view;
  }
Ejemplo n.º 7
0
 @Override
 public void onCreateContextMenu(
     ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfoIn) {
   if (menuInfoIn == null) return;
   AdapterView.AdapterContextMenuInfo mi = (AdapterView.AdapterContextMenuInfo) menuInfoIn;
   selectedPosition = mi.position;
   adapter.getCursor().moveToPosition(selectedPosition);
   String mimeType =
       adapter
           .getCursor()
           .getString(
               adapter.getCursor().getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.MIME_TYPE));
   if (isSong(mimeType)) {
     super.onCreateContextMenu(menu, view, menuInfoIn);
   }
 }
Ejemplo n.º 8
0
 @Override
 public void onListItemClick(ListView l, View v, int position, long id) {
   selectedPosition = position;
   adapter.getCursor().moveToPosition(selectedPosition);
   String mimeType =
       adapter
           .getCursor()
           .getString(
               adapter.getCursor().getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.MIME_TYPE));
   if ("artist".equals(mimeType)) {
     viewCategory(MusicContract.Artist.getMembersUri(id));
   } else if ("album".equals(mimeType)) {
     viewCategory(MusicContract.Album.getMembersUri(id));
   } else if (isSong(mimeType)) {
     super.onListItemClick(l, v, position, id);
   }
 }
Ejemplo n.º 9
0
  /**
   * Parses a saio atom (defined in 14496-12).
   *
   * @param saio The saio atom to parse.
   * @param out The track fragment to populate with data from the saio atom.
   */
  private static void parseSaio(ParsableByteArray saio, TrackFragment out) throws ParserException {
    saio.setPosition(Atom.HEADER_SIZE);
    int fullAtom = saio.readInt();
    int flags = Atom.parseFullAtomFlags(fullAtom);
    if ((flags & 0x01) == 1) {
      saio.skipBytes(8);
    }

    int entryCount = saio.readUnsignedIntToInt();
    if (entryCount != 1) {
      // We only support one trun element currently, so always expect one entry.
      throw new ParserException("Unexpected saio entry count: " + entryCount);
    }

    int version = Atom.parseFullAtomVersion(fullAtom);
    out.auxiliaryDataPosition +=
        version == 0 ? saio.readUnsignedInt() : saio.readUnsignedLongToLong();
  }
 @Override
 public void onArtistsSearched() {
   if (mTwoPane) {
     mTrackFragment.clearTracks();
   }
 }
Ejemplo n.º 11
0
  /**
   * Attempts to extract the next sample in the current mdat atom.
   *
   * <p>If there are no more samples in the current mdat atom then the parser state is transitioned
   * to {@link #STATE_READING_ATOM_HEADER} and {@code false} is returned.
   *
   * <p>It is possible for a sample to be extracted in part in the case that an exception is thrown.
   * In this case the method can be called again to extract the remainder of the sample.
   *
   * @param input The {@link ExtractorInput} from which to read data.
   * @return True if a sample was extracted. False otherwise.
   * @throws IOException If an error occurs reading from the input.
   * @throws InterruptedException If the thread is interrupted.
   */
  private boolean readSample(ExtractorInput input) throws IOException, InterruptedException {
    if (sampleIndex == 0) {
      int bytesToSkip = (int) (fragmentRun.dataPosition - input.getPosition());
      checkState(bytesToSkip >= 0, "Offset to sample data was negative.");
      input.skipFully(bytesToSkip);
    }

    if (sampleIndex >= fragmentRun.length) {
      int bytesToSkip = (int) (endOfMdatPosition - input.getPosition());
      checkState(bytesToSkip >= 0, "Offset to end of mdat was negative.");
      input.skipFully(bytesToSkip);
      // We've run out of samples in the current mdat atom.
      enterReadingAtomHeaderState();
      return false;
    }

    if (parserState == STATE_READING_SAMPLE_START) {
      sampleSize = fragmentRun.sampleSizeTable[sampleIndex];
      if (fragmentRun.definesEncryptionData) {
        sampleBytesWritten = appendSampleEncryptionData(fragmentRun.sampleEncryptionData);
        sampleSize += sampleBytesWritten;
      } else {
        sampleBytesWritten = 0;
      }
      sampleCurrentNalBytesRemaining = 0;
      parserState = STATE_READING_SAMPLE_CONTINUE;
    }

    if (track.nalUnitLengthFieldLength != -1) {
      // Zero the top three bytes of the array that we'll use to parse nal unit lengths, in case
      // they're only 1 or 2 bytes long.
      byte[] nalLengthData = nalLength.data;
      nalLengthData[0] = 0;
      nalLengthData[1] = 0;
      nalLengthData[2] = 0;
      int nalUnitLengthFieldLength = track.nalUnitLengthFieldLength;
      int nalUnitLengthFieldLengthDiff = 4 - track.nalUnitLengthFieldLength;
      // NAL units are length delimited, but the decoder requires start code delimited units.
      // Loop until we've written the sample to the track output, replacing length delimiters with
      // start codes as we encounter them.
      while (sampleBytesWritten < sampleSize) {
        if (sampleCurrentNalBytesRemaining == 0) {
          // Read the NAL length so that we know where we find the next one.
          input.readFully(nalLength.data, nalUnitLengthFieldLengthDiff, nalUnitLengthFieldLength);
          nalLength.setPosition(0);
          sampleCurrentNalBytesRemaining = nalLength.readUnsignedIntToInt();
          // Write a start code for the current NAL unit.
          nalStartCode.setPosition(0);
          trackOutput.sampleData(nalStartCode, 4);
          sampleBytesWritten += 4;
          sampleSize += nalUnitLengthFieldLengthDiff;
        } else {
          // Write the payload of the NAL unit.
          int writtenBytes = trackOutput.sampleData(input, sampleCurrentNalBytesRemaining, false);
          sampleBytesWritten += writtenBytes;
          sampleCurrentNalBytesRemaining -= writtenBytes;
        }
      }
    } else {
      while (sampleBytesWritten < sampleSize) {
        int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
        sampleBytesWritten += writtenBytes;
      }
    }

    long sampleTimeUs = fragmentRun.getSamplePresentationTime(sampleIndex) * 1000L;
    int sampleFlags =
        (fragmentRun.definesEncryptionData ? C.SAMPLE_FLAG_ENCRYPTED : 0)
            | (fragmentRun.sampleIsSyncFrameTable[sampleIndex] ? C.SAMPLE_FLAG_SYNC : 0);
    int sampleDescriptionIndex = fragmentRun.header.sampleDescriptionIndex;
    byte[] encryptionKey =
        fragmentRun.definesEncryptionData
            ? track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId
            : null;
    trackOutput.sampleMetadata(sampleTimeUs, sampleFlags, sampleSize, 0, encryptionKey);

    sampleIndex++;
    parserState = STATE_READING_SAMPLE_START;
    return true;
  }
Ejemplo n.º 12
0
  /**
   * Parses a trun atom (defined in 14496-12).
   *
   * @param track The corresponding track.
   * @param defaultSampleValues Default sample values.
   * @param decodeTime The decode time.
   * @param trun The trun atom to parse.
   * @param out The {@TrackFragment} into which parsed data should be placed.
   */
  private static void parseTrun(
      Track track,
      DefaultSampleValues defaultSampleValues,
      long decodeTime,
      int workaroundFlags,
      ParsableByteArray trun,
      TrackFragment out) {
    trun.setPosition(Atom.HEADER_SIZE);
    int fullAtom = trun.readInt();
    int flags = Atom.parseFullAtomFlags(fullAtom);

    int sampleCount = trun.readUnsignedIntToInt();
    if ((flags & 0x01 /* data_offset_present */) != 0) {
      out.dataPosition += trun.readInt();
    }

    boolean firstSampleFlagsPresent = (flags & 0x04 /* first_sample_flags_present */) != 0;
    int firstSampleFlags = defaultSampleValues.flags;
    if (firstSampleFlagsPresent) {
      firstSampleFlags = trun.readUnsignedIntToInt();
    }

    boolean sampleDurationsPresent = (flags & 0x100 /* sample_duration_present */) != 0;
    boolean sampleSizesPresent = (flags & 0x200 /* sample_size_present */) != 0;
    boolean sampleFlagsPresent = (flags & 0x400 /* sample_flags_present */) != 0;
    boolean sampleCompositionTimeOffsetsPresent =
        (flags & 0x800 /* sample_composition_time_offsets_present */) != 0;

    out.initTables(sampleCount);
    int[] sampleSizeTable = out.sampleSizeTable;
    int[] sampleCompositionTimeOffsetTable = out.sampleCompositionTimeOffsetTable;
    long[] sampleDecodingTimeTable = out.sampleDecodingTimeTable;
    boolean[] sampleIsSyncFrameTable = out.sampleIsSyncFrameTable;

    long timescale = track.timescale;
    long cumulativeTime = decodeTime;
    boolean workaroundEveryVideoFrameIsSyncFrame =
        track.type == Track.TYPE_vide
            && (workaroundFlags & WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME) != 0;
    for (int i = 0; i < sampleCount; i++) {
      // Use trun values if present, otherwise tfhd, otherwise trex.
      int sampleDuration =
          sampleDurationsPresent ? trun.readUnsignedIntToInt() : defaultSampleValues.duration;
      int sampleSize = sampleSizesPresent ? trun.readUnsignedIntToInt() : defaultSampleValues.size;
      int sampleFlags =
          (i == 0 && firstSampleFlagsPresent)
              ? firstSampleFlags
              : sampleFlagsPresent ? trun.readInt() : defaultSampleValues.flags;
      if (sampleCompositionTimeOffsetsPresent) {
        // The BMFF spec (ISO 14496-12) states that sample offsets should be unsigned integers in
        // version 0 trun boxes, however a significant number of streams violate the spec and use
        // signed integers instead. It's safe to always parse sample offsets as signed integers
        // here, because unsigned integers will still be parsed correctly (unless their top bit is
        // set, which is never true in practice because sample offsets are always small).
        int sampleOffset = trun.readInt();
        sampleCompositionTimeOffsetTable[i] = (int) ((sampleOffset * 1000) / timescale);
      } else {
        sampleCompositionTimeOffsetTable[i] = 0;
      }
      sampleDecodingTimeTable[i] = Util.scaleLargeTimestamp(cumulativeTime, 1000, timescale);
      sampleSizeTable[i] = sampleSize;
      sampleIsSyncFrameTable[i] =
          ((sampleFlags >> 16) & 0x1) == 0 && (!workaroundEveryVideoFrameIsSyncFrame || i == 0);
      cumulativeTime += sampleDuration;
    }
  }
Ejemplo n.º 13
0
 private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException {
   fragmentRun.reset();
   parseMoof(track, extendsDefaults, moof, fragmentRun, workaroundFlags, extendedTypeScratch);
   sampleIndex = 0;
 }
Ejemplo n.º 14
0
  private boolean readAtomHeader(ExtractorInput input) throws IOException, InterruptedException {
    if (atomHeaderBytesRead == 0) {
      // Read the standard length atom header.
      if (!input.readFully(atomHeader.data, 0, Atom.HEADER_SIZE, true)) {
        return false;
      }
      atomHeaderBytesRead = Atom.HEADER_SIZE;
      atomHeader.setPosition(0);
      atomSize = atomHeader.readUnsignedInt();
      atomType = atomHeader.readInt();
    }

    if (atomSize == Atom.LONG_SIZE_PREFIX) {
      // Read the extended atom size.
      int headerBytesRemaining = Atom.LONG_HEADER_SIZE - Atom.HEADER_SIZE;
      input.readFully(atomHeader.data, Atom.HEADER_SIZE, headerBytesRemaining);
      atomHeaderBytesRead += headerBytesRemaining;
      atomSize = atomHeader.readUnsignedLongToLong();
    }

    long atomPosition = input.getPosition() - atomHeaderBytesRead;
    if (atomType == Atom.TYPE_moof) {
      // The data positions may be updated when parsing the tfhd/trun.
      fragmentRun.auxiliaryDataPosition = atomPosition;
      fragmentRun.dataPosition = atomPosition;
    }

    if (atomType == Atom.TYPE_mdat) {
      endOfMdatPosition = atomPosition + atomSize;
      if (!haveOutputSeekMap) {
        extractorOutput.seekMap(SeekMap.UNSEEKABLE);
        haveOutputSeekMap = true;
      }
      if (fragmentRun.sampleEncryptionDataNeedsFill) {
        parserState = STATE_READING_ENCRYPTION_DATA;
      } else {
        parserState = STATE_READING_SAMPLE_START;
      }
      return true;
    }

    if (shouldParseContainerAtom(atomType)) {
      long endPosition = input.getPosition() + atomSize - Atom.HEADER_SIZE;
      containerAtoms.add(new ContainerAtom(atomType, endPosition));
      enterReadingAtomHeaderState();
    } else if (shouldParseLeafAtom(atomType)) {
      // We don't support parsing of leaf atoms that define extended atom sizes, or that have
      // lengths greater than Integer.MAX_VALUE.
      checkState(atomHeaderBytesRead == Atom.HEADER_SIZE);
      checkState(atomSize <= Integer.MAX_VALUE);
      atomData = new ParsableByteArray((int) atomSize);
      System.arraycopy(atomHeader.data, 0, atomData.data, 0, Atom.HEADER_SIZE);
      parserState = STATE_READING_ATOM_PAYLOAD;
    } else {
      // We don't support skipping of atoms that have lengths greater than Integer.MAX_VALUE.
      checkState(atomSize <= Integer.MAX_VALUE);
      atomData = null;
      parserState = STATE_READING_ATOM_PAYLOAD;
    }

    return true;
  }