接上篇的setmax.c

/* setmax.c - aeb, 000326 - use on 2.4.0test9 or newer */
/* IBM part thanks to Matan Ziv-Av <matan@svgalib.org> */
/*
 * Results on Maxtor disks:
 * The jumper that clips capacity does not influence the value returned
 * by READ_NATIVE_MAX_ADDRESS, so it is possible to set the jumper
 * and let the kernel, or a utility (like this one) run at boot time
 * restore full capacity.
 * For example, run "setmax -d 0 /dev/hdX" for suitable X.
 * Kernel patches exist that do the same.
 *
 * Results on IBM disks:
 * The jumper that clips capacity is ruthless. You clipped capacity.
 * However, if your BIOS hangs on a large disk, do not use the jumper
 * but find another machine and use a utility (like this one) to
 * clip the non-volatile max address.
 * For example, run "setmax -m 66055248 /dev/hdX" for suitable X.
 * Now go back to your first machine and proceed as with Maxtor drives above.
 */
#include <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/hdreg.h>

#ifndef HDIO_DRIVE_CMD_AEB
#define HDIO_DRIVE_CMD_AEB 0x031e
#endif

#define INITIALIZE_DRIVE_PARAMETERS 0x91
#define READ_NATIVE_MAX_ADDRESS 0xf8
#define CHECK_POWER_MODE 0xe5
#define SET_MAX   0xf9

#define LBA 0x40
#define VV 1  /* if set in sectorct then NOT volatile */

struct idecmdin {
 unsigned char cmd;
 unsigned char feature;
 unsigned char nsect;
 unsigned char sect, lcyl, hcyl;
 unsigned char select;
};

struct idecmdout {
 unsigned char status;
 unsigned char error;
 unsigned char nsect;
 unsigned char sect, lcyl, hcyl;
 unsigned char select;
};

unsigned int
tolba(unsigned char *args) {
 return ((args[6] & 0xf) << 24) + (args[5] << 16) + (args[4] << 8) + args[3];
}

void
fromlba(unsigned char *args, unsigned int lba) {
 args[3] = (lba & 0xff);
 lba >>= 8;
 args[4] = (lba & 0xff);
 lba >>= 8;
 args[5] = (lba & 0xff);
 lba >>= 8;
 args[6] = (args[6] & 0xf0) | (lba & 0xf);
}

int
get_identity(int fd) {
 unsigned char args[4+512] = {WIN_IDENTIFY,0,0,1,};
 struct hd_driveid *id = (struct hd_driveid *)&args[4];

 if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
  perror("HDIO_DRIVE_CMD");
  fprintf(stderr,
   "WIN_IDENTIFY failed - trying WIN_PIDENTIFY/n");
  args[0] = WIN_PIDENTIFY;
  if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
   perror("HDIO_DRIVE_CMD");
   fprintf(stderr,
          "WIN_PIDENTIFY also failed - giving up/n");
   exit(1);
  }
 }

 printf("lba capacity: %d sectors (%lld bytes)/n",
        id->lba_capacity,
        (long long) id->lba_capacity * 512);
}

/*
 * result: in LBA mode precisely what is expected
 *         in CHS mode the correct H and S, and C mod 65536.
 */
unsigned int
get_native_max(int fd, int slave) {
 unsigned char args[7];
 int i, max;

 for (i=0; i<7; i++)
  args[i] = 0;
 args[0] = READ_NATIVE_MAX_ADDRESS;
 args[6] = (slave ? 0x10 : 0) | LBA;
 if (ioctl(fd, HDIO_DRIVE_CMD_AEB, &args)) {
  perror("HDIO_DRIVE_CMD_AEB failed READ_NATIVE_MAX_ADDRESS");
  for (i=0; i<7; i++)
   printf("%d = 0x%x/n", args[i], args[i]);
  exit(1);
 }
 return tolba(args);
}

/*
 * SET_MAX_ADDRESS requires immediately preceding READ_NATIVE_MAX_ADDRESS
 *
 * On old Maxtor disk: this fails for delta <= 254, succeeds for delta >= 255.
 * (So, in order to get the last 255*512=130560 bytes back one has to reboot.
 * Side effect: reset to CurCHS=16383/16/63, CurSects=16514064.)
 * On new Maxtor disk: this works.
 * On IBM disk without jumper: this works.
 */
void
set_max_address(int fd, int slave, int delta, int max, int volat) {
 unsigned char args[7];
 int i, nativemax, newmax;

 nativemax = get_native_max(fd, slave);
 printf("nativemax=%d (0x%x)/n", nativemax, nativemax);

 for (i=0; i<7; i++)
  args[i] = 0;
 args[0] = SET_MAX;
 args[1] = 0;
 args[2] = (volat ? 0 : 1);
 if (delta != -1)
  newmax = nativemax-delta;
 else
  newmax = max-1;
 fromlba(args, newmax);
 args[6] |= LBA;

 if (ioctl(fd, HDIO_DRIVE_CMD_AEB, &args)) {
  perror("HDIO_DRIVE_CMD_AEB failed SET_MAX");
  for (i=0; i<7; i++)
   printf("%d = 0x%x/n", args[i], args[i]);
  exit(1);
 }
}

static char short_opts[] = "d:m:";
static const struct option long_opts[] = {
 { "delta", required_argument, NULL, 'd' },
 { "max", required_argument, NULL, 'm' },
        { NULL, 0, NULL, 0 }
};

static char *usage_txt =
"Call: setmax [-d D] [-m M] DEVICE/n"
"/n"
"The call  /"setmax --max M DEVICE/"  will do a SET_MAX command/n"
"to set the non-volatile max number of accessible sectors to M./n"
"/n"
"The call  /"setmax --delta D DEVICE/"  will do a SET_MAX command/n"
"to set the maximum accessible sector number D sectors/n"
"below end-of-disk./n"
"/n"
"The call  /"setmax DEVICE/"  will do a READ_NATIVE_MAX_ADDRESS/n"
"command, and report the maximum accessible sector number./n"
"/n"
"This is IDE-only. Probably DEVICE is /dev/hdx for some x./n/n";

main(int argc, char **argv){
 int fd, c;
 int delta, max, volat;

 /* If you modify device, also update slave, if necessary. */
 /* The kernel already does this for us since 2.4.0test9. */
 /* master: hda, hdc, hde; slave: hdb, hdd, hdf */
 char *device = NULL; /* e.g. "/dev/hda" */
 int slave = 0;

 delta = max = volat = -1;
 while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) {
  switch(c) {
  case 'd':
   delta = atoi(optarg);
   volat = 1;
   break;
  case 'm':
   max = atoi(optarg);
   volat = 0;
   break;
  case '?':
  default:
   fprintf(stderr, "unknown option/n");
   fprintf(stderr, usage_txt);
   exit(1);
  }
 }

 if (optind < argc)
  device = argv[optind];
 if (!device) {
  fprintf(stderr, "no device specified - "
   "use e.g. /"setmax /dev/hdb/"/n");
  fprintf(stderr, usage_txt);
  exit(1);
 }
 printf("Using device %s/n", device);

 fd = open(device, O_RDONLY);
 if (fd == -1) {
  perror("open");
  exit(1);
 }

 if (delta != -1 || max != -1) {
  if (delta != -1)
   printf("setting delta=%d/n", delta);
  else
   printf("setting max=%d/n", max);
  set_max_address(fd, slave, delta, max, volat);
 } else {
  int mad = get_native_max(fd, slave);
  long long bytes = (long long) (mad+1) * 512;
  int hMB = (bytes+50000000)/100000000;

  printf("native max address: %d/n", mad);
  printf("that is %lld bytes, %d.%d GB/n",
         bytes, hMB/10, hMB%10);
 }
 get_identity(fd);

 return 0;
代码转载自:https://pan.quark.cn/s/a4b39357ea24 本文重点阐述了利用 LabVIEW 软件构建的锁相放大器的设计方案及其具体实施流程,并探讨了该设备在声波相位差定位系统中的实际运用情况。 锁相放大器作为一项基础测量技术,其核心功能在于能够精确锁定微弱信号的频率参数并完成相关测量工作。 在采用 LabVIEW 软件开发的锁相放大器系统中,通过计算测量信号与两条参考信号之间的互相关函数,实现对微弱信号的频率锁定,同时输出被测信号的幅值信息。 虚拟仪器技术是一种基于计算机硬件平台的仪器系统,其显著特征在于用户可以根据实际需求自主设计仪器功能,配备虚拟化操作界面,并将测试功能完全由专用软件程序实现。 虚拟仪器系统的基本架构主要由计算机主机、专用软件程序以及硬件接口模块等核心部件构成。 虚拟仪器最突出的优势在于其功能完全取决于软件编程,用户可以根据具体应用场景灵活调整系统功能参数。 在基于 LabVIEW 软件开发的锁相放大器系统中,主要运用 LabVIEW 软件平台完成锁相放大器功能的整体设计。 LabVIEW 作为一个图形化编程环境,能够高效地完成虚拟仪器的开发工作。 借助 LabVIEW 软件,可以快速构建锁相放大器的用户操作界面,并且可以根据实际需求进行灵活调整和功能扩展。 锁相放大器系统的关键构成要素包括测量信号输入通道、参考信号输入通道、频率锁定处理单元以及信号幅值输出单元。 测量信号是系统需要检测的对象,参考信号则用于引导系统完成对测量信号的频率锁定。 频率锁定处理单元负责实现测量信号的锁定功能,信号幅值输出单元则负责输出被测信号的幅值大小。 在锁相放大器的实际实现过程中,系统采用了双路参考信号输入方案来锁定测量信号。 通过分析两路参考信号之间的相...
<think>我们面临的问题是:`formatMillisecondsToMMSS(player.getDuration())` 返回的字符串可能为负数,导致 `Integer.parseInt(s)` 抛出异常。 分析原因: 1. `player.getDuration()` 返回的是视频总时长(毫秒),正常情况下应为非负数。 2. 但在某些异常情况下(如播放器未准备好、直播流等),可能返回负数(例如 `C.TIME_UNSET` 为 -1 或 -2)。 解决方案思路: 1. 检查 `player.getDuration()` 的返回值,如果是负数,则视为无效,避免解析。 2. 给进度条设置一个默认的最大值(例如0)或根据情况处理。 具体步骤: - 先获取 `player.getDuration()` 的值,存入变量 `long durationMs` - 判断 `durationMs` 是否大于等于0,如果是,则将其转换为分秒格式字符串,再解析为整数(注意:这个整数代表的是秒数?) - 但是,注意:`formatMillisecondsToMMSS` 这个方法返回的字符串格式是 "MM:SS",比如 65 秒会变成 "01:05",我们不能直接对这个字符串使用 `Integer.parseInt`,因为它包含冒号。 问题再分析: 实际上,原代码逻辑有误: ```java String s = formatMillisecondsToMMSS(player.getDuration()); exoProgress.setMax(Integer.parseInt(s)); ``` 这里将格式化的字符串(如"01:05")直接转换成整数,显然会抛出 `NumberFormatException`,因为字符串包含非数字字符。 修正方向: 1. 我们需要的是总秒数(整数)来设置进度条的最大值,而不是将格式化后的字符串转成整数。 2. 所以,应该直接使用 `player.getDuration() / 1000` 得到总秒数(long型),然后转为int(注意范围,但一般视频时长不会超过int最大值)。 因此,正确的做法是: ```java long durationMs = player.getDuration(); // 检查durationMs是否有效(大于等于0) if (durationMs >= 0) { long totalSeconds = durationMs / 1000; // 确保totalSeconds在int范围内 if (totalSeconds <= Integer.MAX_VALUE) { exoProgress.setMax((int) totalSeconds); } else { // 处理超长视频,这里可以设置最大值到Integer.MAX_VALUE,但实际不太可能 exoProgress.setMax(Integer.MAX_VALUE); } } else { // 无效时长,可以设置默认值0,或者不设置(保持之前的最大值),或者根据需求处理 exoProgress.setMax(0); } ``` 但是,注意进度条(`exoProgress`)的类型。如果它是一个 `ProgressBar`,那么最大值应该是一个整数(总秒数)。而进度条当前进度应该是当前播放位置(毫秒)除以1000得到的秒数。 另外,原代码中有一个 `formatMillisecondsToMMSS` 方法,它可能是将毫秒值格式化为 "MM:SS" 的字符串用于显示。所以,这个字符串不应该用于设置进度条的最大值。 总结错误根源: 原代码混淆了显示格式和实际数值。应该用原始数值(毫秒或秒)来设置进度条范围,而格式化字符串仅用于显示时间文本。 修正后的代码逻辑: 1. 获取播放器时长(毫秒)`durationMs`。 2. 如果 `durationMs` 有效(>=0),则计算总秒数 `totalSeconds = durationMs / 1000`,然后设置进度条最大值为 `totalSeconds`(注意int范围)。 3. 如果 `durationMs` 无效,则设置一个默认值(0或之前的值,或者不设置)。 同时,在更新进度的Runnable中,我们也应该使用秒数来设置进度: ```java long position = player.getCurrentPosition(); long positionSeconds = position / 1000; exoProgress.setProgress((int) positionSeconds); ``` 但是,注意:进度条的最大值设置为了总秒数,而进度也是秒数,这样进度条显示正常。 另外,关于之前提到的 `duration`(外部传入)为0时获取总时长,现在我们已经直接使用 `player.getDuration()` 来获取了。 因此,重构后的完整逻辑: 在初始化播放器并准备好后(例如在 `onPlayerStateChanged` 的 `STATE_READY` 状态): ```java long durationMs = player.getDuration(); if (durationMs >= 0) { long totalSeconds = durationMs / 1000; if (totalSeconds > Integer.MAX_VALUE) { exoProgress.setMax(Integer.MAX_VALUE); } else { exoProgress.setMax((int) totalSeconds); } } else { // 无效时长,设置为0,或者可以记录日志,或者使用默认值(比如60秒)? exoProgress.setMax(0); } ``` 在进度更新Runnable中: ```java private final Runnable updateProgress = new Runnable() { @Override public void run() { if (player == null) { return; } long positionMs = player.getCurrentPosition(); long positionSeconds = positionMs / 1000; exoProgress.setProgress((int) positionSeconds); // 检查播放结束:根据外部传入的duration(秒)或者总时长(秒)来判断 long endPositionMs; if (Integer.parseInt(duration) == 0) { // 使用总时长 endPositionMs = player.getDuration(); if (endPositionMs < 0) { // 如果总时长无效,则无法判断结束,所以直接返回 handler.postDelayed(this, 1000); return; } } else { // 外部传入的duration是秒数,转成毫秒 endPositionMs = Integer.parseInt(duration) * 1000L; } if (positionMs >= endPositionMs) { // 播放结束 handler.removeCallbacks(this); onPlaybackComplete(); } else { handler.postDelayed(this, 1000); } } }; ``` 注意:上面代码中,我们使用了 `positionMs` 和 `endPositionMs` 都是毫秒,所以可以直接比较。 但是,进度条设置的最大值是总秒数(整数),而进度也是秒数(整数),这样进度条每一步更新是1秒,对于较短的视频(比如几秒)可能不够平滑。如果希望更平滑,可以以毫秒为单位设置进度条,但最大值可能很大(比如一个两小时视频有7,200,000毫秒),进度条的最大值设置为这么大的整数可能会导致性能问题(但实际测试中一般没问题,因为进度条是整数类型,最大支持到Integer.MAX_VALUE)。或者我们可以将毫秒值除以一个系数(比如100)来设置,这样每一步代表100毫秒,但显示的时候需要转换。 另一种做法:保持进度条的最大值设置为1000(代表百分比),然后根据当前播放位置和总时长的比例来设置进度。但原需求似乎是直接使用时间值(秒)设置进度条。 根据问题,我们主要解决的是字符串解析异常的问题,所以重点在于避免将格式化的字符串(如"01:05")传递给 `Integer.parseInt`。 因此,最终的解决方案是:不要使用 `formatMillisecondsToMMSS` 返回的字符串来设置进度条最大值,而是直接使用毫秒值转换的秒数。 修改后的代码: ```java // 原错误代码 // String s = formatMillisecondsToMMSS(player.getDuration()); // exoProgress.setMax(Integer.parseInt(s)); // 改为: long durationMs = player.getDuration(); if (durationMs >= 0) { long totalSeconds = durationMs / 1000; if (totalSeconds > Integer.MAX_VALUE) { exoProgress.setMax(Integer.MAX_VALUE); } else { exoProgress.setMax((int) totalSeconds); } } else { // 处理无效值,例如设置为0 exoProgress.setMax(0); } ``` 这样,就不会出现将非数字字符串解析为整数的情况,也不会因为负数而解析出错(因为负数已经被过滤)。 另外,关于 `formatMillisecondsToMMSS` 方法的用途,它应该只用于在界面上显示时间文本(比如当前时间和总时间),不要用于进度条数值的设置。 最后,注意:如果播放器返回的时长是负数(例如 `C.TIME_UNSET` 为 -1 或 `C.TIME_END_OF_SOURCE` 为 -2),我们已经过滤,设置进度条最大值为0,表示暂时没有有效时长。 希望这个解决方案能够解决问题。 </think>### 问题分析 在代码 `String s = formatMillisecondsToMMSS(player.getDuration()); exoProgress.setMax(Integer.parseInt(s));` 中,当 `player.getDuration()` 返回负值时,`formatMillisecondsToMMSS()` 生成的字符串可能包含负号(如 "-1"),导致 `Integer.parseInt(s)` 抛出 `NumberFormatException`。 ### 解决方案 以下是优化的处理方法: ```java // 获取原始时长(毫秒) long rawDuration = player.getDuration(); // 处理负值和边界情况 int validDuration; if (rawDuration >= 0) { // 有效时长处理:毫秒转秒 validDuration = (int)(rawDuration / 1000); } else { // 无效时长处理:使用安全默认值 validDuration = 0; // 或根据业务设置默认时长 Log.w(TAG, "Invalid duration: " + rawDuration); } // 直接设置进度条最大值 exoProgress.setMax(validDuration); ``` ### 关键优化说明 1. **绕过字符串转换**: - 直接操作原始毫秒值,避免 `formatMillisecondsToMMSS()` 生成的字符串包含非法字符 - 使用整数除法 `rawDuration / 1000` 将毫秒转为秒 2. **负值安全处理**: ```java if (rawDuration >= 0) { ... } else { ... } ``` 当检测到负值时: - 设置默认值 0 防止崩溃 - 添加日志警告便于调试[^2] 3. **类型安全转换**: ```java (int)(rawDuration / 1000) ``` - 使用显式类型转换避免隐式转换错误 - 除法操作确保获得整型秒数 4. **边界值处理**: ```java if (validDuration > MAX_SAFE_INT) { validDuration = Integer.MAX_VALUE; } ``` 建议添加整型溢出保护(可选) ### 注意事项 1. **播放器状态依赖**: - 直播流可能返回 `C.TIME_UNSET`(-1)或 `C.LENGTH_UNSET`(-),需在播放器 `STATE_READY` 后获取时长[^2] 2. **进度精度处理**: ```java // 毫秒级进度更新 updateRunnable = () -> { long currentMs = player.getCurrentPosition(); int currentSec = (int)(currentMs / 1000); exoProgress.setProgress(currentSec); }; ``` 保持进度条单位(秒)与最大值单位一致 3. **默认值策略**: - 对直播流建议设置为 `Integer.MAX_VALUE` - 点播流可设置默认值 0 或重试获取 ### 相关问题 1. 如何处理播放器在不同状态(缓冲/结束/错误)下的时长获取? 2. 当视频时长超过 `Integer.MAX_VALUE`(约24天)时应如何优化进度条? 3. 如何实现直播流这类无固定时长的进度显示?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值